diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000000000000000000000000000000000000..ea5b04aebe68d28008ed1a644c50cf025f8258fd
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,7 @@
+**/node_modules
+**/coverage
+test/fixtures
+build/
+docs/
+protos/
+samples/generated/
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..782153495464fafd12f23ed5228685b37d6acff5
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+  "extends": "./node_modules/gts"
+}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..33739cb74e44862f497d6b8e0aa4ded51e2ec906
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,4 @@
+*.ts text eol=lf
+*.js text eol=lf
+protos/* linguist-generated
+**/api-extractor.json  linguist-language=JSON-with-Comments
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f3ca5561cb5e322451b338af3f4bb09ad3d0fb39
--- /dev/null
+++ b/.github/.OwlBot.lock.yaml
@@ -0,0 +1,17 @@
+# Copyright 2022 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.
+docker:
+  image: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest
+  digest: sha256:ddb19a6df6c1fa081bc99fb29658f306dd64668bc26f75d1353b28296f3a78e6
+# created: 2022-06-07T21:18:30.024751809Z
diff --git a/.github/.OwlBot.yaml b/.github/.OwlBot.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..459370d51473f1a15815f9004fbef484bbad0427
--- /dev/null
+++ b/.github/.OwlBot.yaml
@@ -0,0 +1,23 @@
+# Copyright 2021 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.
+docker:
+  image: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest
+
+deep-remove-regex:
+  - /owl-bot-staging
+
+deep-copy-regex:
+  - source: /google/cloud/iot/(.*)/.*-nodejs/(.*)
+    dest: /owl-bot-staging/$1/$2
+
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000000000000000000000000000000000000..1cf45a29771ef1f2040a94685549f569cc00a53c
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,12 @@
+# Code owners file.
+# This file controls who is tagged for review for any given pull request.
+#
+# For syntax help see:
+# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax
+
+
+# The yoshi-nodejs team is the default owner for nodejs repositories.
+*     @googleapis/yoshi-nodejs @googleapis/api-iot
+
+# The github automation team is the default owner for the auto-approve file.
+.github/auto-approve.yml @googleapis/github-automation
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000000000000000000000000000000000000..6c2ef89ab025e2a6b7bba277c6bcef638958a5d9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,38 @@
+---
+name: Bug report
+about: Create a report to help us improve
+labels: 'type: bug, priority: p2'
+---
+
+Thanks for stopping by to let us know something could be better!
+
+**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response.
+
+1) Is this a client library issue or a product issue?
+This is the client library for . We will only be able to assist with issues that pertain to the behaviors of this library. If the issue you're experiencing is due to the behavior of the product itself, please visit the [ Support page]() to reach the most relevant engineers.
+
+2) Did someone already solve this?
+  - Search the issues already opened: https://github.com/googleapis/nodejs-iot/issues
+  - Search the issues on our "catch-all" repository: https://github.com/googleapis/google-cloud-node
+  - Search or ask on StackOverflow (engineers monitor these tags): http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js
+
+3) Do you have a support contract?
+Please create an issue in the [support console](https://cloud.google.com/support/) to ensure a timely response.
+
+If the support paths suggested above still do not result in a resolution, please provide the following details.
+
+#### Environment details
+
+  - OS:
+  - Node.js version:
+  - npm version:
+  - `@google-cloud/iot` version:
+
+#### Steps to reproduce
+
+  1. ?
+  2. ?
+
+Making sure to follow these steps will guarantee the quickest resolution possible.
+
+Thanks!
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..603b90133b62a02e6f63fa30d95e5f2b04bb526d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,4 @@
+contact_links:
+  - name: Google Cloud Support
+    url: https://cloud.google.com/support/
+    about: If you have a support contract with Google, please use the Google Cloud Support portal.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..b0327dfa02e7a4c5de8321dd4c8ceedd58c7fd43
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,18 @@
+---
+name: Feature request
+about: Suggest an idea for this library
+labels: 'type: feature request, priority: p3'
+---
+
+Thanks for stopping by to let us know something could be better!
+
+**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response.
+
+ **Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+ **Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+ **Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+ **Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
new file mode 100644
index 0000000000000000000000000000000000000000..97323113911ef653725e1dc0a4d89b0d3b4388da
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -0,0 +1,12 @@
+---
+name: Question
+about: Ask a question
+labels: 'type: question, priority: p3'
+---
+
+Thanks for stopping by to ask us a question! Please make sure to include:
+- What you're trying to do
+- What code you've already tried
+- Any error messages you're getting
+
+**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response.
diff --git a/.github/ISSUE_TEMPLATE/support_request.md b/.github/ISSUE_TEMPLATE/support_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..995869032125fb2e0d6830a2898ea07e0c061499
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/support_request.md
@@ -0,0 +1,7 @@
+---
+name: Support request
+about: If you have a support contract with Google, please create an issue in the Google Cloud Support console.
+
+---
+
+**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000000000000000000000000000000000..f0f897228cfff125ef9555d603adc239ca824cda
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,7 @@
+Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
+- [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/nodejs-iot/issues/new/choose) before writing your code!  That way we can discuss the change, evaluate designs, and agree on the general idea
+- [ ] Ensure the tests and linter pass
+- [ ] Code coverage does not decrease (if any source code was changed)
+- [ ] Appropriate docs were updated (if necessary)
+
+Fixes #<issue_number_goes_here> 🦕
diff --git a/.github/auto-approve.yml b/.github/auto-approve.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4cd91cc16ae278e19ab219e9953e1f0c2b18eb86
--- /dev/null
+++ b/.github/auto-approve.yml
@@ -0,0 +1,3 @@
+processes:
+  - "NodeDependency"
+  - "OwlBotTemplateChanges"
diff --git a/.github/auto-label.yaml b/.github/auto-label.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..09c8d735b456a85811aeaada642755f6e13076f5
--- /dev/null
+++ b/.github/auto-label.yaml
@@ -0,0 +1,2 @@
+requestsize:
+  enabled: true
diff --git a/.github/blunderbuss.yml b/.github/blunderbuss.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b81168c79e13dd3abaa82672ad463f7f3cc9783e
--- /dev/null
+++ b/.github/blunderbuss.yml
@@ -0,0 +1,13 @@
+assign_issues_by:
+- labels:
+  - 'api: cloudiot'
+  to:
+  - simoncsaba-g
+  - laszlokorossy
+
+assign_prs_by:
+- labels:
+  - 'api: cloudiot'
+  to:
+  - simoncsaba-g
+  - laszlokorossy
diff --git a/.github/generated-files-bot.yml b/.github/generated-files-bot.yml
new file mode 100644
index 0000000000000000000000000000000000000000..992ccef4a131315142795d130f237d4754eb6ac3
--- /dev/null
+++ b/.github/generated-files-bot.yml
@@ -0,0 +1,16 @@
+generatedFiles:
+- path: '.kokoro/**'
+  message: '`.kokoro` files are templated and should be updated in [`synthtool`](https://github.com/googleapis/synthtool)'
+- path: '.github/CODEOWNERS'
+  message: 'CODEOWNERS should instead be modified via the `codeowner_team` property in .repo-metadata.json'
+- path: '.github/workflows/ci.yaml'
+  message: '`.github/workflows/ci.yaml` (GitHub Actions) should be updated in [`synthtool`](https://github.com/googleapis/synthtool)'
+- path: '.github/generated-files-bot.+(yml|yaml)'
+  message: '`.github/generated-files-bot.(yml|yaml)` should be updated in [`synthtool`](https://github.com/googleapis/synthtool)'
+- path: 'README.md'
+  message: '`README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml'
+- path: 'samples/README.md'
+  message: '`samples/README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml'
+ignoreAuthors:
+- 'gcf-owl-bot[bot]'
+- 'yoshi-automation'
diff --git a/.github/release-please.yml b/.github/release-please.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a1b41da3cb36492473eebd3fe94c4b89460f1a15
--- /dev/null
+++ b/.github/release-please.yml
@@ -0,0 +1,2 @@
+handleGHRelease: true
+releaseType: node
diff --git a/.github/release-trigger.yml b/.github/release-trigger.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d4ca94189e160a70677ece805ad0cadcaf7edfd5
--- /dev/null
+++ b/.github/release-trigger.yml
@@ -0,0 +1 @@
+enabled: true
diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4a30a08e54cfb762f8ce0c57943e368c6d39324e
--- /dev/null
+++ b/.github/sync-repo-settings.yaml
@@ -0,0 +1,24 @@
+branchProtectionRules:
+  - pattern: main
+    isAdminEnforced: true
+    requiredApprovingReviewCount: 1
+    requiresCodeOwnerReviews: true
+    requiresStrictStatusChecks: true
+    requiredStatusCheckContexts:
+      - "ci/kokoro: Samples test"
+      - "ci/kokoro: System test"
+      - docs
+      - lint
+      - test (12)
+      - test (14)
+      - test (16)
+      - cla/google
+      - windows
+      - OwlBot Post Processor
+permissionRules:
+  - team: yoshi-admins
+    permission: admin
+  - team: jsteam-admins
+    permission: admin
+  - team: jsteam
+    permission: push
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f447b84abed6db7a9a024958faba89a67908131d
--- /dev/null
+++ b/.github/workflows/ci.yaml
@@ -0,0 +1,60 @@
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+name: ci
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        node: [12, 14, 16]
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
+        with:
+          node-version: ${{ matrix.node }}
+      - run: node --version
+      # The first installation step ensures that all of our production
+      # dependencies work on the given Node.js version, this helps us find
+      # dependencies that don't match our engines field:
+      - run: npm install --production --engine-strict --ignore-scripts --no-package-lock
+      # Clean up the production install, before installing dev/production:
+      - run: rm -rf node_modules
+      - run: npm install
+      - run: npm test
+        env:
+          MOCHA_THROW_DEPRECATION: false
+  windows:
+    runs-on: windows-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 14
+      - run: npm install
+      - run: npm test
+        env:
+          MOCHA_THROW_DEPRECATION: false
+  lint:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 14
+      - run: npm install
+      - run: npm run lint
+  docs:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 14
+      - run: npm install
+      - run: npm run docs
+      - uses: JustinBeckwith/linkinator-action@v1
+        with:
+          paths: docs/
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5d32b23782f34a8a4d9f83ec4075bbb95cd9858a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+**/*.log
+**/node_modules
+.coverage
+coverage
+.nyc_output
+docs/
+out/
+build/
+system-test/secrets.js
+system-test/*key.json
+*.lock
+.DS_Store
+package-lock.json
+__pycache__
diff --git a/.jsdoc.js b/.jsdoc.js
new file mode 100644
index 0000000000000000000000000000000000000000..99b19cfa65a8d784a697b63819ccd07e5119adf9
--- /dev/null
+++ b/.jsdoc.js
@@ -0,0 +1,55 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+'use strict';
+
+module.exports = {
+  opts: {
+    readme: './README.md',
+    package: './package.json',
+    template: './node_modules/jsdoc-fresh',
+    recurse: true,
+    verbose: true,
+    destination: './docs/'
+  },
+  plugins: [
+    'plugins/markdown',
+    'jsdoc-region-tag'
+  ],
+  source: {
+    excludePattern: '(^|\\/|\\\\)[._]',
+    include: [
+      'build/src',
+      'protos'
+    ],
+    includePattern: '\\.js$'
+  },
+  templates: {
+    copyright: 'Copyright 2022 Google LLC',
+    includeDate: false,
+    sourceFiles: false,
+    systemName: '@google-cloud/iot',
+    theme: 'lumen',
+    default: {
+      outputSourceFiles: false
+    }
+  },
+  markdown: {
+    idInHeadings: true
+  }
+};
diff --git a/.kokoro/.gitattributes b/.kokoro/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..87acd4f484eef3f4d1703deeee61eac213682058
--- /dev/null
+++ b/.kokoro/.gitattributes
@@ -0,0 +1 @@
+* linguist-generated=true
diff --git a/.kokoro/common.cfg b/.kokoro/common.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..fc055132d22f311dd77a1b63b2c145409aff045e
--- /dev/null
+++ b/.kokoro/common.cfg
@@ -0,0 +1,24 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build logs will be here
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.xml"
+  }
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "nodejs-iot/.kokoro/trampoline_v2.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+    key: "TRAMPOLINE_IMAGE"
+    value: "gcr.io/cloud-devrel-kokoro-resources/node:12-user"
+}
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/test.sh"
+}
diff --git a/.kokoro/continuous/node12/common.cfg b/.kokoro/continuous/node12/common.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..fc055132d22f311dd77a1b63b2c145409aff045e
--- /dev/null
+++ b/.kokoro/continuous/node12/common.cfg
@@ -0,0 +1,24 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build logs will be here
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.xml"
+  }
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "nodejs-iot/.kokoro/trampoline_v2.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+    key: "TRAMPOLINE_IMAGE"
+    value: "gcr.io/cloud-devrel-kokoro-resources/node:12-user"
+}
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/test.sh"
+}
diff --git a/.kokoro/continuous/node12/lint.cfg b/.kokoro/continuous/node12/lint.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..795b532056cf0e562aa9a58de2c6a5caeed1c3fc
--- /dev/null
+++ b/.kokoro/continuous/node12/lint.cfg
@@ -0,0 +1,4 @@
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/lint.sh"
+}
diff --git a/.kokoro/continuous/node12/samples-test.cfg b/.kokoro/continuous/node12/samples-test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..a05b920b25ca7132f31c8fee70390954fe27ee60
--- /dev/null
+++ b/.kokoro/continuous/node12/samples-test.cfg
@@ -0,0 +1,7 @@
+# Download resources for system tests (service account key, etc.)
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs"
+
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/samples-test.sh"
+}
diff --git a/.kokoro/continuous/node12/system-test.cfg b/.kokoro/continuous/node12/system-test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..50f37d032fbb7b4d6eccf67079221ed13ebcc206
--- /dev/null
+++ b/.kokoro/continuous/node12/system-test.cfg
@@ -0,0 +1,7 @@
+# Download resources for system tests (service account key, etc.)
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs"
+
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/system-test.sh"
+}
diff --git a/.kokoro/continuous/node12/test.cfg b/.kokoro/continuous/node12/test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.kokoro/docs.sh b/.kokoro/docs.sh
new file mode 100644
index 0000000000000000000000000000000000000000..85901242b5ee377969c88f47046b98c9e92cf0bb
--- /dev/null
+++ b/.kokoro/docs.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# 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
+#
+#     https://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.
+
+set -eo pipefail
+
+export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+
+cd $(dirname $0)/..
+
+npm install
+
+npm run docs-test
diff --git a/.kokoro/lint.sh b/.kokoro/lint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..aef4866e4c40764399b1de9369786cbb55704aea
--- /dev/null
+++ b/.kokoro/lint.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# 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
+#
+#     https://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.
+
+set -eo pipefail
+
+export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+
+cd $(dirname $0)/..
+
+npm install
+
+# Install and link samples
+if [ -f samples/package.json ]; then
+  cd samples/
+  npm link ../
+  npm install
+  cd ..
+fi
+
+npm run lint
diff --git a/.kokoro/populate-secrets.sh b/.kokoro/populate-secrets.sh
new file mode 100644
index 0000000000000000000000000000000000000000..deb2b199eb4c5456c61c2f9b445e6d32ab93230e
--- /dev/null
+++ b/.kokoro/populate-secrets.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+# Copyright 2020 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.
+
+# This file is called in the early stage of `trampoline_v2.sh` to
+# populate secrets needed for the CI builds.
+
+set -eo pipefail
+
+function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;}
+function msg { println "$*" >&2 ;}
+function println { printf '%s\n' "$(now) $*" ;}
+
+# Populates requested secrets set in SECRET_MANAGER_KEYS
+
+# In Kokoro CI builds, we use the service account attached to the
+# Kokoro VM. This means we need to setup auth on other CI systems.
+# For local run, we just use the gcloud command for retrieving the
+# secrets.
+
+if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then
+    GCLOUD_COMMANDS=(
+	"docker"
+	"run"
+	"--entrypoint=gcloud"
+	"--volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR}"
+	"gcr.io/google.com/cloudsdktool/cloud-sdk"
+    )
+    if [[ "${TRAMPOLINE_CI:-}" == "kokoro" ]]; then
+	SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager"
+    else
+	echo "Authentication for this CI system is not implemented yet."
+	exit 2
+	# TODO: Determine appropriate SECRET_LOCATION and the GCLOUD_COMMANDS.
+    fi
+else
+    # For local run, use /dev/shm or temporary directory for
+    # KOKORO_GFILE_DIR.
+    if [[ -d "/dev/shm" ]]; then
+	export KOKORO_GFILE_DIR=/dev/shm
+    else
+	export KOKORO_GFILE_DIR=$(mktemp -d -t ci-XXXXXXXX)
+    fi
+    SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager"
+    GCLOUD_COMMANDS=("gcloud")
+fi
+
+msg "Creating folder on disk for secrets: ${SECRET_LOCATION}"
+mkdir -p ${SECRET_LOCATION}
+
+for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g")
+do
+    msg "Retrieving secret ${key}"
+    "${GCLOUD_COMMANDS[@]}" \
+	secrets versions access latest \
+	--project cloud-devrel-kokoro-resources \
+	--secret $key > \
+	"$SECRET_LOCATION/$key"
+    if [[ $? == 0 ]]; then
+	msg "Secret written to ${SECRET_LOCATION}/${key}"
+    else
+	msg "Error retrieving secret ${key}"
+	exit 2
+    fi
+done
diff --git a/.kokoro/presubmit/node12/common.cfg b/.kokoro/presubmit/node12/common.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..fc055132d22f311dd77a1b63b2c145409aff045e
--- /dev/null
+++ b/.kokoro/presubmit/node12/common.cfg
@@ -0,0 +1,24 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+# Build logs will be here
+action {
+  define_artifacts {
+    regex: "**/*sponge_log.xml"
+  }
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "nodejs-iot/.kokoro/trampoline_v2.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+    key: "TRAMPOLINE_IMAGE"
+    value: "gcr.io/cloud-devrel-kokoro-resources/node:12-user"
+}
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/test.sh"
+}
diff --git a/.kokoro/presubmit/node12/samples-test.cfg b/.kokoro/presubmit/node12/samples-test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..a05b920b25ca7132f31c8fee70390954fe27ee60
--- /dev/null
+++ b/.kokoro/presubmit/node12/samples-test.cfg
@@ -0,0 +1,7 @@
+# Download resources for system tests (service account key, etc.)
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs"
+
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/samples-test.sh"
+}
diff --git a/.kokoro/presubmit/node12/system-test.cfg b/.kokoro/presubmit/node12/system-test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..50f37d032fbb7b4d6eccf67079221ed13ebcc206
--- /dev/null
+++ b/.kokoro/presubmit/node12/system-test.cfg
@@ -0,0 +1,7 @@
+# Download resources for system tests (service account key, etc.)
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs"
+
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/system-test.sh"
+}
diff --git a/.kokoro/presubmit/node12/test.cfg b/.kokoro/presubmit/node12/test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.kokoro/presubmit/windows/common.cfg b/.kokoro/presubmit/windows/common.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..d6e25e0b1b8e1326666bff681406e3d470b4d626
--- /dev/null
+++ b/.kokoro/presubmit/windows/common.cfg
@@ -0,0 +1,2 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
diff --git a/.kokoro/presubmit/windows/test.cfg b/.kokoro/presubmit/windows/test.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..ce97a8f6e4350f759fa1375b437e78c2295dc878
--- /dev/null
+++ b/.kokoro/presubmit/windows/test.cfg
@@ -0,0 +1,2 @@
+# Use the test file directly
+build_file: "nodejs-iot/.kokoro/test.bat"
diff --git a/.kokoro/publish.sh b/.kokoro/publish.sh
new file mode 100644
index 0000000000000000000000000000000000000000..77a5defb2b54453b0fcdb2dc115eb66c20de5ece
--- /dev/null
+++ b/.kokoro/publish.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# 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
+#
+#     https://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.
+
+set -eo pipefail
+
+export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+
+# Start the releasetool reporter
+python3 -m pip install gcp-releasetool
+python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script
+
+cd $(dirname $0)/..
+
+NPM_TOKEN=$(cat $KOKORO_KEYSTORE_DIR/73713_google-cloud-npm-token-1)
+echo "//wombat-dressing-room.appspot.com/:_authToken=${NPM_TOKEN}" > ~/.npmrc
+
+npm install
+npm publish --access=public --registry=https://wombat-dressing-room.appspot.com
diff --git a/.kokoro/release/common.cfg b/.kokoro/release/common.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..3ba2eb095fe1c0308dfe8ed801701c9e8002bc05
--- /dev/null
+++ b/.kokoro/release/common.cfg
@@ -0,0 +1,8 @@
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 73713
+      keyname: "yoshi-automation-github-key"
+    }
+  }
+}
diff --git a/.kokoro/release/docs-devsite.cfg b/.kokoro/release/docs-devsite.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..788d1699542b4ad0de4f292d1be42d148b869d0e
--- /dev/null
+++ b/.kokoro/release/docs-devsite.cfg
@@ -0,0 +1,26 @@
+# service account used to publish up-to-date docs.
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 73713
+      keyname: "docuploader_service_account"
+    }
+  }
+}
+
+# doc publications use a Python image.
+env_vars: {
+    key: "TRAMPOLINE_IMAGE"
+    value: "gcr.io/cloud-devrel-kokoro-resources/node:14-user"
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "nodejs-iot/.kokoro/trampoline_v2.sh"
+
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/release/docs-devsite.sh"
+}
diff --git a/.kokoro/release/docs-devsite.sh b/.kokoro/release/docs-devsite.sh
new file mode 100644
index 0000000000000000000000000000000000000000..2198e67fe924f6c04cb97b634efd7d2504cd5c12
--- /dev/null
+++ b/.kokoro/release/docs-devsite.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# Copyright 2021 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
+#
+#     https://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.
+
+set -eo pipefail
+
+if [[ -z "$CREDENTIALS" ]]; then
+  # if CREDENTIALS are explicitly set, assume we're testing locally
+  # and don't set NPM_CONFIG_PREFIX.
+  export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+  export PATH="$PATH:${NPM_CONFIG_PREFIX}/bin"
+  cd $(dirname $0)/../..
+fi
+
+npm install
+npm install --no-save @google-cloud/cloud-rad@^0.2.5
+npx @google-cloud/cloud-rad
\ No newline at end of file
diff --git a/.kokoro/release/docs.cfg b/.kokoro/release/docs.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..df310653bd37dc50e4e05402413a0072b3bf9e1e
--- /dev/null
+++ b/.kokoro/release/docs.cfg
@@ -0,0 +1,26 @@
+# service account used to publish up-to-date docs.
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 73713
+      keyname: "docuploader_service_account"
+    }
+  }
+}
+
+# doc publications use a Python image.
+env_vars: {
+    key: "TRAMPOLINE_IMAGE"
+    value: "gcr.io/cloud-devrel-kokoro-resources/node:12-user"
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "nodejs-iot/.kokoro/trampoline_v2.sh"
+
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/release/docs.sh"
+}
diff --git a/.kokoro/release/docs.sh b/.kokoro/release/docs.sh
new file mode 100644
index 0000000000000000000000000000000000000000..4c866c86000e32226e4b5fb282099fa83157fc00
--- /dev/null
+++ b/.kokoro/release/docs.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# Copyright 2019 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
+#
+#     https://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.
+
+set -eo pipefail
+
+# build jsdocs (Python is installed on the Node 10 docker image).
+if [[ -z "$CREDENTIALS" ]]; then
+  # if CREDENTIALS are explicitly set, assume we're testing locally
+  # and don't set NPM_CONFIG_PREFIX.
+  export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+  export PATH="$PATH:${NPM_CONFIG_PREFIX}/bin"
+  cd $(dirname $0)/../..
+fi
+npm install
+npm run docs
+
+# create docs.metadata, based on package.json and .repo-metadata.json.
+npm i json@9.0.6 -g
+python3 -m pip install --user gcp-docuploader
+python3 -m docuploader create-metadata \
+  --name=$(cat .repo-metadata.json | json name) \
+  --version=$(cat package.json | json version) \
+  --language=$(cat .repo-metadata.json | json language) \
+  --distribution-name=$(cat .repo-metadata.json | json distribution_name) \
+  --product-page=$(cat .repo-metadata.json | json product_documentation) \
+  --github-repository=$(cat .repo-metadata.json | json repo) \
+  --issue-tracker=$(cat .repo-metadata.json | json issue_tracker)
+cp docs.metadata ./docs/docs.metadata
+
+# deploy the docs.
+if [[ -z "$CREDENTIALS" ]]; then
+  CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account
+fi
+if [[ -z "$BUCKET" ]]; then
+  BUCKET=docs-staging
+fi
+python3 -m docuploader upload ./docs --credentials $CREDENTIALS --staging-bucket $BUCKET
diff --git a/.kokoro/release/publish.cfg b/.kokoro/release/publish.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..6b4ffcf14aaf311aeb7f37609f812764362e1d87
--- /dev/null
+++ b/.kokoro/release/publish.cfg
@@ -0,0 +1,39 @@
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 73713
+      keyname: "docuploader_service_account"
+    }
+  }
+}
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 73713
+      keyname: "google-cloud-npm-token-1"
+    }
+  }
+}
+
+env_vars: {
+  key: "SECRET_MANAGER_KEYS"
+  value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem"
+}
+
+# Download trampoline resources.
+gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
+
+# Use the trampoline script to run in docker.
+build_file: "nodejs-iot/.kokoro/trampoline_v2.sh"
+
+# Configure the docker image for kokoro-trampoline.
+env_vars: {
+    key: "TRAMPOLINE_IMAGE"
+    value: "gcr.io/cloud-devrel-kokoro-resources/node:12-user"
+}
+
+env_vars: {
+    key: "TRAMPOLINE_BUILD_FILE"
+    value: "github/nodejs-iot/.kokoro/publish.sh"
+}
diff --git a/.kokoro/samples-test.sh b/.kokoro/samples-test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..fbc058a4ec4f4e43bac8c4647f1b831465fa670c
--- /dev/null
+++ b/.kokoro/samples-test.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+# 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
+#
+#     https://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.
+
+set -eo pipefail
+
+export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+
+# Setup service account credentials.
+export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json
+export GCLOUD_PROJECT=long-door-651
+
+cd $(dirname $0)/..
+
+# Run a pre-test hook, if a pre-samples-test.sh is in the project
+if [ -f .kokoro/pre-samples-test.sh ]; then
+    set +x
+    . .kokoro/pre-samples-test.sh
+    set -x
+fi
+
+if [ -f samples/package.json ]; then
+    npm install
+
+    # Install and link samples
+    cd samples/
+    npm link ../
+    npm install
+    cd ..
+    # If tests are running against main branch, configure flakybot
+    # to open issues on failures:
+    if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then
+      export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml
+      export MOCHA_REPORTER=xunit
+      cleanup() {
+        chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot
+        $KOKORO_GFILE_DIR/linux_amd64/flakybot
+      }
+      trap cleanup EXIT HUP
+    fi
+
+    npm run samples-test
+fi
+
+# codecov combines coverage across integration and unit tests. Include
+# the logic below for any environment you wish to collect coverage for:
+COVERAGE_NODE=12
+if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then
+  NYC_BIN=./node_modules/nyc/bin/nyc.js
+  if [ -f "$NYC_BIN" ]; then
+    $NYC_BIN report || true
+  fi
+  bash $KOKORO_GFILE_DIR/codecov.sh
+else
+  echo "coverage is only reported for Node $COVERAGE_NODE"
+fi
diff --git a/.kokoro/system-test.sh b/.kokoro/system-test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..87fa0653d76eca77c258930de1188acd95747b54
--- /dev/null
+++ b/.kokoro/system-test.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+# 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
+#
+#     https://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.
+
+set -eo pipefail
+
+export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+
+# Setup service account credentials.
+export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json
+export GCLOUD_PROJECT=long-door-651
+
+cd $(dirname $0)/..
+
+# Run a pre-test hook, if a pre-system-test.sh is in the project
+if [ -f .kokoro/pre-system-test.sh ]; then
+    set +x
+    . .kokoro/pre-system-test.sh
+    set -x
+fi
+
+npm install
+
+# If tests are running against main branch, configure flakybot
+# to open issues on failures:
+if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then
+  export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml
+  export MOCHA_REPORTER=xunit
+  cleanup() {
+    chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot
+    $KOKORO_GFILE_DIR/linux_amd64/flakybot
+  }
+  trap cleanup EXIT HUP
+fi
+
+npm run system-test
+
+# codecov combines coverage across integration and unit tests. Include
+# the logic below for any environment you wish to collect coverage for:
+COVERAGE_NODE=12
+if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then
+  NYC_BIN=./node_modules/nyc/bin/nyc.js
+  if [ -f "$NYC_BIN" ]; then
+    $NYC_BIN report || true
+  fi
+  bash $KOKORO_GFILE_DIR/codecov.sh
+else
+  echo "coverage is only reported for Node $COVERAGE_NODE"
+fi
diff --git a/.kokoro/test.bat b/.kokoro/test.bat
new file mode 100644
index 0000000000000000000000000000000000000000..ae59e59be3e674249641f33dcda82c011a54b35f
--- /dev/null
+++ b/.kokoro/test.bat
@@ -0,0 +1,33 @@
+@rem Copyright 2018 Google LLC. All rights reserved.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem     http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+
+@echo "Starting Windows build"
+
+cd /d %~dp0
+cd ..
+
+@rem npm path is not currently set in our image, we should fix this next time
+@rem we upgrade Node.js in the image:
+SET PATH=%PATH%;/cygdrive/c/Program Files/nodejs/npm
+
+call nvm use v12.14.1
+call which node
+
+call npm install || goto :error
+call npm run test || goto :error
+
+goto :EOF
+
+:error
+exit /b 1
diff --git a/.kokoro/test.sh b/.kokoro/test.sh
new file mode 100644
index 0000000000000000000000000000000000000000..a5c7ac04cd32e61bd7a09c752a1a0486d1cb81d3
--- /dev/null
+++ b/.kokoro/test.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# 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
+#
+#     https://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.
+
+set -eo pipefail
+
+export NPM_CONFIG_PREFIX=${HOME}/.npm-global
+
+cd $(dirname $0)/..
+
+npm install
+# If tests are running against main branch, configure flakybot
+# to open issues on failures:
+if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then
+  export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml
+  export MOCHA_REPORTER=xunit
+  cleanup() {
+    chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot
+    $KOKORO_GFILE_DIR/linux_amd64/flakybot
+  }
+  trap cleanup EXIT HUP
+fi
+# Unit tests exercise the entire API surface, which may include
+# deprecation warnings:
+export MOCHA_THROW_DEPRECATION=false
+npm test
+
+# codecov combines coverage across integration and unit tests. Include
+# the logic below for any environment you wish to collect coverage for:
+COVERAGE_NODE=12
+if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then
+  NYC_BIN=./node_modules/nyc/bin/nyc.js
+  if [ -f "$NYC_BIN" ]; then
+    $NYC_BIN report || true
+  fi
+  bash $KOKORO_GFILE_DIR/codecov.sh
+else
+  echo "coverage is only reported for Node $COVERAGE_NODE"
+fi
diff --git a/.kokoro/trampoline.sh b/.kokoro/trampoline.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f693a1ce7aa83066d87539a36b16681a9b6226c2
--- /dev/null
+++ b/.kokoro/trampoline.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# Copyright 2017 Google Inc.
+#
+# 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.
+
+# This file is not used any more, but we keep this file for making it
+# easy to roll back.
+# TODO: Remove this file from the template.
+
+set -eo pipefail
+
+# Always run the cleanup script, regardless of the success of bouncing into
+# the container.
+function cleanup() {
+    chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
+    ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
+    echo "cleanup";
+}
+trap cleanup EXIT
+
+$(dirname $0)/populate-secrets.sh # Secret Manager secrets.
+python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py"
diff --git a/.kokoro/trampoline_v2.sh b/.kokoro/trampoline_v2.sh
new file mode 100644
index 0000000000000000000000000000000000000000..4d03112128a63415da90ea64ca0216564d78d215
--- /dev/null
+++ b/.kokoro/trampoline_v2.sh
@@ -0,0 +1,490 @@
+#!/usr/bin/env bash
+# Copyright 2020 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.
+
+# trampoline_v2.sh
+#
+# If you want to make a change to this file, consider doing so at:
+# https://github.com/googlecloudplatform/docker-ci-helper
+#
+# This script is for running CI builds. For Kokoro builds, we
+# set this script to `build_file` field in the Kokoro configuration.
+
+# This script does 3 things.
+#
+# 1. Prepare the Docker image for the test
+# 2. Run the Docker with appropriate flags to run the test
+# 3. Upload the newly built Docker image
+#
+# in a way that is somewhat compatible with trampoline_v1.
+#
+# These environment variables are required:
+# TRAMPOLINE_IMAGE: The docker image to use.
+# TRAMPOLINE_DOCKERFILE: The location of the Dockerfile.
+#
+# You can optionally change these environment variables:
+# TRAMPOLINE_IMAGE_UPLOAD:
+#     (true|false): Whether to upload the Docker image after the
+#                   successful builds.
+# TRAMPOLINE_BUILD_FILE: The script to run in the docker container.
+# TRAMPOLINE_WORKSPACE: The workspace path in the docker container.
+#                       Defaults to /workspace.
+# Potentially there are some repo specific envvars in .trampolinerc in
+# the project root.
+#
+# Here is an example for running this script.
+#   TRAMPOLINE_IMAGE=gcr.io/cloud-devrel-kokoro-resources/node:10-user \
+#     TRAMPOLINE_BUILD_FILE=.kokoro/system-test.sh \
+#     .kokoro/trampoline_v2.sh
+
+set -euo pipefail
+
+TRAMPOLINE_VERSION="2.0.7"
+
+if command -v tput >/dev/null && [[ -n "${TERM:-}" ]]; then
+  readonly IO_COLOR_RED="$(tput setaf 1)"
+  readonly IO_COLOR_GREEN="$(tput setaf 2)"
+  readonly IO_COLOR_YELLOW="$(tput setaf 3)"
+  readonly IO_COLOR_RESET="$(tput sgr0)"
+else
+  readonly IO_COLOR_RED=""
+  readonly IO_COLOR_GREEN=""
+  readonly IO_COLOR_YELLOW=""
+  readonly IO_COLOR_RESET=""
+fi
+
+function function_exists {
+    [ $(LC_ALL=C type -t $1)"" == "function" ]
+}
+
+# Logs a message using the given color. The first argument must be one
+# of the IO_COLOR_* variables defined above, such as
+# "${IO_COLOR_YELLOW}". The remaining arguments will be logged in the
+# given color. The log message will also have an RFC-3339 timestamp
+# prepended (in UTC). You can disable the color output by setting
+# TERM=vt100.
+function log_impl() {
+    local color="$1"
+    shift
+    local timestamp="$(date -u "+%Y-%m-%dT%H:%M:%SZ")"
+    echo "================================================================"
+    echo "${color}${timestamp}:" "$@" "${IO_COLOR_RESET}"
+    echo "================================================================"
+}
+
+# Logs the given message with normal coloring and a timestamp.
+function log() {
+  log_impl "${IO_COLOR_RESET}" "$@"
+}
+
+# Logs the given message in green with a timestamp.
+function log_green() {
+  log_impl "${IO_COLOR_GREEN}" "$@"
+}
+
+# Logs the given message in yellow with a timestamp.
+function log_yellow() {
+  log_impl "${IO_COLOR_YELLOW}" "$@"
+}
+
+# Logs the given message in red with a timestamp.
+function log_red() {
+  log_impl "${IO_COLOR_RED}" "$@"
+}
+
+readonly tmpdir=$(mktemp -d -t ci-XXXXXXXX)
+readonly tmphome="${tmpdir}/h"
+mkdir -p "${tmphome}"
+
+function cleanup() {
+    rm -rf "${tmpdir}"
+}
+trap cleanup EXIT
+
+RUNNING_IN_CI="${RUNNING_IN_CI:-false}"
+
+# The workspace in the container, defaults to /workspace.
+TRAMPOLINE_WORKSPACE="${TRAMPOLINE_WORKSPACE:-/workspace}"
+
+pass_down_envvars=(
+    # TRAMPOLINE_V2 variables.
+    # Tells scripts whether they are running as part of CI or not.
+    "RUNNING_IN_CI"
+    # Indicates which CI system we're in.
+    "TRAMPOLINE_CI"
+    # Indicates the version of the script.
+    "TRAMPOLINE_VERSION"
+    # Contains path to build artifacts being executed.
+    "KOKORO_BUILD_ARTIFACTS_SUBDIR"
+)
+
+log_yellow "Building with Trampoline ${TRAMPOLINE_VERSION}"
+
+# Detect which CI systems we're in. If we're in any of the CI systems
+# we support, `RUNNING_IN_CI` will be true and `TRAMPOLINE_CI` will be
+# the name of the CI system. Both envvars will be passing down to the
+# container for telling which CI system we're in.
+if [[ -n "${KOKORO_BUILD_ID:-}" ]]; then
+    # descriptive env var for indicating it's on CI.
+    RUNNING_IN_CI="true"
+    TRAMPOLINE_CI="kokoro"
+    if [[ "${TRAMPOLINE_USE_LEGACY_SERVICE_ACCOUNT:-}" == "true" ]]; then
+	if [[ ! -f "${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json" ]]; then
+	    log_red "${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json does not exist. Did you forget to mount cloud-devrel-kokoro-resources/trampoline? Aborting."
+	    exit 1
+	fi
+	# This service account will be activated later.
+	TRAMPOLINE_SERVICE_ACCOUNT="${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json"
+    else
+	if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+	    gcloud auth list
+	fi
+	log_yellow "Configuring Container Registry access"
+	gcloud auth configure-docker --quiet
+    fi
+    pass_down_envvars+=(
+	# KOKORO dynamic variables.
+	"KOKORO_BUILD_NUMBER"
+	"KOKORO_BUILD_ID"
+	"KOKORO_JOB_NAME"
+	"KOKORO_GIT_COMMIT"
+	"KOKORO_GITHUB_COMMIT"
+	"KOKORO_GITHUB_PULL_REQUEST_NUMBER"
+	"KOKORO_GITHUB_PULL_REQUEST_COMMIT"
+	# For flakybot
+	"KOKORO_GITHUB_COMMIT_URL"
+	"KOKORO_GITHUB_PULL_REQUEST_URL"
+    )
+elif [[ "${TRAVIS:-}" == "true" ]]; then
+    RUNNING_IN_CI="true"
+    TRAMPOLINE_CI="travis"
+    pass_down_envvars+=(
+	"TRAVIS_BRANCH"
+	"TRAVIS_BUILD_ID"
+	"TRAVIS_BUILD_NUMBER"
+	"TRAVIS_BUILD_WEB_URL"
+	"TRAVIS_COMMIT"
+	"TRAVIS_COMMIT_MESSAGE"
+	"TRAVIS_COMMIT_RANGE"
+	"TRAVIS_JOB_NAME"
+	"TRAVIS_JOB_NUMBER"
+	"TRAVIS_JOB_WEB_URL"
+	"TRAVIS_PULL_REQUEST"
+	"TRAVIS_PULL_REQUEST_BRANCH"
+	"TRAVIS_PULL_REQUEST_SHA"
+	"TRAVIS_PULL_REQUEST_SLUG"
+	"TRAVIS_REPO_SLUG"
+	"TRAVIS_SECURE_ENV_VARS"
+	"TRAVIS_TAG"
+    )
+elif [[ -n "${GITHUB_RUN_ID:-}" ]]; then
+    RUNNING_IN_CI="true"
+    TRAMPOLINE_CI="github-workflow"
+    pass_down_envvars+=(
+	"GITHUB_WORKFLOW"
+	"GITHUB_RUN_ID"
+	"GITHUB_RUN_NUMBER"
+	"GITHUB_ACTION"
+	"GITHUB_ACTIONS"
+	"GITHUB_ACTOR"
+	"GITHUB_REPOSITORY"
+	"GITHUB_EVENT_NAME"
+	"GITHUB_EVENT_PATH"
+	"GITHUB_SHA"
+	"GITHUB_REF"
+	"GITHUB_HEAD_REF"
+	"GITHUB_BASE_REF"
+    )
+elif [[ "${CIRCLECI:-}" == "true" ]]; then
+    RUNNING_IN_CI="true"
+    TRAMPOLINE_CI="circleci"
+    pass_down_envvars+=(
+	"CIRCLE_BRANCH"
+	"CIRCLE_BUILD_NUM"
+	"CIRCLE_BUILD_URL"
+	"CIRCLE_COMPARE_URL"
+	"CIRCLE_JOB"
+	"CIRCLE_NODE_INDEX"
+	"CIRCLE_NODE_TOTAL"
+	"CIRCLE_PREVIOUS_BUILD_NUM"
+	"CIRCLE_PROJECT_REPONAME"
+	"CIRCLE_PROJECT_USERNAME"
+	"CIRCLE_REPOSITORY_URL"
+	"CIRCLE_SHA1"
+	"CIRCLE_STAGE"
+	"CIRCLE_USERNAME"
+	"CIRCLE_WORKFLOW_ID"
+	"CIRCLE_WORKFLOW_JOB_ID"
+	"CIRCLE_WORKFLOW_UPSTREAM_JOB_IDS"
+	"CIRCLE_WORKFLOW_WORKSPACE_ID"
+    )
+fi
+
+# Configure the service account for pulling the docker image.
+function repo_root() {
+    local dir="$1"
+    while [[ ! -d "${dir}/.git" ]]; do
+	dir="$(dirname "$dir")"
+    done
+    echo "${dir}"
+}
+
+# Detect the project root. In CI builds, we assume the script is in
+# the git tree and traverse from there, otherwise, traverse from `pwd`
+# to find `.git` directory.
+if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then
+    PROGRAM_PATH="$(realpath "$0")"
+    PROGRAM_DIR="$(dirname "${PROGRAM_PATH}")"
+    PROJECT_ROOT="$(repo_root "${PROGRAM_DIR}")"
+else
+    PROJECT_ROOT="$(repo_root $(pwd))"
+fi
+
+log_yellow "Changing to the project root: ${PROJECT_ROOT}."
+cd "${PROJECT_ROOT}"
+
+# To support relative path for `TRAMPOLINE_SERVICE_ACCOUNT`, we need
+# to use this environment variable in `PROJECT_ROOT`.
+if [[ -n "${TRAMPOLINE_SERVICE_ACCOUNT:-}" ]]; then
+
+    mkdir -p "${tmpdir}/gcloud"
+    gcloud_config_dir="${tmpdir}/gcloud"
+
+    log_yellow "Using isolated gcloud config: ${gcloud_config_dir}."
+    export CLOUDSDK_CONFIG="${gcloud_config_dir}"
+
+    log_yellow "Using ${TRAMPOLINE_SERVICE_ACCOUNT} for authentication."
+    gcloud auth activate-service-account \
+	   --key-file "${TRAMPOLINE_SERVICE_ACCOUNT}"
+    log_yellow "Configuring Container Registry access"
+    gcloud auth configure-docker --quiet
+fi
+
+required_envvars=(
+    # The basic trampoline configurations.
+    "TRAMPOLINE_IMAGE"
+    "TRAMPOLINE_BUILD_FILE"
+)
+
+if [[ -f "${PROJECT_ROOT}/.trampolinerc" ]]; then
+    source "${PROJECT_ROOT}/.trampolinerc"
+fi
+
+log_yellow "Checking environment variables."
+for e in "${required_envvars[@]}"
+do
+    if [[ -z "${!e:-}" ]]; then
+	log "Missing ${e} env var. Aborting."
+	exit 1
+    fi
+done
+
+# We want to support legacy style TRAMPOLINE_BUILD_FILE used with V1
+# script: e.g. "github/repo-name/.kokoro/run_tests.sh"
+TRAMPOLINE_BUILD_FILE="${TRAMPOLINE_BUILD_FILE#github/*/}"
+log_yellow "Using TRAMPOLINE_BUILD_FILE: ${TRAMPOLINE_BUILD_FILE}"
+
+# ignore error on docker operations and test execution
+set +e
+
+log_yellow "Preparing Docker image."
+# We only download the docker image in CI builds.
+if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then
+    # Download the docker image specified by `TRAMPOLINE_IMAGE`
+
+    # We may want to add --max-concurrent-downloads flag.
+
+    log_yellow "Start pulling the Docker image: ${TRAMPOLINE_IMAGE}."
+    if docker pull "${TRAMPOLINE_IMAGE}"; then
+	log_green "Finished pulling the Docker image: ${TRAMPOLINE_IMAGE}."
+	has_image="true"
+    else
+	log_red "Failed pulling the Docker image: ${TRAMPOLINE_IMAGE}."
+	has_image="false"
+    fi
+else
+    # For local run, check if we have the image.
+    if docker images "${TRAMPOLINE_IMAGE}" | grep "${TRAMPOLINE_IMAGE%:*}"; then
+	has_image="true"
+    else
+	has_image="false"
+    fi
+fi
+
+
+# The default user for a Docker container has uid 0 (root). To avoid
+# creating root-owned files in the build directory we tell docker to
+# use the current user ID.
+user_uid="$(id -u)"
+user_gid="$(id -g)"
+user_name="$(id -un)"
+
+# To allow docker in docker, we add the user to the docker group in
+# the host os.
+docker_gid=$(cut -d: -f3 < <(getent group docker))
+
+update_cache="false"
+if [[ "${TRAMPOLINE_DOCKERFILE:-none}" != "none" ]]; then
+    # Build the Docker image from the source.
+    context_dir=$(dirname "${TRAMPOLINE_DOCKERFILE}")
+    docker_build_flags=(
+	"-f" "${TRAMPOLINE_DOCKERFILE}"
+	"-t" "${TRAMPOLINE_IMAGE}"
+	"--build-arg" "UID=${user_uid}"
+	"--build-arg" "USERNAME=${user_name}"
+    )
+    if [[ "${has_image}" == "true" ]]; then
+	docker_build_flags+=("--cache-from" "${TRAMPOLINE_IMAGE}")
+    fi
+
+    log_yellow "Start building the docker image."
+    if [[ "${TRAMPOLINE_VERBOSE:-false}" == "true" ]]; then
+	echo "docker build" "${docker_build_flags[@]}" "${context_dir}"
+    fi
+
+    # ON CI systems, we want to suppress docker build logs, only
+    # output the logs when it fails.
+    if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then
+	if docker build "${docker_build_flags[@]}" "${context_dir}" \
+		  > "${tmpdir}/docker_build.log" 2>&1; then
+	    if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+		cat "${tmpdir}/docker_build.log"
+	    fi
+
+	    log_green "Finished building the docker image."
+	    update_cache="true"
+	else
+	    log_red "Failed to build the Docker image, aborting."
+	    log_yellow "Dumping the build logs:"
+	    cat "${tmpdir}/docker_build.log"
+	    exit 1
+	fi
+    else
+	if docker build "${docker_build_flags[@]}" "${context_dir}"; then
+	    log_green "Finished building the docker image."
+	    update_cache="true"
+	else
+	    log_red "Failed to build the Docker image, aborting."
+	    exit 1
+	fi
+    fi
+else
+    if [[ "${has_image}" != "true" ]]; then
+	log_red "We do not have ${TRAMPOLINE_IMAGE} locally, aborting."
+	exit 1
+    fi
+fi
+
+# We use an array for the flags so they are easier to document.
+docker_flags=(
+    # Remove the container after it exists.
+    "--rm"
+
+    # Use the host network.
+    "--network=host"
+
+    # Run in priviledged mode. We are not using docker for sandboxing or
+    # isolation, just for packaging our dev tools.
+    "--privileged"
+
+    # Run the docker script with the user id. Because the docker image gets to
+    # write in ${PWD} you typically want this to be your user id.
+    # To allow docker in docker, we need to use docker gid on the host.
+    "--user" "${user_uid}:${docker_gid}"
+
+    # Pass down the USER.
+    "--env" "USER=${user_name}"
+
+    # Mount the project directory inside the Docker container.
+    "--volume" "${PROJECT_ROOT}:${TRAMPOLINE_WORKSPACE}"
+    "--workdir" "${TRAMPOLINE_WORKSPACE}"
+    "--env" "PROJECT_ROOT=${TRAMPOLINE_WORKSPACE}"
+
+    # Mount the temporary home directory.
+    "--volume" "${tmphome}:/h"
+    "--env" "HOME=/h"
+
+    # Allow docker in docker.
+    "--volume" "/var/run/docker.sock:/var/run/docker.sock"
+
+    # Mount the /tmp so that docker in docker can mount the files
+    # there correctly.
+    "--volume" "/tmp:/tmp"
+    # Pass down the KOKORO_GFILE_DIR and KOKORO_KEYSTORE_DIR
+    # TODO(tmatsuo): This part is not portable.
+    "--env" "TRAMPOLINE_SECRET_DIR=/secrets"
+    "--volume" "${KOKORO_GFILE_DIR:-/dev/shm}:/secrets/gfile"
+    "--env" "KOKORO_GFILE_DIR=/secrets/gfile"
+    "--volume" "${KOKORO_KEYSTORE_DIR:-/dev/shm}:/secrets/keystore"
+    "--env" "KOKORO_KEYSTORE_DIR=/secrets/keystore"
+)
+
+# Add an option for nicer output if the build gets a tty.
+if [[ -t 0 ]]; then
+    docker_flags+=("-it")
+fi
+
+# Passing down env vars
+for e in "${pass_down_envvars[@]}"
+do
+    if [[ -n "${!e:-}" ]]; then
+	docker_flags+=("--env" "${e}=${!e}")
+    fi
+done
+
+# If arguments are given, all arguments will become the commands run
+# in the container, otherwise run TRAMPOLINE_BUILD_FILE.
+if [[ $# -ge 1 ]]; then
+    log_yellow "Running the given commands '" "${@:1}" "' in the container."
+    readonly commands=("${@:1}")
+    if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+	echo docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" "${commands[@]}"
+    fi
+    docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" "${commands[@]}"
+else
+    log_yellow "Running the tests in a Docker container."
+    docker_flags+=("--entrypoint=${TRAMPOLINE_BUILD_FILE}")
+    if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+	echo docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}"
+    fi
+    docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}"
+fi
+
+
+test_retval=$?
+
+if [[ ${test_retval} -eq 0 ]]; then
+    log_green "Build finished with ${test_retval}"
+else
+    log_red "Build finished with ${test_retval}"
+fi
+
+# Only upload it when the test passes.
+if [[ "${update_cache}" == "true" ]] && \
+       [[ $test_retval == 0 ]] && \
+       [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]]; then
+    log_yellow "Uploading the Docker image."
+    if docker push "${TRAMPOLINE_IMAGE}"; then
+	log_green "Finished uploading the Docker image."
+    else
+	log_red "Failed uploading the Docker image."
+    fi
+    # Call trampoline_after_upload_hook if it's defined.
+    if function_exists trampoline_after_upload_hook; then
+	trampoline_after_upload_hook
+    fi
+
+fi
+
+exit "${test_retval}"
diff --git a/.mocharc.js b/.mocharc.js
new file mode 100644
index 0000000000000000000000000000000000000000..0b600509bed2b896d183c4ecf6ec36c3bd6fdef6
--- /dev/null
+++ b/.mocharc.js
@@ -0,0 +1,29 @@
+// Copyright 2020 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.
+const config = {
+  "enable-source-maps": true,
+  "throw-deprecation": true,
+  "timeout": 10000,
+  "recursive": true
+}
+if (process.env.MOCHA_THROW_DEPRECATION === 'false') {
+  delete config['throw-deprecation'];
+}
+if (process.env.MOCHA_REPORTER) {
+  config.reporter = process.env.MOCHA_REPORTER;
+}
+if (process.env.MOCHA_REPORTER_OUTPUT) {
+  config['reporter-option'] = `output=${process.env.MOCHA_REPORTER_OUTPUT}`;
+}
+module.exports = config
diff --git a/.nycrc b/.nycrc
new file mode 100644
index 0000000000000000000000000000000000000000..b18d5472b62b531f76420f2da26e1201a11d929f
--- /dev/null
+++ b/.nycrc
@@ -0,0 +1,24 @@
+{
+  "report-dir": "./.coverage",
+  "reporter": ["text", "lcov"],
+  "exclude": [
+    "**/*-test",
+    "**/.coverage",
+    "**/apis",
+    "**/benchmark",
+    "**/conformance",
+    "**/docs",
+    "**/samples",
+    "**/scripts",
+    "**/protos",
+    "**/test",
+    "**/*.d.ts",
+    ".jsdoc.js",
+    "**/.jsdoc.js",
+    "karma.conf.js",
+    "webpack-tests.config.js",
+    "webpack.config.js"
+  ],
+  "exclude-after-remap": false,
+  "all": true
+}
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000000000000000000000000000000000000..9340ad9b86d355eba9ee08347e4ac15e66fe312f
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,6 @@
+**/node_modules
+**/coverage
+test/fixtures
+build/
+docs/
+protos/
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..d1b95106f4ce6a65d00cdaea5c9792366539849b
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,17 @@
+// Copyright 2020 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
+//
+//      https://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.
+
+module.exports = {
+  ...require('gts/.prettierrc.json')
+}
diff --git a/.readme-partials.yaml b/.readme-partials.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b7b914a2154766da7299e0f20b15ba84d77a1d51
--- /dev/null
+++ b/.readme-partials.yaml
@@ -0,0 +1,4 @@
+introduction: |-
+    > Node.js idiomatic client for [Cloud IoT Core][product-docs].
+
+    [Google Cloud Internet of Things (IoT) Core](https://cloud.google.com/iot/docs) is a fully managed service for securely connecting and managing IoT devices, from a few to millions. Ingest data from connected devices and build rich applications that integrate with the other big data services of Google Cloud Platform.
diff --git a/.repo-metadata.json b/.repo-metadata.json
new file mode 100644
index 0000000000000000000000000000000000000000..a53e100f9c43533093a2c71ea13a3da1c7471d11
--- /dev/null
+++ b/.repo-metadata.json
@@ -0,0 +1,16 @@
+{
+  "client_documentation": "https://cloud.google.com/nodejs/docs/reference/iot/latest",
+  "api_id": "cloudiot.googleapis.com",
+  "codeowner_team": "@googleapis/api-iot",
+  "distribution_name": "@google-cloud/iot",
+  "release_level": "stable",
+  "language": "nodejs",
+  "name_pretty": "Google Cloud Internet of Things (IoT) Core",
+  "repo": "googleapis/nodejs-iot",
+  "product_documentation": "https://cloud.google.com/iot",
+  "requires_billing": true,
+  "name": "iot",
+  "default_version": "v1",
+  "api_shortname": "cloudiot",
+  "library_type": "GAPIC_AUTO"
+}
diff --git a/.trampolinerc b/.trampolinerc
new file mode 100644
index 0000000000000000000000000000000000000000..5fc2253137dbffe11d193daa6e0659661b67bb71
--- /dev/null
+++ b/.trampolinerc
@@ -0,0 +1,52 @@
+# Copyright 2020 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.
+
+# Template for .trampolinerc
+
+# Add required env vars here.
+required_envvars+=(
+)
+
+# Add env vars which are passed down into the container here.
+pass_down_envvars+=(
+    "AUTORELEASE_PR"
+    "VERSION"
+)
+
+# Prevent unintentional override on the default image.
+if [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]] && \
+   [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then
+   echo "Please set TRAMPOLINE_IMAGE if you want to upload the Docker image."
+   exit 1
+fi
+
+# Define the default value if it makes sense.
+if [[ -z "${TRAMPOLINE_IMAGE_UPLOAD:-}" ]]; then
+    TRAMPOLINE_IMAGE_UPLOAD=""
+fi
+
+if [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then
+    TRAMPOLINE_IMAGE=""
+fi
+
+if [[ -z "${TRAMPOLINE_DOCKERFILE:-}" ]]; then
+    TRAMPOLINE_DOCKERFILE=""
+fi
+
+if [[ -z "${TRAMPOLINE_BUILD_FILE:-}" ]]; then
+    TRAMPOLINE_BUILD_FILE=""
+fi
+
+# Secret Manager secrets.
+source ${PROJECT_ROOT}/.kokoro/populate-secrets.sh
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..397836fadaf1dd303a371eb1da0583cf89aa42c6
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,456 @@
+# Changelog
+
+## [3.1.0](https://github.com/googleapis/nodejs-iot/compare/v3.0.0...v3.1.0) (2022-07-05)
+
+
+### Features
+
+* support regapic LRO ([b02cd4d](https://github.com/googleapis/nodejs-iot/commit/b02cd4d8f954fa1c34ef77055eb5c0b628095482))
+
+## [3.0.0](https://github.com/googleapis/nodejs-iot/compare/v2.5.1...v3.0.0) (2022-06-20)
+
+
+### âš  BREAKING CHANGES
+
+* update library to use Node 12 (#566)
+
+### Features
+
+* AuditConfig for IAM v1 ([#552](https://github.com/googleapis/nodejs-iot/issues/552)) ([1b1a3d2](https://github.com/googleapis/nodejs-iot/commit/1b1a3d226374bb7e9df3444d7384ae6e4d4ece4d))
+
+
+### Bug Fixes
+
+* **deps:** update dependency @google-cloud/pubsub to v3 ([#569](https://github.com/googleapis/nodejs-iot/issues/569)) ([77a2005](https://github.com/googleapis/nodejs-iot/commit/77a2005a44866ef0261791da592878fca1d067bd))
+* **deps:** update dependency @google-cloud/storage to v6 ([#568](https://github.com/googleapis/nodejs-iot/issues/568)) ([b15efb4](https://github.com/googleapis/nodejs-iot/commit/b15efb4f8319eab0e1e01dbd38f163b7fa844d39))
+
+
+### Build System
+
+* update library to use Node 12 ([#566](https://github.com/googleapis/nodejs-iot/issues/566)) ([1efe654](https://github.com/googleapis/nodejs-iot/commit/1efe6549ae7d0a84bd4388dd4cf89f924a118db4))
+
+### [2.5.1](https://www.github.com/googleapis/nodejs-iot/compare/v2.5.0...v2.5.1) (2021-09-27)
+
+
+### Bug Fixes
+
+* **deps:** update dependency @google-cloud/storage to v5 ([#515](https://www.github.com/googleapis/nodejs-iot/issues/515)) ([ba34e57](https://www.github.com/googleapis/nodejs-iot/commit/ba34e57652a18ac839d6feb4e0ba5c3e60364f60))
+
+## [2.5.0](https://www.github.com/googleapis/nodejs-iot/compare/v2.4.0...v2.5.0) (2021-09-17)
+
+
+### Features
+
+* Add sample codes for cloud-iot-token-service generateAccessToken API ([#502](https://www.github.com/googleapis/nodejs-iot/issues/502)) ([21ef5c7](https://www.github.com/googleapis/nodejs-iot/commit/21ef5c7a264c01c12675e623e7c160b2e33c8072))
+
+## [2.4.0](https://www.github.com/googleapis/nodejs-iot/compare/v2.3.6...v2.4.0) (2021-09-03)
+
+
+### Features
+
+* turns on self-signed JWT feature flag ([#509](https://www.github.com/googleapis/nodejs-iot/issues/509)) ([09350a3](https://www.github.com/googleapis/nodejs-iot/commit/09350a3b33d418c94dc36d0ff3abd1e11958fc55))
+
+
+### Bug Fixes
+
+* **build:** migrate to main branch ([#512](https://www.github.com/googleapis/nodejs-iot/issues/512)) ([8528684](https://www.github.com/googleapis/nodejs-iot/commit/852868454982502c0a1ab0d2fa09f14bcfe5ff13))
+
+### [2.3.6](https://www.github.com/googleapis/nodejs-iot/compare/v2.3.5...v2.3.6) (2021-08-17)
+
+
+### Bug Fixes
+
+* **deps:** google-gax v2.24.1 ([#507](https://www.github.com/googleapis/nodejs-iot/issues/507)) ([8fa3d71](https://www.github.com/googleapis/nodejs-iot/commit/8fa3d7180578cab4bc5b29d64a2f8a05a741cdff))
+
+### [2.3.5](https://www.github.com/googleapis/nodejs-iot/compare/v2.3.4...v2.3.5) (2021-07-21)
+
+
+### Bug Fixes
+
+* **deps:** google-gax v2.17.1 ([#496](https://www.github.com/googleapis/nodejs-iot/issues/496)) ([dc278eb](https://www.github.com/googleapis/nodejs-iot/commit/dc278eb4d8ce23454a582fda121766fa0f47e619))
+* Updating WORKSPACE files to use the newest version of the Typescript generator. ([#499](https://www.github.com/googleapis/nodejs-iot/issues/499)) ([0e5967f](https://www.github.com/googleapis/nodejs-iot/commit/0e5967f873ff7db59f400ac651f2b0590650e42f))
+
+### [2.3.4](https://www.github.com/googleapis/nodejs-iot/compare/v2.3.3...v2.3.4) (2021-07-01)
+
+
+### Bug Fixes
+
+* **deps:** require google-gax v2.17.0 ([#493](https://www.github.com/googleapis/nodejs-iot/issues/493)) ([f61a834](https://www.github.com/googleapis/nodejs-iot/commit/f61a834d9d8e9564f73849821de351757589422a))
+
+### [2.3.3](https://www.github.com/googleapis/nodejs-iot/compare/v2.3.2...v2.3.3) (2021-06-22)
+
+
+### Bug Fixes
+
+* make request optional in all cases ([#487](https://www.github.com/googleapis/nodejs-iot/issues/487)) ([72c258b](https://www.github.com/googleapis/nodejs-iot/commit/72c258b53e18add510c59f2756f9d8d628edefaa))
+
+### [2.3.2](https://www.github.com/googleapis/nodejs-iot/compare/v2.3.1...v2.3.2) (2021-06-07)
+
+
+### Bug Fixes
+
+* GoogleAdsError missing using generator version after 1.3.0 ([#478](https://www.github.com/googleapis/nodejs-iot/issues/478)) ([5c20030](https://www.github.com/googleapis/nodejs-iot/commit/5c20030e43fdd110b87aeeabed533f6c70a03e81))
+
+### [2.3.1](https://www.github.com/googleapis/nodejs-iot/compare/v2.3.0...v2.3.1) (2021-05-12)
+
+
+### Bug Fixes
+
+* **deps:** require google-gax v2.12.0 ([#469](https://www.github.com/googleapis/nodejs-iot/issues/469)) ([fba8758](https://www.github.com/googleapis/nodejs-iot/commit/fba875813f41232a71338971c4c1766001dcefb5))
+* use require() to load JSON protos ([#472](https://www.github.com/googleapis/nodejs-iot/issues/472)) ([d963cf7](https://www.github.com/googleapis/nodejs-iot/commit/d963cf709052a7236a80cf1c0c9fbbaffd311aad))
+
+## [2.3.0](https://www.github.com/googleapis/nodejs-iot/compare/v2.2.1...v2.3.0) (2021-02-10)
+
+
+### Features
+
+* add serverCertFile parameter ([#438](https://www.github.com/googleapis/nodejs-iot/issues/438)) ([e979160](https://www.github.com/googleapis/nodejs-iot/commit/e97916026e6d794b09143059203f8d3530311ffe))
+
+### [2.2.1](https://www.github.com/googleapis/nodejs-iot/compare/v2.2.0...v2.2.1) (2021-02-05)
+
+
+### Bug Fixes
+
+* add fieldMask for getDevice and listDevices ([#436](https://www.github.com/googleapis/nodejs-iot/issues/436)) ([a97ed10](https://www.github.com/googleapis/nodejs-iot/commit/a97ed10e8ecc75aeba1fcb89637ef1298801150e))
+
+## [2.2.0](https://www.github.com/googleapis/nodejs-iot/compare/v2.1.3...v2.2.0) (2021-01-09)
+
+
+### Features
+
+* adds style enumeration ([#426](https://www.github.com/googleapis/nodejs-iot/issues/426)) ([4daeff4](https://www.github.com/googleapis/nodejs-iot/commit/4daeff47d5cfc5fd826705f4da5b8dbed1784e44))
+
+### [2.1.3](https://www.github.com/googleapis/nodejs-iot/compare/v2.1.2...v2.1.3) (2020-11-25)
+
+
+### Bug Fixes
+
+* **browser:** check for fetch on window ([84ca7b6](https://www.github.com/googleapis/nodejs-iot/commit/84ca7b6f4d6a696713e02a1f9d4b3aebb30a5589))
+
+### [2.1.2](https://www.github.com/googleapis/nodejs-iot/compare/v2.1.1...v2.1.2) (2020-11-07)
+
+
+### Bug Fixes
+
+* do not modify options object, use defaultScopes ([#416](https://www.github.com/googleapis/nodejs-iot/issues/416)) ([00bf691](https://www.github.com/googleapis/nodejs-iot/commit/00bf691f327f596effc67679b1fb05f6614b57fe))
+* **deps:** update dependency gaxios to v4 ([#403](https://www.github.com/googleapis/nodejs-iot/issues/403)) ([0f05a18](https://www.github.com/googleapis/nodejs-iot/commit/0f05a18d4facda85735f7b7aafc04584b9234c81))
+
+### [2.1.1](https://www.github.com/googleapis/nodejs-iot/compare/v2.1.0...v2.1.1) (2020-07-15)
+
+
+### Bug Fixes
+
+* **deps:** update dependency googleapis to v54 ([#360](https://www.github.com/googleapis/nodejs-iot/issues/360)) ([d4fc58a](https://www.github.com/googleapis/nodejs-iot/commit/d4fc58a9588af800556f884b8e8d3e2418eda94a))
+
+## [2.1.0](https://www.github.com/googleapis/nodejs-iot/compare/v2.0.2...v2.1.0) (2020-06-28)
+
+
+### Features
+
+* move ts target to es2018 from es2016 ([#348](https://www.github.com/googleapis/nodejs-iot/issues/348)) ([e876504](https://www.github.com/googleapis/nodejs-iot/commit/e876504a2670481c9263ef56261469463dacad47))
+
+
+### Bug Fixes
+
+* proper fallback option handling ([3a595f0](https://www.github.com/googleapis/nodejs-iot/commit/3a595f0636429914c5384f02b78f9ef21d9d08d6))
+
+### [2.0.2](https://www.github.com/googleapis/nodejs-iot/compare/v2.0.1...v2.0.2) (2020-06-04)
+
+
+### Bug Fixes
+
+* **deps:** update dependency @google-cloud/pubsub to v2 ([#341](https://www.github.com/googleapis/nodejs-iot/issues/341)) ([81609b8](https://www.github.com/googleapis/nodejs-iot/commit/81609b84406077532f58af70028ccf675fa838f3))
+* **deps:** update dependency googleapis to v52 ([#343](https://www.github.com/googleapis/nodejs-iot/issues/343)) ([d26347e](https://www.github.com/googleapis/nodejs-iot/commit/d26347e4b80ac6bff4270442dc9f8e24c7245316))
+
+### [2.0.1](https://www.github.com/googleapis/nodejs-iot/compare/v2.0.0...v2.0.1) (2020-05-18)
+
+
+### Bug Fixes
+
+* **deps:** update dependency @google-cloud/iot to v2 ([#326](https://www.github.com/googleapis/nodejs-iot/issues/326)) ([37a9faf](https://www.github.com/googleapis/nodejs-iot/commit/37a9faf5bece0d08b3205baa4e8e4505b07cbd73))
+* **deps:** update dependency googleapis to v49 ([#327](https://www.github.com/googleapis/nodejs-iot/issues/327)) ([e1fee34](https://www.github.com/googleapis/nodejs-iot/commit/e1fee342fa0eedb2ec9f0d1c0ed9e20da2b1cd6c))
+* regenerate unit tests ([#333](https://www.github.com/googleapis/nodejs-iot/issues/333)) ([f4a35b3](https://www.github.com/googleapis/nodejs-iot/commit/f4a35b369297d7ff91793f59a0451931d4abff94))
+* remove unused file, fix synth ([#309](https://www.github.com/googleapis/nodejs-iot/issues/309)) ([17b2ddc](https://www.github.com/googleapis/nodejs-iot/commit/17b2ddccc72a91023a348a0dbf13705670e0c0ca))
+* **deps:** update dependency googleapis to v50 ([#334](https://www.github.com/googleapis/nodejs-iot/issues/334)) ([a5b5fcc](https://www.github.com/googleapis/nodejs-iot/commit/a5b5fcccfffe06f4cd3969ba374e67a0f2144add))
+* synth.py clean up for multiple version ([#335](https://www.github.com/googleapis/nodejs-iot/issues/335)) ([a329db2](https://www.github.com/googleapis/nodejs-iot/commit/a329db210db15e6a34b4fa6cae400b52f62dafa2))
+* **deps:** update dependency googleapis to v51 ([#339](https://www.github.com/googleapis/nodejs-iot/issues/339)) ([70b65b7](https://www.github.com/googleapis/nodejs-iot/commit/70b65b74e803e1fd8cdaed258cbc63f73a110a87))
+
+## [2.0.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.8.0...v2.0.0) (2020-04-12)
+
+
+### âš  BREAKING CHANGES
+
+* The library now supports Node.js v10+. The last version to support Node.js v8 is tagged legacy-8 on NPM.
+
+### Features
+
+* drop node8 support, support for async iterators ([#297](https://www.github.com/googleapis/nodejs-iot/issues/297)) ([1cf607e](https://www.github.com/googleapis/nodejs-iot/commit/1cf607edcecfe2053596096efaa1cabe0d11de1e))
+
+
+### Bug Fixes
+
+* export explicit version from protos.js ([#302](https://www.github.com/googleapis/nodejs-iot/issues/302)) ([8c8acba](https://www.github.com/googleapis/nodejs-iot/commit/8c8acba58f2670139863849cb86e3d8fe9fc7af7))
+* remove eslint, update gax, fix generated protos, run the generator ([#306](https://www.github.com/googleapis/nodejs-iot/issues/306)) ([8edd1b5](https://www.github.com/googleapis/nodejs-iot/commit/8edd1b51347efc7a78390702ba8bd0a714599695))
+
+## [1.8.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.7.0...v1.8.0) (2020-03-06)
+
+
+### Features
+
+* deferred client initialization ([#283](https://www.github.com/googleapis/nodejs-iot/issues/283)) ([b70a193](https://www.github.com/googleapis/nodejs-iot/commit/b70a1938f4254fff0f3839bca5871207b8d97c35))
+* export protos in src/index.ts ([9c3098c](https://www.github.com/googleapis/nodejs-iot/commit/9c3098ca5a232f7fb575d5dce2bc1473365b20bd))
+
+
+### Bug Fixes
+
+* pass x-goog-request-params header for streaming calls ([5a35e0f](https://www.github.com/googleapis/nodejs-iot/commit/5a35e0fd4ea40a1a5e9be2c03e83db5fb7c11f81))
+
+## [1.7.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.6.1...v1.7.0) (2020-01-30)
+
+
+### Features
+
+* bump release level to GA ([#257](https://www.github.com/googleapis/nodejs-iot/issues/257)) ([aeb5ff6](https://www.github.com/googleapis/nodejs-iot/commit/aeb5ff6f0e9dc01f68c41d7cf7eeda770ee4d35e))
+
+
+### Bug Fixes
+
+* enum, bytes, and Long types now accept strings ([629e2ed](https://www.github.com/googleapis/nodejs-iot/commit/629e2edcf7a693e156ca2a144615c2b5a4daa4ee))
+
+### [1.6.1](https://www.github.com/googleapis/nodejs-iot/compare/v1.6.0...v1.6.1) (2020-01-09)
+
+
+### Bug Fixes
+
+* proper routing headers ([2fcf0f3](https://www.github.com/googleapis/nodejs-iot/commit/2fcf0f312ef16f6b7a3f149a14fb1bcf35140644))
+
+## [1.6.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.5.0...v1.6.0) (2020-01-05)
+
+
+### Features
+
+* move to typescript code generation ([#236](https://www.github.com/googleapis/nodejs-iot/issues/236)) ([beb3f18](https://www.github.com/googleapis/nodejs-iot/commit/beb3f18b32715b9cc72e7905bde8fffac58c494f))
+
+
+### Bug Fixes
+
+* **deps:** pin TypeScript below 3.7.0 ([d5f5ff2](https://www.github.com/googleapis/nodejs-iot/commit/d5f5ff2bbc885b7bcc6798c3620643407782d8fc))
+* better client close(), update .nycrc, require mocha explicitly ([2ca2d37](https://www.github.com/googleapis/nodejs-iot/commit/2ca2d378bcafe0d821506e0696e973d14c91af31))
+
+## [1.5.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.4.0...v1.5.0) (2019-11-20)
+
+
+### Features
+
+* add singular and plural resource descriptors ([#230](https://www.github.com/googleapis/nodejs-iot/issues/230)) ([2124a2f](https://www.github.com/googleapis/nodejs-iot/commit/2124a2f4bf8ef74e1d0b09108b8a737a090c3802))
+
+
+### Bug Fixes
+
+* **docs:** bump the release level to beta ([#229](https://www.github.com/googleapis/nodejs-iot/issues/229)) ([b62087f](https://www.github.com/googleapis/nodejs-iot/commit/b62087fdb781c9942df72ca3d8c3bedd46eac380))
+
+## [1.4.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.3.1...v1.4.0) (2019-11-15)
+
+
+### Features
+
+* add permissions to testIamPermissions call ([#225](https://www.github.com/googleapis/nodejs-iot/issues/225)) ([5549944](https://www.github.com/googleapis/nodejs-iot/commit/554994431348f46b618e407c5f75661de2c4f24b))
+
+### [1.3.1](https://www.github.com/googleapis/nodejs-iot/compare/v1.3.0...v1.3.1) (2019-11-12)
+
+
+### Bug Fixes
+
+* **docs:** snippets are now replaced in jsdoc comments ([#222](https://www.github.com/googleapis/nodejs-iot/issues/222)) ([50e0c77](https://www.github.com/googleapis/nodejs-iot/commit/50e0c7787e480089913606818a34396a0c35725b))
+* revert incorrect deviceRegistryPath to correct registryPath in proto ([a216742](https://www.github.com/googleapis/nodejs-iot/commit/a21674225a0b8b0081a43028e3b8c7b3d497d201))
+
+## [1.3.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.2.0...v1.3.0) (2019-10-22)
+
+
+### Features
+
+* .d.ts for protos ([653713e](https://www.github.com/googleapis/nodejs-iot/commit/653713e2694a82db67a0bf2c810a70d761b65e29))
+* .d.ts for protos ([#207](https://www.github.com/googleapis/nodejs-iot/issues/207)) ([6bf34f4](https://www.github.com/googleapis/nodejs-iot/commit/6bf34f4445c7624235e0b83c3ef4423168467b89))
+
+
+### Bug Fixes
+
+* changes to retry logic ([68a1d6e](https://www.github.com/googleapis/nodejs-iot/commit/68a1d6ecb61c6c1af74e3890e7eee302d01db370))
+* use compatible version of google-gax ([b3a96bb](https://www.github.com/googleapis/nodejs-iot/commit/b3a96bb6afd654844e52953b2409fcc3f48148f5))
+* **deps:** bump google-gax to 1.7.5 ([#217](https://www.github.com/googleapis/nodejs-iot/issues/217)) ([7a6442e](https://www.github.com/googleapis/nodejs-iot/commit/7a6442ee0f8959ff10a9a8d646bb10e1c042c135))
+
+## [1.2.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.1.3...v1.2.0) (2019-09-16)
+
+
+### Bug Fixes
+
+* use correct version # for x-goog-api-client header ([09adf73](https://www.github.com/googleapis/nodejs-iot/commit/09adf73))
+
+
+### Features
+
+* load protos from JSON, grpc-fallback support ([5028ead](https://www.github.com/googleapis/nodejs-iot/commit/5028ead))
+
+### [1.1.3](https://www.github.com/googleapis/nodejs-iot/compare/v1.1.2...v1.1.3) (2019-08-02)
+
+
+### Bug Fixes
+
+* allow calls with no request, add JSON proto ([9449e5a](https://www.github.com/googleapis/nodejs-iot/commit/9449e5a))
+
+### [1.1.2](https://www.github.com/googleapis/nodejs-iot/compare/v1.1.1...v1.1.2) (2019-06-27)
+
+
+### Bug Fixes
+
+* **docs:** link to reference docs section on googleapis.dev ([#179](https://www.github.com/googleapis/nodejs-iot/issues/179)) ([ce86dba](https://www.github.com/googleapis/nodejs-iot/commit/ce86dba))
+
+### [1.1.1](https://www.github.com/googleapis/nodejs-iot/compare/v1.1.0...v1.1.1) (2019-06-14)
+
+
+### Bug Fixes
+
+* **docs:** move to new client docs URL ([#174](https://www.github.com/googleapis/nodejs-iot/issues/174)) ([281face](https://www.github.com/googleapis/nodejs-iot/commit/281face))
+
+## [1.1.0](https://www.github.com/googleapis/nodejs-iot/compare/v1.0.0...v1.1.0) (2019-06-06)
+
+
+### Features
+
+* support apiEndpoint override in client constructor ([#171](https://www.github.com/googleapis/nodejs-iot/issues/171)) ([551751e](https://www.github.com/googleapis/nodejs-iot/commit/551751e))
+
+## [1.0.0](https://www.github.com/googleapis/nodejs-iot/compare/v0.2.1...v1.0.0) (2019-05-20)
+
+
+### âš  BREAKING CHANGES
+
+* upgrade engines field to >=8.10.0 (#144)
+
+### Bug Fixes
+
+* **deps:** update dependency google-gax to ^0.26.0 ([#142](https://www.github.com/googleapis/nodejs-iot/issues/142)) ([e329c68](https://www.github.com/googleapis/nodejs-iot/commit/e329c68))
+* DEADLINE_EXCEEDED is no longer retried ([#152](https://www.github.com/googleapis/nodejs-iot/issues/152)) ([d037e51](https://www.github.com/googleapis/nodejs-iot/commit/d037e51))
+* DEADLINE_EXCEEDED retry code is idempotent ([#155](https://www.github.com/googleapis/nodejs-iot/issues/155)) ([9e177ed](https://www.github.com/googleapis/nodejs-iot/commit/9e177ed))
+* **deps:** update dependency google-gax to v1 ([#154](https://www.github.com/googleapis/nodejs-iot/issues/154)) ([ea2d803](https://www.github.com/googleapis/nodejs-iot/commit/ea2d803))
+
+
+### Build System
+
+* upgrade engines field to >=8.10.0 ([#144](https://www.github.com/googleapis/nodejs-iot/issues/144)) ([320fb70](https://www.github.com/googleapis/nodejs-iot/commit/320fb70))
+
+## v0.2.1
+
+03-13-2019 14:59 PDT
+
+### Bug Fixes
+- fix: throw on invalid credentials ([#119](https://github.com/googleapis/nodejs-iot/pull/119))
+
+### Dependencies
+- fix(deps): update dependency google-gax to ^0.25.0 ([#110](https://github.com/googleapis/nodejs-iot/pull/110))
+
+### Documentation
+- docs: update links in contrib guide ([#121](https://github.com/googleapis/nodejs-iot/pull/121))
+- docs: update contributing path in README ([#116](https://github.com/googleapis/nodejs-iot/pull/116))
+- docs: move CONTRIBUTING.md to root ([#115](https://github.com/googleapis/nodejs-iot/pull/115))
+- docs: add lint/fix example to contributing guide ([#112](https://github.com/googleapis/nodejs-iot/pull/112))
+
+### Internal / Testing Changes
+- chore: update require statement code style
+- build: Add docuploader credentials to node publish jobs ([#126](https://github.com/googleapis/nodejs-iot/pull/126))
+- build: use node10 to run samples-test, system-test etc ([#125](https://github.com/googleapis/nodejs-iot/pull/125))
+- build: update release configuration
+- chore: update proto docs and code style
+- chore(deps): update dependency mocha to v6
+- build: use linkinator for docs test ([#120](https://github.com/googleapis/nodejs-iot/pull/120))
+- build: create docs test npm scripts ([#118](https://github.com/googleapis/nodejs-iot/pull/118))
+- build: test using @grpc/grpc-js in CI ([#117](https://github.com/googleapis/nodejs-iot/pull/117))
+- refactor: improve generated code style. ([#114](https://github.com/googleapis/nodejs-iot/pull/114))
+- chore(deps): update dependency eslint-config-prettier to v4 ([#109](https://github.com/googleapis/nodejs-iot/pull/109))
+- build: ignore googleapis.com in doc link check ([#107](https://github.com/googleapis/nodejs-iot/pull/107))
+- chore: update year in the license headers. ([#106](https://github.com/googleapis/nodejs-iot/pull/106))
+- build: check broken links in generated docs ([#101](https://github.com/googleapis/nodejs-iot/pull/101))
+
+## v0.2.0
+
+01-14-2019 14:30 PST
+
+### New Features
+- feat: add enhanced gateway features ([#80](https://github.com/googleapis/nodejs-iot/pull/80))
+
+### Dependencies
+- chore(deps): update dependency through2 to v3 ([#69](https://github.com/googleapis/nodejs-iot/pull/69))
+- fix(deps): update dependency google-gax to ^0.23.0 ([#103](https://github.com/googleapis/nodejs-iot/pull/103))
+
+### Documentation
+- fix(docs): remove unused IAM message types
+- samples: update quickstart sample and add sample tests ([#98](https://github.com/googleapis/nodejs-iot/pull/98))
+- docs: update readme badges ([#83](https://github.com/googleapis/nodejs-iot/pull/83))
+
+### Internal / Testing Changes
+- chore(build): inject yoshi automation key ([#97](https://github.com/googleapis/nodejs-iot/pull/97))
+- chore: update nyc and eslint configs ([#96](https://github.com/googleapis/nodejs-iot/pull/96))
+- chore: fix publish.sh permission +x ([#94](https://github.com/googleapis/nodejs-iot/pull/94))
+- fix(build): fix Kokoro release script ([#93](https://github.com/googleapis/nodejs-iot/pull/93))
+- build: add Kokoro configs for autorelease ([#92](https://github.com/googleapis/nodejs-iot/pull/92))
+- chore: always nyc report before calling codecov ([#88](https://github.com/googleapis/nodejs-iot/pull/88))
+- chore: nyc ignore build/test by default ([#87](https://github.com/googleapis/nodejs-iot/pull/87))
+- chore: update license file ([#85](https://github.com/googleapis/nodejs-iot/pull/85))
+- fix(build): fix system key decryption ([#81](https://github.com/googleapis/nodejs-iot/pull/81))
+- chore: add a synth.metadata
+- chore: update eslintignore config ([#74](https://github.com/googleapis/nodejs-iot/pull/74))
+- chore(deps): update dependency @google-cloud/nodejs-repo-tools to v3 ([#73](https://github.com/googleapis/nodejs-iot/pull/73))
+- chore: remove unused deps ([#71](https://github.com/googleapis/nodejs-iot/pull/71))
+- chore: drop contributors from multiple places ([#72](https://github.com/googleapis/nodejs-iot/pull/72))
+- chore: use latest npm on Windows ([#70](https://github.com/googleapis/nodejs-iot/pull/70))
+- chore: update CircleCI config ([#68](https://github.com/googleapis/nodejs-iot/pull/68))
+- chore: include build in eslintignore ([#65](https://github.com/googleapis/nodejs-iot/pull/65))
+- chore(deps): update dependency eslint-plugin-node to v8 ([#61](https://github.com/googleapis/nodejs-iot/pull/61))
+- chore: update issue templates ([#60](https://github.com/googleapis/nodejs-iot/pull/60))
+- chore: remove old issue template ([#58](https://github.com/googleapis/nodejs-iot/pull/58))
+- build: run tests on node11 ([#57](https://github.com/googleapis/nodejs-iot/pull/57))
+- chores(build): do not collect sponge.xml from windows builds ([#56](https://github.com/googleapis/nodejs-iot/pull/56))
+- chores(build): run codecov on continuous builds ([#55](https://github.com/googleapis/nodejs-iot/pull/55))
+- chore: update new issue template ([#54](https://github.com/googleapis/nodejs-iot/pull/54))
+- build: fix codecov uploading on Kokoro ([#51](https://github.com/googleapis/nodejs-iot/pull/51))
+- Update kokoro config ([#49](https://github.com/googleapis/nodejs-iot/pull/49))
+- chore(deps): update dependency eslint-plugin-prettier to v3 ([#48](https://github.com/googleapis/nodejs-iot/pull/48))
+- build: prevent system/sample-test from leaking credentials
+- Update the kokoro config ([#45](https://github.com/googleapis/nodejs-iot/pull/45))
+- test: remove appveyor config ([#44](https://github.com/googleapis/nodejs-iot/pull/44))
+- Update the CI config ([#43](https://github.com/googleapis/nodejs-iot/pull/43))
+- Enable prefer-const in the eslint config ([#41](https://github.com/googleapis/nodejs-iot/pull/41))
+- Enable no-var in eslint ([#40](https://github.com/googleapis/nodejs-iot/pull/40))
+- Switch to let/const ([#39](https://github.com/googleapis/nodejs-iot/pull/39))
+- Update CI config ([#37](https://github.com/googleapis/nodejs-iot/pull/37))
+- Retry npm install in CI ([#35](https://github.com/googleapis/nodejs-iot/pull/35))
+- Update CI config ([#32](https://github.com/googleapis/nodejs-iot/pull/32))
+- Re-generate library using /synth.py ([#31](https://github.com/googleapis/nodejs-iot/pull/31))
+- chore(deps): update dependency nyc to v13 ([#30](https://github.com/googleapis/nodejs-iot/pull/30))
+- chore(deps): update dependency eslint-config-prettier to v3 ([#26](https://github.com/googleapis/nodejs-iot/pull/26))
+- chore: do not use npm ci ([#25](https://github.com/googleapis/nodejs-iot/pull/25))
+- chore: ignore package-lock.json ([#24](https://github.com/googleapis/nodejs-iot/pull/24))
+- chore(deps): lock file maintenance ([#23](https://github.com/googleapis/nodejs-iot/pull/23))
+- chore(deps): lock file maintenance ([#22](https://github.com/googleapis/nodejs-iot/pull/22))
+- chore: update renovate config ([#21](https://github.com/googleapis/nodejs-iot/pull/21))
+- test: throw on deprecation ([#20](https://github.com/googleapis/nodejs-iot/pull/20))
+- chore(deps): lock file maintenance ([#18](https://github.com/googleapis/nodejs-iot/pull/18))
+- chore: move mocha options to mocha.opts ([#16](https://github.com/googleapis/nodejs-iot/pull/16))
+- chore: require node 8 for samples ([#17](https://github.com/googleapis/nodejs-iot/pull/17))
+
+## v0.1.1
+
+### Dependencies
+- chore(deps): update dependency eslint-plugin-node to v7 (#8)
+
+### Documentation
+- doc: fix product name, etc.. in README.md (#14)
+- Add missing JSDoc namespaces. (#9)
+
+### Internal / Testing Changes
+- chore(build): use .circleci/config.yml from synth tool template (#11)
+- test: use strictEqual in tests (#6)
+- chore: Configure Renovate (#7)
+
+## v0.1.0
+
+- Initial release of @google-cloud/iot
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000000000000000000000000000000000..2add2547a81295747bc0d97efc508cabeb161db0
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,94 @@
+<!-- # Generated by synthtool. DO NOT EDIT! !-->
+# Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of
+experience, education, socio-economic status, nationality, personal appearance,
+race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+*   Using welcoming and inclusive language
+*   Being respectful of differing viewpoints and experiences
+*   Gracefully accepting constructive criticism
+*   Focusing on what is best for the community
+*   Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+*   The use of sexualized language or imagery and unwelcome sexual attention or
+    advances
+*   Trolling, insulting/derogatory comments, and personal or political attacks
+*   Public or private harassment
+*   Publishing others' private information, such as a physical or electronic
+    address, without explicit permission
+*   Other conduct which could reasonably be considered inappropriate in a
+    professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, or to ban temporarily or permanently any
+contributor for other behaviors that they deem inappropriate, threatening,
+offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+This Code of Conduct also applies outside the project spaces when the Project
+Steward has a reasonable belief that an individual's behavior may have a
+negative impact on the project or its community.
+
+## Conflict Resolution
+
+We do not believe that all conflict is bad; healthy debate and disagreement
+often yield positive results. However, it is never okay to be disrespectful or
+to engage in behavior that violates the project’s code of conduct.
+
+If you see someone violating the code of conduct, you are encouraged to address
+the behavior directly with those involved. Many issues can be resolved quickly
+and easily, and this gives people more control over the outcome of their
+dispute. If you are unable to resolve the matter for any reason, or if the
+behavior is threatening or harassing, report it. We are dedicated to providing
+an environment where participants feel welcome and safe.
+
+Reports should be directed to *googleapis-stewards@google.com*, the
+Project Steward(s) for *Google Cloud Client Libraries*. It is the Project Steward’s duty to
+receive and address reported violations of the code of conduct. They will then
+work with a committee consisting of representatives from the Open Source
+Programs Office and the Google Open Source Strategy team. If for any reason you
+are uncomfortable reaching out to the Project Steward, please email
+opensource@google.com.
+
+We will investigate every complaint, but you may not receive a direct response.
+We will use our discretion in determining when and how to follow up on reported
+incidents, which may range from not taking action to permanent expulsion from
+the project and project-sponsored spaces. We will notify the accused of the
+report and provide them an opportunity to discuss it before any action is taken.
+The identity of the reporter will be omitted from the details of the report
+supplied to the accused. In potentially harmful situations, such as ongoing
+harassment or threats to anyone's safety, we may take action without notice.
+
+## Attribution
+
+This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
+available at
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..965598735058acf9cbcd892c9f749627fed199ee
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,76 @@
+# How to become a contributor and submit your own code
+
+**Table of contents**
+
+* [Contributor License Agreements](#contributor-license-agreements)
+* [Contributing a patch](#contributing-a-patch)
+* [Running the tests](#running-the-tests)
+* [Releasing the library](#releasing-the-library)
+
+## Contributor License Agreements
+
+We'd love to accept your sample apps and patches! Before we can take them, we
+have to jump a couple of legal hurdles.
+
+Please fill out either the individual or corporate Contributor License Agreement
+(CLA).
+
+  * If you are an individual writing original source code and you're sure you
+    own the intellectual property, then you'll need to sign an [individual CLA](https://developers.google.com/open-source/cla/individual).
+  * If you work for a company that wants to allow you to contribute your work,
+    then you'll need to sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate).
+
+Follow either of the two links above to access the appropriate CLA and
+instructions for how to sign and return it. Once we receive it, we'll be able to
+accept your pull requests.
+
+## Contributing A Patch
+
+1.  Submit an issue describing your proposed change to the repo in question.
+1.  The repo owner will respond to your issue promptly.
+1.  If your proposed change is accepted, and you haven't already done so, sign a
+    Contributor License Agreement (see details above).
+1.  Fork the desired repo, develop and test your code changes.
+1.  Ensure that your code adheres to the existing style in the code to which
+    you are contributing.
+1.  Ensure that your code has an appropriate set of tests which all pass.
+1.  Title your pull request following [Conventional Commits](https://www.conventionalcommits.org/) styling.
+1.  Submit a pull request.
+
+### Before you begin
+
+1.  [Select or create a Cloud Platform project][projects].
+1.  [Enable billing for your project][billing]. 
+1.  [Enable the Google Cloud Internet of Things (IoT) Core API][enable_api]. 
+1.  [Set up authentication with a service account][auth] so you can access the
+    API from your local workstation.
+
+
+## Running the tests
+
+1.  [Prepare your environment for Node.js setup][setup].
+
+1.  Install dependencies:
+
+        npm install
+
+1.  Run the tests:
+
+        # Run unit tests.
+        npm test
+
+        # Run sample integration tests.
+        npm run samples-test
+
+        # Run all system tests.
+        npm run system-test
+
+1.  Lint (and maybe fix) any changes:
+
+        npm run fix
+
+[setup]: https://cloud.google.com/nodejs/docs/setup
+[projects]: https://console.cloud.google.com/project
+[billing]: https://support.google.com/cloud/answer/6293499#enable-billing
+[enable_api]: https://console.cloud.google.com/flows/enableapi?apiid=cloudiot.googleapis.com
+[auth]: https://cloud.google.com/docs/authentication/getting-started
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/README.md b/README.md
index 25b555e5de3278f0b549d4747bb141ece300ed7e..05fd841a3ee92bbf7865148ccabceb9acbd130ff 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,156 @@
-# mqtt-simulator-nodejs
+[//]: # "This README.md file is auto-generated, all changes to this file will be lost."
+[//]: # "To regenerate it, use `python -m synthtool`."
+<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
 
+# [Google Cloud Internet of Things (IoT) Core: Node.js Client](https://github.com/googleapis/nodejs-iot)
+
+[![release level](https://img.shields.io/badge/release%20level-stable-brightgreen.svg?style=flat)](https://cloud.google.com/terms/launch-stages)
+[![npm version](https://img.shields.io/npm/v/@google-cloud/iot.svg)](https://www.npmjs.org/package/@google-cloud/iot)
+
+
+
+
+> Node.js idiomatic client for [Cloud IoT Core][product-docs].
+
+[Google Cloud Internet of Things (IoT) Core](https://cloud.google.com/iot/docs) is a fully managed service for securely connecting and managing IoT devices, from a few to millions. Ingest data from connected devices and build rich applications that integrate with the other big data services of Google Cloud Platform.
+
+
+A comprehensive list of changes in each version may be found in
+[the CHANGELOG](https://github.com/googleapis/nodejs-iot/blob/main/CHANGELOG.md).
+
+* [Google Cloud Internet of Things (IoT) Core Node.js Client API Reference][client-docs]
+* [Google Cloud Internet of Things (IoT) Core Documentation][product-docs]
+* [github.com/googleapis/nodejs-iot](https://github.com/googleapis/nodejs-iot)
+
+Read more about the client libraries for Cloud APIs, including the older
+Google APIs Client Libraries, in [Client Libraries Explained][explained].
+
+[explained]: https://cloud.google.com/apis/docs/client-libraries-explained
+
+**Table of contents:**
+
+
+* [Quickstart](#quickstart)
+  * [Before you begin](#before-you-begin)
+  * [Installing the client library](#installing-the-client-library)
+  * [Using the client library](#using-the-client-library)
+* [Samples](#samples)
+* [Versioning](#versioning)
+* [Contributing](#contributing)
+* [License](#license)
+
+## Quickstart
+
+### Before you begin
+
+1.  [Select or create a Cloud Platform project][projects].
+1.  [Enable billing for your project][billing].
+1.  [Enable the Google Cloud Internet of Things (IoT) Core API][enable_api].
+1.  [Set up authentication with a service account][auth] so you can access the
+    API from your local workstation.
+
+### Installing the client library
+
+```bash
+npm install @google-cloud/iot
+```
+
+
+### Using the client library
+
+```javascript
+const iot = require('@google-cloud/iot');
+const client = new iot.v1.DeviceManagerClient();
+
+async function quickstart() {
+  const projectId = await client.getProjectId();
+  const parent = client.locationPath(projectId, 'us-central1');
+  const [resources] = await client.listDeviceRegistries({parent});
+  console.log(`${resources.length} resource(s) found.`);
+  for (const resource of resources) {
+    console.log(resource);
+  }
+}
+quickstart();
+
+```
+
+
+
+## Samples
+
+Samples are in the [`samples/`](https://github.com/googleapis/nodejs-iot/tree/main/samples) directory. Each sample's `README.md` has instructions for running its sample.
+
+| Sample                      | Source Code                       | Try it |
+| --------------------------- | --------------------------------- | ------ |
+| Quickstart | [source code](https://github.com/googleapis/nodejs-iot/blob/main/samples/quickstart.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-iot&page=editor&open_in_editor=samples/quickstart.js,samples/README.md) |
+
+
+
+The [Google Cloud Internet of Things (IoT) Core Node.js Client API Reference][client-docs] documentation
+also contains samples.
+
+## Supported Node.js Versions
+
+Our client libraries follow the [Node.js release schedule](https://nodejs.org/en/about/releases/).
+Libraries are compatible with all current _active_ and _maintenance_ versions of
+Node.js.
+If you are using an end-of-life version of Node.js, we recommend that you update
+as soon as possible to an actively supported LTS version.
+
+Google's client libraries support legacy versions of Node.js runtimes on a
+best-efforts basis with the following warnings:
+
+* Legacy versions are not tested in continuous integration.
+* Some security patches and features cannot be backported.
+* Dependencies cannot be kept up-to-date.
+
+Client libraries targeting some end-of-life versions of Node.js are available, and
+can be installed through npm [dist-tags](https://docs.npmjs.com/cli/dist-tag).
+The dist-tags follow the naming convention `legacy-(version)`.
+For example, `npm install @google-cloud/iot@legacy-8` installs client libraries
+for versions compatible with Node.js 8.
+
+## Versioning
+
+This library follows [Semantic Versioning](http://semver.org/).
+
+
+
+This library is considered to be **stable**. The code surface will not change in backwards-incompatible ways
+unless absolutely necessary (e.g. because of critical security issues) or with
+an extensive deprecation period. Issues and requests against **stable** libraries
+are addressed with the highest priority.
+
+
+
+
+
+
+More Information: [Google Cloud Platform Launch Stages][launch_stages]
+
+[launch_stages]: https://cloud.google.com/terms/launch-stages
+
+## Contributing
+
+Contributions welcome! See the [Contributing Guide](https://github.com/googleapis/nodejs-iot/blob/main/CONTRIBUTING.md).
+
+Please note that this `README.md`, the `samples/README.md`,
+and a variety of configuration files in this repository (including `.nycrc` and `tsconfig.json`)
+are generated from a central template. To edit one of these files, make an edit
+to its templates in
+[directory](https://github.com/googleapis/synthtool).
+
+## License
+
+Apache Version 2.0
+
+See [LICENSE](https://github.com/googleapis/nodejs-iot/blob/main/LICENSE)
+
+[client-docs]: https://cloud.google.com/nodejs/docs/reference/iot/latest
+[product-docs]: https://cloud.google.com/iot
+[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png
+[projects]: https://console.cloud.google.com/project
+[billing]: https://support.google.com/cloud/answer/6293499#enable-billing
+[enable_api]: https://console.cloud.google.com/flows/enableapi?apiid=cloudiot.googleapis.com
+[auth]: https://cloud.google.com/docs/authentication/getting-started
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000000000000000000000000000000000..8b58ae9c01ae3b07eeba325544a99071e0713f31
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,7 @@
+# Security Policy
+
+To report a security issue, please use [g.co/vulnz](https://g.co/vulnz).
+
+The Google Security Team will respond within 5 working days of your report on g.co/vulnz.
+
+We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue.
diff --git a/linkinator.config.json b/linkinator.config.json
new file mode 100644
index 0000000000000000000000000000000000000000..befd23c86335b343d44af2ad2388bc306067b04f
--- /dev/null
+++ b/linkinator.config.json
@@ -0,0 +1,16 @@
+{
+  "recurse": true,
+  "skip": [
+    "https://codecov.io/gh/googleapis/",
+    "www.googleapis.com",
+    "img.shields.io",
+    "https://console.cloud.google.com/cloudshell",
+    "https://support.google.com"
+  ],
+  "silent": true,
+  "concurrency": 5,
+  "retry": true,
+  "retryErrors": true,
+  "retryErrorsCount": 5,
+  "retryErrorsJitter": 3000
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..65361f122fa1b8ecfb3dc0c8bc7d7bd1f2e986aa
--- /dev/null
+++ b/package.json
@@ -0,0 +1,67 @@
+{
+  "name": "@google-cloud/iot",
+  "description": "Cloud IoT API client for Node.js",
+  "version": "3.1.0",
+  "license": "Apache-2.0",
+  "author": "Google LLC",
+  "engines": {
+    "node": ">=12.0.0"
+  },
+  "repository": "googleapis/nodejs-iot",
+  "main": "build/src/index.js",
+  "files": [
+    "build/protos",
+    "build/src"
+  ],
+  "keywords": [
+    "google apis client",
+    "google api client",
+    "google apis",
+    "google api",
+    "google",
+    "google cloud platform",
+    "google cloud",
+    "cloud",
+    "google iot",
+    "iot",
+    "Cloud IoT API"
+  ],
+  "scripts": {
+    "test": "c8 mocha build/test",
+    "samples-test": "cd samples/ && npm link ../ && npm install && npm test && cd ../",
+    "lint": "gts check",
+    "docs": "jsdoc -c .jsdoc.js",
+    "system-test": "mocha build/system-test",
+    "fix": "gts fix",
+    "docs-test": "linkinator docs",
+    "predocs-test": "npm run docs",
+    "clean": "gts clean",
+    "compile": "tsc -p . && cp -r protos build/",
+    "compile-protos": "compileProtos src",
+    "prepare": "npm run compile",
+    "prelint": "cd samples; npm link ../; npm install",
+    "precompile": "gts clean"
+  },
+  "dependencies": {
+    "google-gax": "^3.0.1"
+  },
+  "devDependencies": {
+    "@types/mocha": "^9.0.0",
+    "@types/node": "^16.0.0",
+    "@types/sinon": "^10.0.0",
+    "c8": "^7.2.1",
+    "gts": "^3.1.0",
+    "jsdoc": "^3.6.2",
+    "jsdoc-fresh": "^2.0.0",
+    "jsdoc-region-tag": "^2.0.0",
+    "linkinator": "^4.0.0",
+    "mocha": "^9.2.2",
+    "null-loader": "^4.0.0",
+    "pack-n-play": "^1.0.0-2",
+    "sinon": "^14.0.0",
+    "ts-loader": "^9.0.0",
+    "typescript": "^4.6.4",
+    "webpack": "^5.0.0",
+    "webpack-cli": "^4.0.0"
+  }
+}
diff --git a/protos/google/cloud/common_resources.proto b/protos/google/cloud/common_resources.proto
new file mode 100644
index 0000000000000000000000000000000000000000..56c9f800d5e35e8866f389128dac33c1fec3c318
--- /dev/null
+++ b/protos/google/cloud/common_resources.proto
@@ -0,0 +1,52 @@
+// Copyright 2019 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.
+
+// This file contains stub messages for common resources in GCP.
+// It is not intended to be directly generated, and is instead used by
+// other tooling to be able to match common resource patterns.
+syntax = "proto3";
+
+package google.cloud;
+
+import "google/api/resource.proto";
+
+
+option (google.api.resource_definition) = {
+  type: "cloudresourcemanager.googleapis.com/Project"
+  pattern: "projects/{project}"
+};
+
+
+option (google.api.resource_definition) = {
+  type: "cloudresourcemanager.googleapis.com/Organization"
+  pattern: "organizations/{organization}"
+};
+
+
+option (google.api.resource_definition) = {
+  type: "cloudresourcemanager.googleapis.com/Folder"
+  pattern: "folders/{folder}"
+};
+
+
+option (google.api.resource_definition) = {
+  type: "cloudbilling.googleapis.com/BillingAccount"
+  pattern: "billingAccounts/{billing_account}"
+};
+
+option (google.api.resource_definition) = {
+  type: "locations.googleapis.com/Location"
+  pattern: "projects/{project}/locations/{location}"
+};
+
diff --git a/protos/google/cloud/iot/v1/device_manager.proto b/protos/google/cloud/iot/v1/device_manager.proto
new file mode 100644
index 0000000000000000000000000000000000000000..dfd6c9b6af81977d2834445a88b4a91f47cbb632
--- /dev/null
+++ b/protos/google/cloud/iot/v1/device_manager.proto
@@ -0,0 +1,652 @@
+// Copyright 2020 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.
+
+syntax = "proto3";
+
+package google.cloud.iot.v1;
+
+import "google/api/annotations.proto";
+import "google/api/client.proto";
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/cloud/iot/v1/resources.proto";
+import "google/iam/v1/iam_policy.proto";
+import "google/iam/v1/policy.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/field_mask.proto";
+import "google/rpc/status.proto";
+
+option cc_enable_arenas = true;
+option go_package = "google.golang.org/genproto/googleapis/cloud/iot/v1;iot";
+option java_multiple_files = true;
+option java_outer_classname = "DeviceManagerProto";
+option java_package = "com.google.cloud.iot.v1";
+
+// Internet of Things (IoT) service. Securely connect and manage IoT devices.
+service DeviceManager {
+  option (google.api.default_host) = "cloudiot.googleapis.com";
+  option (google.api.oauth_scopes) =
+      "https://www.googleapis.com/auth/cloud-platform,"
+      "https://www.googleapis.com/auth/cloudiot";
+
+  // Creates a device registry that contains devices.
+  rpc CreateDeviceRegistry(CreateDeviceRegistryRequest) returns (DeviceRegistry) {
+    option (google.api.http) = {
+      post: "/v1/{parent=projects/*/locations/*}/registries"
+      body: "device_registry"
+    };
+    option (google.api.method_signature) = "parent,device_registry";
+  }
+
+  // Gets a device registry configuration.
+  rpc GetDeviceRegistry(GetDeviceRegistryRequest) returns (DeviceRegistry) {
+    option (google.api.http) = {
+      get: "/v1/{name=projects/*/locations/*/registries/*}"
+    };
+    option (google.api.method_signature) = "name";
+  }
+
+  // Updates a device registry configuration.
+  rpc UpdateDeviceRegistry(UpdateDeviceRegistryRequest) returns (DeviceRegistry) {
+    option (google.api.http) = {
+      patch: "/v1/{device_registry.name=projects/*/locations/*/registries/*}"
+      body: "device_registry"
+    };
+    option (google.api.method_signature) = "device_registry,update_mask";
+  }
+
+  // Deletes a device registry configuration.
+  rpc DeleteDeviceRegistry(DeleteDeviceRegistryRequest) returns (google.protobuf.Empty) {
+    option (google.api.http) = {
+      delete: "/v1/{name=projects/*/locations/*/registries/*}"
+    };
+    option (google.api.method_signature) = "name";
+  }
+
+  // Lists device registries.
+  rpc ListDeviceRegistries(ListDeviceRegistriesRequest) returns (ListDeviceRegistriesResponse) {
+    option (google.api.http) = {
+      get: "/v1/{parent=projects/*/locations/*}/registries"
+    };
+    option (google.api.method_signature) = "parent";
+  }
+
+  // Creates a device in a device registry.
+  rpc CreateDevice(CreateDeviceRequest) returns (Device) {
+    option (google.api.http) = {
+      post: "/v1/{parent=projects/*/locations/*/registries/*}/devices"
+      body: "device"
+    };
+    option (google.api.method_signature) = "parent,device";
+  }
+
+  // Gets details about a device.
+  rpc GetDevice(GetDeviceRequest) returns (Device) {
+    option (google.api.http) = {
+      get: "/v1/{name=projects/*/locations/*/registries/*/devices/*}"
+      additional_bindings {
+        get: "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}"
+      }
+    };
+    option (google.api.method_signature) = "name";
+  }
+
+  // Updates a device.
+  rpc UpdateDevice(UpdateDeviceRequest) returns (Device) {
+    option (google.api.http) = {
+      patch: "/v1/{device.name=projects/*/locations/*/registries/*/devices/*}"
+      body: "device"
+      additional_bindings {
+        patch: "/v1/{device.name=projects/*/locations/*/registries/*/groups/*/devices/*}"
+        body: "device"
+      }
+    };
+    option (google.api.method_signature) = "device,update_mask";
+  }
+
+  // Deletes a device.
+  rpc DeleteDevice(DeleteDeviceRequest) returns (google.protobuf.Empty) {
+    option (google.api.http) = {
+      delete: "/v1/{name=projects/*/locations/*/registries/*/devices/*}"
+    };
+    option (google.api.method_signature) = "name";
+  }
+
+  // List devices in a device registry.
+  rpc ListDevices(ListDevicesRequest) returns (ListDevicesResponse) {
+    option (google.api.http) = {
+      get: "/v1/{parent=projects/*/locations/*/registries/*}/devices"
+      additional_bindings {
+        get: "/v1/{parent=projects/*/locations/*/registries/*/groups/*}/devices"
+      }
+    };
+    option (google.api.method_signature) = "parent";
+  }
+
+  // Modifies the configuration for the device, which is eventually sent from
+  // the Cloud IoT Core servers. Returns the modified configuration version and
+  // its metadata.
+  rpc ModifyCloudToDeviceConfig(ModifyCloudToDeviceConfigRequest) returns (DeviceConfig) {
+    option (google.api.http) = {
+      post: "/v1/{name=projects/*/locations/*/registries/*/devices/*}:modifyCloudToDeviceConfig"
+      body: "*"
+      additional_bindings {
+        post: "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}:modifyCloudToDeviceConfig"
+        body: "*"
+      }
+    };
+    option (google.api.method_signature) = "name,binary_data";
+  }
+
+  // Lists the last few versions of the device configuration in descending
+  // order (i.e.: newest first).
+  rpc ListDeviceConfigVersions(ListDeviceConfigVersionsRequest) returns (ListDeviceConfigVersionsResponse) {
+    option (google.api.http) = {
+      get: "/v1/{name=projects/*/locations/*/registries/*/devices/*}/configVersions"
+      additional_bindings {
+        get: "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}/configVersions"
+      }
+    };
+    option (google.api.method_signature) = "name";
+  }
+
+  // Lists the last few versions of the device state in descending order (i.e.:
+  // newest first).
+  rpc ListDeviceStates(ListDeviceStatesRequest) returns (ListDeviceStatesResponse) {
+    option (google.api.http) = {
+      get: "/v1/{name=projects/*/locations/*/registries/*/devices/*}/states"
+      additional_bindings {
+        get: "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}/states"
+      }
+    };
+    option (google.api.method_signature) = "name";
+  }
+
+  // Sets the access control policy on the specified resource. Replaces any
+  // existing policy.
+  rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest) returns (google.iam.v1.Policy) {
+    option (google.api.http) = {
+      post: "/v1/{resource=projects/*/locations/*/registries/*}:setIamPolicy"
+      body: "*"
+      additional_bindings {
+        post: "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:setIamPolicy"
+        body: "*"
+      }
+    };
+    option (google.api.method_signature) = "resource,policy";
+  }
+
+  // Gets the access control policy for a resource.
+  // Returns an empty policy if the resource exists and does not have a policy
+  // set.
+  rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest) returns (google.iam.v1.Policy) {
+    option (google.api.http) = {
+      post: "/v1/{resource=projects/*/locations/*/registries/*}:getIamPolicy"
+      body: "*"
+      additional_bindings {
+        post: "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:getIamPolicy"
+        body: "*"
+      }
+    };
+    option (google.api.method_signature) = "resource";
+  }
+
+  // Returns permissions that a caller has on the specified resource.
+  // If the resource does not exist, this will return an empty set of
+  // permissions, not a NOT_FOUND error.
+  rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest) returns (google.iam.v1.TestIamPermissionsResponse) {
+    option (google.api.http) = {
+      post: "/v1/{resource=projects/*/locations/*/registries/*}:testIamPermissions"
+      body: "*"
+      additional_bindings {
+        post: "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:testIamPermissions"
+        body: "*"
+      }
+    };
+    option (google.api.method_signature) = "resource,permissions";
+  }
+
+  // Sends a command to the specified device. In order for a device to be able
+  // to receive commands, it must:
+  // 1) be connected to Cloud IoT Core using the MQTT protocol, and
+  // 2) be subscribed to the group of MQTT topics specified by
+  //    /devices/{device-id}/commands/#. This subscription will receive commands
+  //    at the top-level topic /devices/{device-id}/commands as well as commands
+  //    for subfolders, like /devices/{device-id}/commands/subfolder.
+  //    Note that subscribing to specific subfolders is not supported.
+  // If the command could not be delivered to the device, this method will
+  // return an error; in particular, if the device is not subscribed, this
+  // method will return FAILED_PRECONDITION. Otherwise, this method will
+  // return OK. If the subscription is QoS 1, at least once delivery will be
+  // guaranteed; for QoS 0, no acknowledgment will be expected from the device.
+  rpc SendCommandToDevice(SendCommandToDeviceRequest) returns (SendCommandToDeviceResponse) {
+    option (google.api.http) = {
+      post: "/v1/{name=projects/*/locations/*/registries/*/devices/*}:sendCommandToDevice"
+      body: "*"
+      additional_bindings {
+        post: "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}:sendCommandToDevice"
+        body: "*"
+      }
+    };
+    option (google.api.method_signature) = "name,binary_data";
+    option (google.api.method_signature) = "name,binary_data,subfolder";
+  }
+
+  // Associates the device with the gateway.
+  rpc BindDeviceToGateway(BindDeviceToGatewayRequest) returns (BindDeviceToGatewayResponse) {
+    option (google.api.http) = {
+      post: "/v1/{parent=projects/*/locations/*/registries/*}:bindDeviceToGateway"
+      body: "*"
+      additional_bindings {
+        post: "/v1/{parent=projects/*/locations/*/registries/*/groups/*}:bindDeviceToGateway"
+        body: "*"
+      }
+    };
+    option (google.api.method_signature) = "parent,gateway_id,device_id";
+  }
+
+  // Deletes the association between the device and the gateway.
+  rpc UnbindDeviceFromGateway(UnbindDeviceFromGatewayRequest) returns (UnbindDeviceFromGatewayResponse) {
+    option (google.api.http) = {
+      post: "/v1/{parent=projects/*/locations/*/registries/*}:unbindDeviceFromGateway"
+      body: "*"
+      additional_bindings {
+        post: "/v1/{parent=projects/*/locations/*/registries/*/groups/*}:unbindDeviceFromGateway"
+        body: "*"
+      }
+    };
+    option (google.api.method_signature) = "parent,gateway_id,device_id";
+  }
+}
+
+// Request for `CreateDeviceRegistry`.
+message CreateDeviceRegistryRequest {
+  // Required. The project and cloud region where this device registry must be created.
+  // For example, `projects/example-project/locations/us-central1`.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "locations.googleapis.com/Location"
+    }
+  ];
+
+  // Required. The device registry. The field `name` must be empty. The server will
+  // generate that field from the device registry `id` provided and the
+  // `parent` field.
+  DeviceRegistry device_registry = 2 [(google.api.field_behavior) = REQUIRED];
+}
+
+// Request for `GetDeviceRegistry`.
+message GetDeviceRegistryRequest {
+  // Required. The name of the device registry. For example,
+  // `projects/example-project/locations/us-central1/registries/my-registry`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Registry"
+    }
+  ];
+}
+
+// Request for `DeleteDeviceRegistry`.
+message DeleteDeviceRegistryRequest {
+  // Required. The name of the device registry. For example,
+  // `projects/example-project/locations/us-central1/registries/my-registry`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Registry"
+    }
+  ];
+}
+
+// Request for `UpdateDeviceRegistry`.
+message UpdateDeviceRegistryRequest {
+  // Required. The new values for the device registry. The `id` field must be empty, and
+  // the `name` field must indicate the path of the resource. For example,
+  // `projects/example-project/locations/us-central1/registries/my-registry`.
+  DeviceRegistry device_registry = 1 [(google.api.field_behavior) = REQUIRED];
+
+  // Required. Only updates the `device_registry` fields indicated by this mask.
+  // The field mask must not be empty, and it must not contain fields that
+  // are immutable or only set by the server.
+  // Mutable top-level fields: `event_notification_config`, `http_config`,
+  // `mqtt_config`, and `state_notification_config`.
+  google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = REQUIRED];
+}
+
+// Request for `ListDeviceRegistries`.
+message ListDeviceRegistriesRequest {
+  // Required. The project and cloud region path. For example,
+  // `projects/example-project/locations/us-central1`.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "locations.googleapis.com/Location"
+    }
+  ];
+
+  // The maximum number of registries to return in the response. If this value
+  // is zero, the service will select a default size. A call may return fewer
+  // objects than requested. A non-empty `next_page_token` in the response
+  // indicates that more data is available.
+  int32 page_size = 2;
+
+  // The value returned by the last `ListDeviceRegistriesResponse`; indicates
+  // that this is a continuation of a prior `ListDeviceRegistries` call and
+  // the system should return the next page of data.
+  string page_token = 3;
+}
+
+// Response for `ListDeviceRegistries`.
+message ListDeviceRegistriesResponse {
+  // The registries that matched the query.
+  repeated DeviceRegistry device_registries = 1;
+
+  // If not empty, indicates that there may be more registries that match the
+  // request; this value should be passed in a new
+  // `ListDeviceRegistriesRequest`.
+  string next_page_token = 2;
+}
+
+// Request for `CreateDevice`.
+message CreateDeviceRequest {
+  // Required. The name of the device registry where this device should be created.
+  // For example,
+  // `projects/example-project/locations/us-central1/registries/my-registry`.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Registry"
+    }
+  ];
+
+  // Required. The device registration details. The field `name` must be empty. The server
+  // generates `name` from the device registry `id` and the
+  // `parent` field.
+  Device device = 2 [(google.api.field_behavior) = REQUIRED];
+}
+
+// Request for `GetDevice`.
+message GetDeviceRequest {
+  // Required. The name of the device. For example,
+  // `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+  // `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Device"
+    }
+  ];
+
+  // The fields of the `Device` resource to be returned in the response. If the
+  // field mask is unset or empty, all fields are returned. Fields have to be
+  // provided in snake_case format, for example: `last_heartbeat_time`.
+  google.protobuf.FieldMask field_mask = 2;
+}
+
+// Request for `UpdateDevice`.
+message UpdateDeviceRequest {
+  // Required. The new values for the device. The `id` and `num_id` fields must
+  // be empty, and the field `name` must specify the name path. For example,
+  // `projects/p0/locations/us-central1/registries/registry0/devices/device0`or
+  // `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+  Device device = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // Required. Only updates the `device` fields indicated by this mask.
+  // The field mask must not be empty, and it must not contain fields that
+  // are immutable or only set by the server.
+  // Mutable top-level fields: `credentials`, `blocked`, and `metadata`
+  google.protobuf.FieldMask update_mask = 3 [(google.api.field_behavior) = REQUIRED];
+}
+
+// Request for `DeleteDevice`.
+message DeleteDeviceRequest {
+  // Required. The name of the device. For example,
+  // `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+  // `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Device"
+    }
+  ];
+}
+
+// Request for `ListDevices`.
+message ListDevicesRequest {
+  // Required. The device registry path. Required. For example,
+  // `projects/my-project/locations/us-central1/registries/my-registry`.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Registry"
+    }
+  ];
+
+  // A list of device numeric IDs. If empty, this field is ignored. Maximum
+  // IDs: 10,000.
+  repeated uint64 device_num_ids = 2;
+
+  // A list of device string IDs. For example, `['device0', 'device12']`.
+  // If empty, this field is ignored. Maximum IDs: 10,000
+  repeated string device_ids = 3;
+
+  // The fields of the `Device` resource to be returned in the response. The
+  // fields `id` and `num_id` are always returned, along with any
+  // other fields specified in snake_case format, for example:
+  // `last_heartbeat_time`.
+  google.protobuf.FieldMask field_mask = 4;
+
+  // Options related to gateways.
+  GatewayListOptions gateway_list_options = 6;
+
+  // The maximum number of devices to return in the response. If this value
+  // is zero, the service will select a default size. A call may return fewer
+  // objects than requested. A non-empty `next_page_token` in the response
+  // indicates that more data is available.
+  int32 page_size = 100;
+
+  // The value returned by the last `ListDevicesResponse`; indicates
+  // that this is a continuation of a prior `ListDevices` call and
+  // the system should return the next page of data.
+  string page_token = 101;
+}
+
+// Options for limiting the list based on gateway type and associations.
+message GatewayListOptions {
+  // If not set, all devices and gateways are returned. If set, the list is
+  // filtered based on gateway type and associations.
+  oneof filter {
+    // If `GATEWAY` is specified, only gateways are returned. If `NON_GATEWAY`
+    // is specified, only non-gateway devices are returned. If
+    // `GATEWAY_TYPE_UNSPECIFIED` is specified, all devices are returned.
+    GatewayType gateway_type = 1;
+
+    // If set, only devices associated with the specified gateway are returned.
+    // The gateway ID can be numeric (`num_id`) or the user-defined string
+    // (`id`). For example, if `123` is specified, only devices bound to the
+    // gateway with `num_id` 123 are returned.
+    string associations_gateway_id = 2;
+
+    // If set, returns only the gateways with which the specified device is
+    // associated. The device ID can be numeric (`num_id`) or the user-defined
+    // string (`id`). For example, if `456` is specified, returns only the
+    // gateways to which the device with `num_id` 456 is bound.
+    string associations_device_id = 3;
+  }
+}
+
+// Response for `ListDevices`.
+message ListDevicesResponse {
+  // The devices that match the request.
+  repeated Device devices = 1;
+
+  // If not empty, indicates that there may be more devices that match the
+  // request; this value should be passed in a new `ListDevicesRequest`.
+  string next_page_token = 2;
+}
+
+// Request for `ModifyCloudToDeviceConfig`.
+message ModifyCloudToDeviceConfigRequest {
+  // Required. The name of the device. For example,
+  // `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+  // `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Device"
+    }
+  ];
+
+  // The version number to update. If this value is zero, it will not check the
+  // version number of the server and will always update the current version;
+  // otherwise, this update will fail if the version number found on the server
+  // does not match this version number. This is used to support multiple
+  // simultaneous updates without losing data.
+  int64 version_to_update = 2;
+
+  // Required. The configuration data for the device.
+  bytes binary_data = 3 [(google.api.field_behavior) = REQUIRED];
+}
+
+// Request for `ListDeviceConfigVersions`.
+message ListDeviceConfigVersionsRequest {
+  // Required. The name of the device. For example,
+  // `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+  // `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Device"
+    }
+  ];
+
+  // The number of versions to list. Versions are listed in decreasing order of
+  // the version number. The maximum number of versions retained is 10. If this
+  // value is zero, it will return all the versions available.
+  int32 num_versions = 2;
+}
+
+// Response for `ListDeviceConfigVersions`.
+message ListDeviceConfigVersionsResponse {
+  // The device configuration for the last few versions. Versions are listed
+  // in decreasing order, starting from the most recent one.
+  repeated DeviceConfig device_configs = 1;
+}
+
+// Request for `ListDeviceStates`.
+message ListDeviceStatesRequest {
+  // Required. The name of the device. For example,
+  // `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+  // `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Device"
+    }
+  ];
+
+  // The number of states to list. States are listed in descending order of
+  // update time. The maximum number of states retained is 10. If this
+  // value is zero, it will return all the states available.
+  int32 num_states = 2;
+}
+
+// Response for `ListDeviceStates`.
+message ListDeviceStatesResponse {
+  // The last few device states. States are listed in descending order of server
+  // update time, starting from the most recent one.
+  repeated DeviceState device_states = 1;
+}
+
+// Request for `SendCommandToDevice`.
+message SendCommandToDeviceRequest {
+  // Required. The name of the device. For example,
+  // `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+  // `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+  string name = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Device"
+    }
+  ];
+
+  // Required. The command data to send to the device.
+  bytes binary_data = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // Optional subfolder for the command. If empty, the command will be delivered
+  // to the /devices/{device-id}/commands topic, otherwise it will be delivered
+  // to the /devices/{device-id}/commands/{subfolder} topic. Multi-level
+  // subfolders are allowed. This field must not have more than 256 characters,
+  // and must not contain any MQTT wildcards ("+" or "#") or null characters.
+  string subfolder = 3;
+}
+
+// Response for `SendCommandToDevice`.
+message SendCommandToDeviceResponse {
+
+}
+
+// Request for `BindDeviceToGateway`.
+message BindDeviceToGatewayRequest {
+  // Required. The name of the registry. For example,
+  // `projects/example-project/locations/us-central1/registries/my-registry`.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Registry"
+    }
+  ];
+
+  // Required. The value of `gateway_id` can be either the device numeric ID or the
+  // user-defined device identifier.
+  string gateway_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // Required. The device to associate with the specified gateway. The value of
+  // `device_id` can be either the device numeric ID or the user-defined device
+  // identifier.
+  string device_id = 3 [(google.api.field_behavior) = REQUIRED];
+}
+
+// Response for `BindDeviceToGateway`.
+message BindDeviceToGatewayResponse {
+
+}
+
+// Request for `UnbindDeviceFromGateway`.
+message UnbindDeviceFromGatewayRequest {
+  // Required. The name of the registry. For example,
+  // `projects/example-project/locations/us-central1/registries/my-registry`.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      type: "cloudiot.googleapis.com/Registry"
+    }
+  ];
+
+  // Required. The value of `gateway_id` can be either the device numeric ID or the
+  // user-defined device identifier.
+  string gateway_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+  // Required. The device to disassociate from the specified gateway. The value of
+  // `device_id` can be either the device numeric ID or the user-defined device
+  // identifier.
+  string device_id = 3 [(google.api.field_behavior) = REQUIRED];
+}
+
+// Response for `UnbindDeviceFromGateway`.
+message UnbindDeviceFromGatewayResponse {
+
+}
diff --git a/protos/google/cloud/iot/v1/resources.proto b/protos/google/cloud/iot/v1/resources.proto
new file mode 100644
index 0000000000000000000000000000000000000000..a14fc027ef479c8da44fc2c8e27bcb977fc76e18
--- /dev/null
+++ b/protos/google/cloud/iot/v1/resources.proto
@@ -0,0 +1,483 @@
+// Copyright 2020 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.
+
+syntax = "proto3";
+
+package google.cloud.iot.v1;
+
+import "google/api/resource.proto";
+import "google/protobuf/timestamp.proto";
+import "google/rpc/status.proto";
+
+option cc_enable_arenas = true;
+option go_package = "google.golang.org/genproto/googleapis/cloud/iot/v1;iot";
+option java_multiple_files = true;
+option java_outer_classname = "ResourcesProto";
+option java_package = "com.google.cloud.iot.v1";
+
+// The device resource.
+message Device {
+  option (google.api.resource) = {
+    type: "cloudiot.googleapis.com/Device"
+    pattern: "projects/{project}/locations/{location}/registries/{registry}/devices/{device}"
+  };
+
+  // The user-defined device identifier. The device ID must be unique
+  // within a device registry.
+  string id = 1;
+
+  // The resource path name. For example,
+  // `projects/p1/locations/us-central1/registries/registry0/devices/dev0` or
+  // `projects/p1/locations/us-central1/registries/registry0/devices/{num_id}`.
+  // When `name` is populated as a response from the service, it always ends
+  // in the device numeric ID.
+  string name = 2;
+
+  // [Output only] A server-defined unique numeric ID for the device. This is a
+  // more compact way to identify devices, and it is globally unique.
+  uint64 num_id = 3;
+
+  // The credentials used to authenticate this device. To allow credential
+  // rotation without interruption, multiple device credentials can be bound to
+  // this device. No more than 3 credentials can be bound to a single device at
+  // a time. When new credentials are added to a device, they are verified
+  // against the registry credentials. For details, see the description of the
+  // `DeviceRegistry.credentials` field.
+  repeated DeviceCredential credentials = 12;
+
+  // [Output only] The last time an MQTT `PINGREQ` was received. This field
+  // applies only to devices connecting through MQTT. MQTT clients usually only
+  // send `PINGREQ` messages if the connection is idle, and no other messages
+  // have been sent. Timestamps are periodically collected and written to
+  // storage; they may be stale by a few minutes.
+  google.protobuf.Timestamp last_heartbeat_time = 7;
+
+  // [Output only] The last time a telemetry event was received. Timestamps are
+  // periodically collected and written to storage; they may be stale by a few
+  // minutes.
+  google.protobuf.Timestamp last_event_time = 8;
+
+  // [Output only] The last time a state event was received. Timestamps are
+  // periodically collected and written to storage; they may be stale by a few
+  // minutes.
+  google.protobuf.Timestamp last_state_time = 20;
+
+  // [Output only] The last time a cloud-to-device config version acknowledgment
+  // was received from the device. This field is only for configurations
+  // sent through MQTT.
+  google.protobuf.Timestamp last_config_ack_time = 14;
+
+  // [Output only] The last time a cloud-to-device config version was sent to
+  // the device.
+  google.protobuf.Timestamp last_config_send_time = 18;
+
+  // If a device is blocked, connections or requests from this device will fail.
+  // Can be used to temporarily prevent the device from connecting if, for
+  // example, the sensor is generating bad data and needs maintenance.
+  bool blocked = 19;
+
+  // [Output only] The time the most recent error occurred, such as a failure to
+  // publish to Cloud Pub/Sub. This field is the timestamp of
+  // 'last_error_status'.
+  google.protobuf.Timestamp last_error_time = 10;
+
+  // [Output only] The error message of the most recent error, such as a failure
+  // to publish to Cloud Pub/Sub. 'last_error_time' is the timestamp of this
+  // field. If no errors have occurred, this field has an empty message
+  // and the status code 0 == OK. Otherwise, this field is expected to have a
+  // status code other than OK.
+  google.rpc.Status last_error_status = 11;
+
+  // The most recent device configuration, which is eventually sent from
+  // Cloud IoT Core to the device. If not present on creation, the
+  // configuration will be initialized with an empty payload and version value
+  // of `1`. To update this field after creation, use the
+  // `DeviceManager.ModifyCloudToDeviceConfig` method.
+  DeviceConfig config = 13;
+
+  // [Output only] The state most recently received from the device. If no state
+  // has been reported, this field is not present.
+  DeviceState state = 16;
+
+  // **Beta Feature**
+  //
+  // The logging verbosity for device activity. If unspecified,
+  // DeviceRegistry.log_level will be used.
+  LogLevel log_level = 21;
+
+  // The metadata key-value pairs assigned to the device. This metadata is not
+  // interpreted or indexed by Cloud IoT Core. It can be used to add contextual
+  // information for the device.
+  //
+  // Keys must conform to the regular expression [a-zA-Z][a-zA-Z0-9-_.+~%]+ and
+  // be less than 128 bytes in length.
+  //
+  // Values are free-form strings. Each value must be less than or equal to 32
+  // KB in size.
+  //
+  // The total size of all keys and values must be less than 256 KB, and the
+  // maximum number of key-value pairs is 500.
+  map<string, string> metadata = 17;
+
+  // Gateway-related configuration and state.
+  GatewayConfig gateway_config = 24;
+}
+
+// Gateway-related configuration and state.
+message GatewayConfig {
+  // Indicates whether the device is a gateway.
+  GatewayType gateway_type = 1;
+
+  // Indicates how to authorize and/or authenticate devices to access the
+  // gateway.
+  GatewayAuthMethod gateway_auth_method = 2;
+
+  // [Output only] The ID of the gateway the device accessed most recently.
+  string last_accessed_gateway_id = 3;
+
+  // [Output only] The most recent time at which the device accessed the gateway
+  // specified in `last_accessed_gateway`.
+  google.protobuf.Timestamp last_accessed_gateway_time = 4;
+}
+
+// A container for a group of devices.
+message DeviceRegistry {
+  option (google.api.resource) = {
+    type: "cloudiot.googleapis.com/Registry"
+    pattern: "projects/{project}/locations/{location}/registries/{registry}"
+  };
+
+  // The identifier of this device registry. For example, `myRegistry`.
+  string id = 1;
+
+  // The resource path name. For example,
+  // `projects/example-project/locations/us-central1/registries/my-registry`.
+  string name = 2;
+
+  // The configuration for notification of telemetry events received from the
+  // device. All telemetry events that were successfully published by the
+  // device and acknowledged by Cloud IoT Core are guaranteed to be
+  // delivered to Cloud Pub/Sub. If multiple configurations match a message,
+  // only the first matching configuration is used. If you try to publish a
+  // device telemetry event using MQTT without specifying a Cloud Pub/Sub topic
+  // for the device's registry, the connection closes automatically. If you try
+  // to do so using an HTTP connection, an error is returned. Up to 10
+  // configurations may be provided.
+  repeated EventNotificationConfig event_notification_configs = 10;
+
+  // The configuration for notification of new states received from the device.
+  // State updates are guaranteed to be stored in the state history, but
+  // notifications to Cloud Pub/Sub are not guaranteed. For example, if
+  // permissions are misconfigured or the specified topic doesn't exist, no
+  // notification will be published but the state will still be stored in Cloud
+  // IoT Core.
+  StateNotificationConfig state_notification_config = 7;
+
+  // The MQTT configuration for this device registry.
+  MqttConfig mqtt_config = 4;
+
+  // The DeviceService (HTTP) configuration for this device registry.
+  HttpConfig http_config = 9;
+
+  // **Beta Feature**
+  //
+  // The default logging verbosity for activity from devices in this registry.
+  // The verbosity level can be overridden by Device.log_level.
+  LogLevel log_level = 11;
+
+  // The credentials used to verify the device credentials. No more than 10
+  // credentials can be bound to a single registry at a time. The verification
+  // process occurs at the time of device creation or update. If this field is
+  // empty, no verification is performed. Otherwise, the credentials of a newly
+  // created device or added credentials of an updated device should be signed
+  // with one of these registry credentials.
+  //
+  // Note, however, that existing devices will never be affected by
+  // modifications to this list of credentials: after a device has been
+  // successfully created in a registry, it should be able to connect even if
+  // its registry credentials are revoked, deleted, or modified.
+  repeated RegistryCredential credentials = 8;
+}
+
+// The configuration of MQTT for a device registry.
+message MqttConfig {
+  // If enabled, allows connections using the MQTT protocol. Otherwise, MQTT
+  // connections to this registry will fail.
+  MqttState mqtt_enabled_state = 1;
+}
+
+// Indicates whether an MQTT connection is enabled or disabled. See the field
+// description for details.
+enum MqttState {
+  // No MQTT state specified. If not specified, MQTT will be enabled by default.
+  MQTT_STATE_UNSPECIFIED = 0;
+
+  // Enables a MQTT connection.
+  MQTT_ENABLED = 1;
+
+  // Disables a MQTT connection.
+  MQTT_DISABLED = 2;
+}
+
+// The configuration of the HTTP bridge for a device registry.
+message HttpConfig {
+  // If enabled, allows devices to use DeviceService via the HTTP protocol.
+  // Otherwise, any requests to DeviceService will fail for this registry.
+  HttpState http_enabled_state = 1;
+}
+
+// Indicates whether DeviceService (HTTP) is enabled or disabled for the
+// registry. See the field description for details.
+enum HttpState {
+  // No HTTP state specified. If not specified, DeviceService will be
+  // enabled by default.
+  HTTP_STATE_UNSPECIFIED = 0;
+
+  // Enables DeviceService (HTTP) service for the registry.
+  HTTP_ENABLED = 1;
+
+  // Disables DeviceService (HTTP) service for the registry.
+  HTTP_DISABLED = 2;
+}
+
+// **Beta Feature**
+//
+// The logging verbosity for device activity. Specifies which events should be
+// written to logs. For example, if the LogLevel is ERROR, only events that
+// terminate in errors will be logged. LogLevel is inclusive; enabling INFO
+// logging will also enable ERROR logging.
+enum LogLevel {
+  // No logging specified. If not specified, logging will be disabled.
+  LOG_LEVEL_UNSPECIFIED = 0;
+
+  // Disables logging.
+  NONE = 10;
+
+  // Error events will be logged.
+  ERROR = 20;
+
+  // Informational events will be logged, such as connections and
+  // disconnections.
+  INFO = 30;
+
+  // All events will be logged.
+  DEBUG = 40;
+}
+
+// Gateway type.
+enum GatewayType {
+  // If unspecified, the device is considered a non-gateway device.
+  GATEWAY_TYPE_UNSPECIFIED = 0;
+
+  // The device is a gateway.
+  GATEWAY = 1;
+
+  // The device is not a gateway.
+  NON_GATEWAY = 2;
+}
+
+// The gateway authorization/authentication method. This setting determines how
+// Cloud IoT Core authorizes/authenticate devices to access the gateway.
+enum GatewayAuthMethod {
+  // No authentication/authorization method specified. No devices are allowed to
+  // access the gateway.
+  GATEWAY_AUTH_METHOD_UNSPECIFIED = 0;
+
+  // The device is authenticated through the gateway association only. Device
+  // credentials are ignored even if provided.
+  ASSOCIATION_ONLY = 1;
+
+  // The device is authenticated through its own credentials. Gateway
+  // association is not checked.
+  DEVICE_AUTH_TOKEN_ONLY = 2;
+
+  // The device is authenticated through both device credentials and gateway
+  // association. The device must be bound to the gateway and must provide its
+  // own credentials.
+  ASSOCIATION_AND_DEVICE_AUTH_TOKEN = 3;
+}
+
+// The configuration for forwarding telemetry events.
+message EventNotificationConfig {
+  // If the subfolder name matches this string exactly, this configuration will
+  // be used. The string must not include the leading '/' character. If empty,
+  // all strings are matched. This field is used only for telemetry events;
+  // subfolders are not supported for state changes.
+  string subfolder_matches = 2;
+
+  // A Cloud Pub/Sub topic name. For example,
+  // `projects/myProject/topics/deviceEvents`.
+  string pubsub_topic_name = 1;
+}
+
+// The configuration for notification of new states received from the device.
+message StateNotificationConfig {
+  // A Cloud Pub/Sub topic name. For example,
+  // `projects/myProject/topics/deviceEvents`.
+  string pubsub_topic_name = 1;
+}
+
+// A server-stored registry credential used to validate device credentials.
+message RegistryCredential {
+  // The credential data. Reserved for expansion in the future.
+  oneof credential {
+    // A public key certificate used to verify the device credentials.
+    PublicKeyCertificate public_key_certificate = 1;
+  }
+}
+
+// Details of an X.509 certificate. For informational purposes only.
+message X509CertificateDetails {
+  // The entity that signed the certificate.
+  string issuer = 1;
+
+  // The entity the certificate and public key belong to.
+  string subject = 2;
+
+  // The time the certificate becomes valid.
+  google.protobuf.Timestamp start_time = 3;
+
+  // The time the certificate becomes invalid.
+  google.protobuf.Timestamp expiry_time = 4;
+
+  // The algorithm used to sign the certificate.
+  string signature_algorithm = 5;
+
+  // The type of public key in the certificate.
+  string public_key_type = 6;
+}
+
+// A public key certificate format and data.
+message PublicKeyCertificate {
+  // The certificate format.
+  PublicKeyCertificateFormat format = 1;
+
+  // The certificate data.
+  string certificate = 2;
+
+  // [Output only] The certificate details. Used only for X.509 certificates.
+  X509CertificateDetails x509_details = 3;
+}
+
+// The supported formats for the public key.
+enum PublicKeyCertificateFormat {
+  // The format has not been specified. This is an invalid default value and
+  // must not be used.
+  UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT = 0;
+
+  // An X.509v3 certificate ([RFC5280](https://www.ietf.org/rfc/rfc5280.txt)),
+  // encoded in base64, and wrapped by `-----BEGIN CERTIFICATE-----` and
+  // `-----END CERTIFICATE-----`.
+  X509_CERTIFICATE_PEM = 1;
+}
+
+// A server-stored device credential used for authentication.
+message DeviceCredential {
+  // The credential data. Reserved for expansion in the future.
+  oneof credential {
+    // A public key used to verify the signature of JSON Web Tokens (JWTs).
+    // When adding a new device credential, either via device creation or via
+    // modifications, this public key credential may be required to be signed by
+    // one of the registry level certificates. More specifically, if the
+    // registry contains at least one certificate, any new device credential
+    // must be signed by one of the registry certificates. As a result,
+    // when the registry contains certificates, only X.509 certificates are
+    // accepted as device credentials. However, if the registry does
+    // not contain a certificate, self-signed certificates and public keys will
+    // be accepted. New device credentials must be different from every
+    // registry-level certificate.
+    PublicKeyCredential public_key = 2;
+  }
+
+  // [Optional] The time at which this credential becomes invalid. This
+  // credential will be ignored for new client authentication requests after
+  // this timestamp; however, it will not be automatically deleted.
+  google.protobuf.Timestamp expiration_time = 6;
+}
+
+// A public key format and data.
+message PublicKeyCredential {
+  // The format of the key.
+  PublicKeyFormat format = 1;
+
+  // The key data.
+  string key = 2;
+}
+
+// The supported formats for the public key.
+enum PublicKeyFormat {
+  // The format has not been specified. This is an invalid default value and
+  // must not be used.
+  UNSPECIFIED_PUBLIC_KEY_FORMAT = 0;
+
+  // An RSA public key encoded in base64, and wrapped by
+  // `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----`. This can be
+  // used to verify `RS256` signatures in JWT tokens ([RFC7518](
+  // https://www.ietf.org/rfc/rfc7518.txt)).
+  RSA_PEM = 3;
+
+  // As RSA_PEM, but wrapped in an X.509v3 certificate ([RFC5280](
+  // https://www.ietf.org/rfc/rfc5280.txt)), encoded in base64, and wrapped by
+  // `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`.
+  RSA_X509_PEM = 1;
+
+  // Public key for the ECDSA algorithm using P-256 and SHA-256, encoded in
+  // base64, and wrapped by `-----BEGIN PUBLIC KEY-----` and `-----END
+  // PUBLIC KEY-----`. This can be used to verify JWT tokens with the `ES256`
+  // algorithm ([RFC7518](https://www.ietf.org/rfc/rfc7518.txt)). This curve is
+  // defined in [OpenSSL](https://www.openssl.org/) as the `prime256v1` curve.
+  ES256_PEM = 2;
+
+  // As ES256_PEM, but wrapped in an X.509v3 certificate ([RFC5280](
+  // https://www.ietf.org/rfc/rfc5280.txt)), encoded in base64, and wrapped by
+  // `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`.
+  ES256_X509_PEM = 4;
+}
+
+// The device configuration. Eventually delivered to devices.
+message DeviceConfig {
+  // [Output only] The version of this update. The version number is assigned by
+  // the server, and is always greater than 0 after device creation. The
+  // version must be 0 on the `CreateDevice` request if a `config` is
+  // specified; the response of `CreateDevice` will always have a value of 1.
+  int64 version = 1;
+
+  // [Output only] The time at which this configuration version was updated in
+  // Cloud IoT Core. This timestamp is set by the server.
+  google.protobuf.Timestamp cloud_update_time = 2;
+
+  // [Output only] The time at which Cloud IoT Core received the
+  // acknowledgment from the device, indicating that the device has received
+  // this configuration version. If this field is not present, the device has
+  // not yet acknowledged that it received this version. Note that when
+  // the config was sent to the device, many config versions may have been
+  // available in Cloud IoT Core while the device was disconnected, and on
+  // connection, only the latest version is sent to the device. Some
+  // versions may never be sent to the device, and therefore are never
+  // acknowledged. This timestamp is set by Cloud IoT Core.
+  google.protobuf.Timestamp device_ack_time = 3;
+
+  // The device configuration data.
+  bytes binary_data = 4;
+}
+
+// The device state, as reported by the device.
+message DeviceState {
+  // [Output only] The time at which this state version was updated in Cloud
+  // IoT Core.
+  google.protobuf.Timestamp update_time = 1;
+
+  // The device state data.
+  bytes binary_data = 2;
+}
diff --git a/protos/protos.d.ts b/protos/protos.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..751221e1ca500cb8f06135a84cf73f773d5bc3ab
--- /dev/null
+++ b/protos/protos.d.ts
@@ -0,0 +1,9726 @@
+// Copyright 2022 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.
+
+import * as Long from "long";
+import {protobuf as $protobuf} from "google-gax";
+/** Namespace google. */
+export namespace google {
+
+    /** Namespace cloud. */
+    namespace cloud {
+
+        /** Namespace iot. */
+        namespace iot {
+
+            /** Namespace v1. */
+            namespace v1 {
+
+                /** Represents a DeviceManager */
+                class DeviceManager extends $protobuf.rpc.Service {
+
+                    /**
+                     * Constructs a new DeviceManager service.
+                     * @param rpcImpl RPC implementation
+                     * @param [requestDelimited=false] Whether requests are length-delimited
+                     * @param [responseDelimited=false] Whether responses are length-delimited
+                     */
+                    constructor(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean);
+
+                    /**
+                     * Creates new DeviceManager service using the specified rpc implementation.
+                     * @param rpcImpl RPC implementation
+                     * @param [requestDelimited=false] Whether requests are length-delimited
+                     * @param [responseDelimited=false] Whether responses are length-delimited
+                     * @returns RPC service. Useful where requests and/or responses are streamed.
+                     */
+                    public static create(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): DeviceManager;
+
+                    /**
+                     * Calls CreateDeviceRegistry.
+                     * @param request CreateDeviceRegistryRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and DeviceRegistry
+                     */
+                    public createDeviceRegistry(request: google.cloud.iot.v1.ICreateDeviceRegistryRequest, callback: google.cloud.iot.v1.DeviceManager.CreateDeviceRegistryCallback): void;
+
+                    /**
+                     * Calls CreateDeviceRegistry.
+                     * @param request CreateDeviceRegistryRequest message or plain object
+                     * @returns Promise
+                     */
+                    public createDeviceRegistry(request: google.cloud.iot.v1.ICreateDeviceRegistryRequest): Promise<google.cloud.iot.v1.DeviceRegistry>;
+
+                    /**
+                     * Calls GetDeviceRegistry.
+                     * @param request GetDeviceRegistryRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and DeviceRegistry
+                     */
+                    public getDeviceRegistry(request: google.cloud.iot.v1.IGetDeviceRegistryRequest, callback: google.cloud.iot.v1.DeviceManager.GetDeviceRegistryCallback): void;
+
+                    /**
+                     * Calls GetDeviceRegistry.
+                     * @param request GetDeviceRegistryRequest message or plain object
+                     * @returns Promise
+                     */
+                    public getDeviceRegistry(request: google.cloud.iot.v1.IGetDeviceRegistryRequest): Promise<google.cloud.iot.v1.DeviceRegistry>;
+
+                    /**
+                     * Calls UpdateDeviceRegistry.
+                     * @param request UpdateDeviceRegistryRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and DeviceRegistry
+                     */
+                    public updateDeviceRegistry(request: google.cloud.iot.v1.IUpdateDeviceRegistryRequest, callback: google.cloud.iot.v1.DeviceManager.UpdateDeviceRegistryCallback): void;
+
+                    /**
+                     * Calls UpdateDeviceRegistry.
+                     * @param request UpdateDeviceRegistryRequest message or plain object
+                     * @returns Promise
+                     */
+                    public updateDeviceRegistry(request: google.cloud.iot.v1.IUpdateDeviceRegistryRequest): Promise<google.cloud.iot.v1.DeviceRegistry>;
+
+                    /**
+                     * Calls DeleteDeviceRegistry.
+                     * @param request DeleteDeviceRegistryRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and Empty
+                     */
+                    public deleteDeviceRegistry(request: google.cloud.iot.v1.IDeleteDeviceRegistryRequest, callback: google.cloud.iot.v1.DeviceManager.DeleteDeviceRegistryCallback): void;
+
+                    /**
+                     * Calls DeleteDeviceRegistry.
+                     * @param request DeleteDeviceRegistryRequest message or plain object
+                     * @returns Promise
+                     */
+                    public deleteDeviceRegistry(request: google.cloud.iot.v1.IDeleteDeviceRegistryRequest): Promise<google.protobuf.Empty>;
+
+                    /**
+                     * Calls ListDeviceRegistries.
+                     * @param request ListDeviceRegistriesRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and ListDeviceRegistriesResponse
+                     */
+                    public listDeviceRegistries(request: google.cloud.iot.v1.IListDeviceRegistriesRequest, callback: google.cloud.iot.v1.DeviceManager.ListDeviceRegistriesCallback): void;
+
+                    /**
+                     * Calls ListDeviceRegistries.
+                     * @param request ListDeviceRegistriesRequest message or plain object
+                     * @returns Promise
+                     */
+                    public listDeviceRegistries(request: google.cloud.iot.v1.IListDeviceRegistriesRequest): Promise<google.cloud.iot.v1.ListDeviceRegistriesResponse>;
+
+                    /**
+                     * Calls CreateDevice.
+                     * @param request CreateDeviceRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and Device
+                     */
+                    public createDevice(request: google.cloud.iot.v1.ICreateDeviceRequest, callback: google.cloud.iot.v1.DeviceManager.CreateDeviceCallback): void;
+
+                    /**
+                     * Calls CreateDevice.
+                     * @param request CreateDeviceRequest message or plain object
+                     * @returns Promise
+                     */
+                    public createDevice(request: google.cloud.iot.v1.ICreateDeviceRequest): Promise<google.cloud.iot.v1.Device>;
+
+                    /**
+                     * Calls GetDevice.
+                     * @param request GetDeviceRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and Device
+                     */
+                    public getDevice(request: google.cloud.iot.v1.IGetDeviceRequest, callback: google.cloud.iot.v1.DeviceManager.GetDeviceCallback): void;
+
+                    /**
+                     * Calls GetDevice.
+                     * @param request GetDeviceRequest message or plain object
+                     * @returns Promise
+                     */
+                    public getDevice(request: google.cloud.iot.v1.IGetDeviceRequest): Promise<google.cloud.iot.v1.Device>;
+
+                    /**
+                     * Calls UpdateDevice.
+                     * @param request UpdateDeviceRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and Device
+                     */
+                    public updateDevice(request: google.cloud.iot.v1.IUpdateDeviceRequest, callback: google.cloud.iot.v1.DeviceManager.UpdateDeviceCallback): void;
+
+                    /**
+                     * Calls UpdateDevice.
+                     * @param request UpdateDeviceRequest message or plain object
+                     * @returns Promise
+                     */
+                    public updateDevice(request: google.cloud.iot.v1.IUpdateDeviceRequest): Promise<google.cloud.iot.v1.Device>;
+
+                    /**
+                     * Calls DeleteDevice.
+                     * @param request DeleteDeviceRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and Empty
+                     */
+                    public deleteDevice(request: google.cloud.iot.v1.IDeleteDeviceRequest, callback: google.cloud.iot.v1.DeviceManager.DeleteDeviceCallback): void;
+
+                    /**
+                     * Calls DeleteDevice.
+                     * @param request DeleteDeviceRequest message or plain object
+                     * @returns Promise
+                     */
+                    public deleteDevice(request: google.cloud.iot.v1.IDeleteDeviceRequest): Promise<google.protobuf.Empty>;
+
+                    /**
+                     * Calls ListDevices.
+                     * @param request ListDevicesRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and ListDevicesResponse
+                     */
+                    public listDevices(request: google.cloud.iot.v1.IListDevicesRequest, callback: google.cloud.iot.v1.DeviceManager.ListDevicesCallback): void;
+
+                    /**
+                     * Calls ListDevices.
+                     * @param request ListDevicesRequest message or plain object
+                     * @returns Promise
+                     */
+                    public listDevices(request: google.cloud.iot.v1.IListDevicesRequest): Promise<google.cloud.iot.v1.ListDevicesResponse>;
+
+                    /**
+                     * Calls ModifyCloudToDeviceConfig.
+                     * @param request ModifyCloudToDeviceConfigRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and DeviceConfig
+                     */
+                    public modifyCloudToDeviceConfig(request: google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest, callback: google.cloud.iot.v1.DeviceManager.ModifyCloudToDeviceConfigCallback): void;
+
+                    /**
+                     * Calls ModifyCloudToDeviceConfig.
+                     * @param request ModifyCloudToDeviceConfigRequest message or plain object
+                     * @returns Promise
+                     */
+                    public modifyCloudToDeviceConfig(request: google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest): Promise<google.cloud.iot.v1.DeviceConfig>;
+
+                    /**
+                     * Calls ListDeviceConfigVersions.
+                     * @param request ListDeviceConfigVersionsRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and ListDeviceConfigVersionsResponse
+                     */
+                    public listDeviceConfigVersions(request: google.cloud.iot.v1.IListDeviceConfigVersionsRequest, callback: google.cloud.iot.v1.DeviceManager.ListDeviceConfigVersionsCallback): void;
+
+                    /**
+                     * Calls ListDeviceConfigVersions.
+                     * @param request ListDeviceConfigVersionsRequest message or plain object
+                     * @returns Promise
+                     */
+                    public listDeviceConfigVersions(request: google.cloud.iot.v1.IListDeviceConfigVersionsRequest): Promise<google.cloud.iot.v1.ListDeviceConfigVersionsResponse>;
+
+                    /**
+                     * Calls ListDeviceStates.
+                     * @param request ListDeviceStatesRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and ListDeviceStatesResponse
+                     */
+                    public listDeviceStates(request: google.cloud.iot.v1.IListDeviceStatesRequest, callback: google.cloud.iot.v1.DeviceManager.ListDeviceStatesCallback): void;
+
+                    /**
+                     * Calls ListDeviceStates.
+                     * @param request ListDeviceStatesRequest message or plain object
+                     * @returns Promise
+                     */
+                    public listDeviceStates(request: google.cloud.iot.v1.IListDeviceStatesRequest): Promise<google.cloud.iot.v1.ListDeviceStatesResponse>;
+
+                    /**
+                     * Calls SetIamPolicy.
+                     * @param request SetIamPolicyRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and Policy
+                     */
+                    public setIamPolicy(request: google.iam.v1.ISetIamPolicyRequest, callback: google.cloud.iot.v1.DeviceManager.SetIamPolicyCallback): void;
+
+                    /**
+                     * Calls SetIamPolicy.
+                     * @param request SetIamPolicyRequest message or plain object
+                     * @returns Promise
+                     */
+                    public setIamPolicy(request: google.iam.v1.ISetIamPolicyRequest): Promise<google.iam.v1.Policy>;
+
+                    /**
+                     * Calls GetIamPolicy.
+                     * @param request GetIamPolicyRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and Policy
+                     */
+                    public getIamPolicy(request: google.iam.v1.IGetIamPolicyRequest, callback: google.cloud.iot.v1.DeviceManager.GetIamPolicyCallback): void;
+
+                    /**
+                     * Calls GetIamPolicy.
+                     * @param request GetIamPolicyRequest message or plain object
+                     * @returns Promise
+                     */
+                    public getIamPolicy(request: google.iam.v1.IGetIamPolicyRequest): Promise<google.iam.v1.Policy>;
+
+                    /**
+                     * Calls TestIamPermissions.
+                     * @param request TestIamPermissionsRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and TestIamPermissionsResponse
+                     */
+                    public testIamPermissions(request: google.iam.v1.ITestIamPermissionsRequest, callback: google.cloud.iot.v1.DeviceManager.TestIamPermissionsCallback): void;
+
+                    /**
+                     * Calls TestIamPermissions.
+                     * @param request TestIamPermissionsRequest message or plain object
+                     * @returns Promise
+                     */
+                    public testIamPermissions(request: google.iam.v1.ITestIamPermissionsRequest): Promise<google.iam.v1.TestIamPermissionsResponse>;
+
+                    /**
+                     * Calls SendCommandToDevice.
+                     * @param request SendCommandToDeviceRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and SendCommandToDeviceResponse
+                     */
+                    public sendCommandToDevice(request: google.cloud.iot.v1.ISendCommandToDeviceRequest, callback: google.cloud.iot.v1.DeviceManager.SendCommandToDeviceCallback): void;
+
+                    /**
+                     * Calls SendCommandToDevice.
+                     * @param request SendCommandToDeviceRequest message or plain object
+                     * @returns Promise
+                     */
+                    public sendCommandToDevice(request: google.cloud.iot.v1.ISendCommandToDeviceRequest): Promise<google.cloud.iot.v1.SendCommandToDeviceResponse>;
+
+                    /**
+                     * Calls BindDeviceToGateway.
+                     * @param request BindDeviceToGatewayRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and BindDeviceToGatewayResponse
+                     */
+                    public bindDeviceToGateway(request: google.cloud.iot.v1.IBindDeviceToGatewayRequest, callback: google.cloud.iot.v1.DeviceManager.BindDeviceToGatewayCallback): void;
+
+                    /**
+                     * Calls BindDeviceToGateway.
+                     * @param request BindDeviceToGatewayRequest message or plain object
+                     * @returns Promise
+                     */
+                    public bindDeviceToGateway(request: google.cloud.iot.v1.IBindDeviceToGatewayRequest): Promise<google.cloud.iot.v1.BindDeviceToGatewayResponse>;
+
+                    /**
+                     * Calls UnbindDeviceFromGateway.
+                     * @param request UnbindDeviceFromGatewayRequest message or plain object
+                     * @param callback Node-style callback called with the error, if any, and UnbindDeviceFromGatewayResponse
+                     */
+                    public unbindDeviceFromGateway(request: google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest, callback: google.cloud.iot.v1.DeviceManager.UnbindDeviceFromGatewayCallback): void;
+
+                    /**
+                     * Calls UnbindDeviceFromGateway.
+                     * @param request UnbindDeviceFromGatewayRequest message or plain object
+                     * @returns Promise
+                     */
+                    public unbindDeviceFromGateway(request: google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest): Promise<google.cloud.iot.v1.UnbindDeviceFromGatewayResponse>;
+                }
+
+                namespace DeviceManager {
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#createDeviceRegistry}.
+                     * @param error Error, if any
+                     * @param [response] DeviceRegistry
+                     */
+                    type CreateDeviceRegistryCallback = (error: (Error|null), response?: google.cloud.iot.v1.DeviceRegistry) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#getDeviceRegistry}.
+                     * @param error Error, if any
+                     * @param [response] DeviceRegistry
+                     */
+                    type GetDeviceRegistryCallback = (error: (Error|null), response?: google.cloud.iot.v1.DeviceRegistry) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#updateDeviceRegistry}.
+                     * @param error Error, if any
+                     * @param [response] DeviceRegistry
+                     */
+                    type UpdateDeviceRegistryCallback = (error: (Error|null), response?: google.cloud.iot.v1.DeviceRegistry) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#deleteDeviceRegistry}.
+                     * @param error Error, if any
+                     * @param [response] Empty
+                     */
+                    type DeleteDeviceRegistryCallback = (error: (Error|null), response?: google.protobuf.Empty) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDeviceRegistries}.
+                     * @param error Error, if any
+                     * @param [response] ListDeviceRegistriesResponse
+                     */
+                    type ListDeviceRegistriesCallback = (error: (Error|null), response?: google.cloud.iot.v1.ListDeviceRegistriesResponse) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#createDevice}.
+                     * @param error Error, if any
+                     * @param [response] Device
+                     */
+                    type CreateDeviceCallback = (error: (Error|null), response?: google.cloud.iot.v1.Device) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#getDevice}.
+                     * @param error Error, if any
+                     * @param [response] Device
+                     */
+                    type GetDeviceCallback = (error: (Error|null), response?: google.cloud.iot.v1.Device) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#updateDevice}.
+                     * @param error Error, if any
+                     * @param [response] Device
+                     */
+                    type UpdateDeviceCallback = (error: (Error|null), response?: google.cloud.iot.v1.Device) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#deleteDevice}.
+                     * @param error Error, if any
+                     * @param [response] Empty
+                     */
+                    type DeleteDeviceCallback = (error: (Error|null), response?: google.protobuf.Empty) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDevices}.
+                     * @param error Error, if any
+                     * @param [response] ListDevicesResponse
+                     */
+                    type ListDevicesCallback = (error: (Error|null), response?: google.cloud.iot.v1.ListDevicesResponse) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#modifyCloudToDeviceConfig}.
+                     * @param error Error, if any
+                     * @param [response] DeviceConfig
+                     */
+                    type ModifyCloudToDeviceConfigCallback = (error: (Error|null), response?: google.cloud.iot.v1.DeviceConfig) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDeviceConfigVersions}.
+                     * @param error Error, if any
+                     * @param [response] ListDeviceConfigVersionsResponse
+                     */
+                    type ListDeviceConfigVersionsCallback = (error: (Error|null), response?: google.cloud.iot.v1.ListDeviceConfigVersionsResponse) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDeviceStates}.
+                     * @param error Error, if any
+                     * @param [response] ListDeviceStatesResponse
+                     */
+                    type ListDeviceStatesCallback = (error: (Error|null), response?: google.cloud.iot.v1.ListDeviceStatesResponse) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#setIamPolicy}.
+                     * @param error Error, if any
+                     * @param [response] Policy
+                     */
+                    type SetIamPolicyCallback = (error: (Error|null), response?: google.iam.v1.Policy) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#getIamPolicy}.
+                     * @param error Error, if any
+                     * @param [response] Policy
+                     */
+                    type GetIamPolicyCallback = (error: (Error|null), response?: google.iam.v1.Policy) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#testIamPermissions}.
+                     * @param error Error, if any
+                     * @param [response] TestIamPermissionsResponse
+                     */
+                    type TestIamPermissionsCallback = (error: (Error|null), response?: google.iam.v1.TestIamPermissionsResponse) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#sendCommandToDevice}.
+                     * @param error Error, if any
+                     * @param [response] SendCommandToDeviceResponse
+                     */
+                    type SendCommandToDeviceCallback = (error: (Error|null), response?: google.cloud.iot.v1.SendCommandToDeviceResponse) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#bindDeviceToGateway}.
+                     * @param error Error, if any
+                     * @param [response] BindDeviceToGatewayResponse
+                     */
+                    type BindDeviceToGatewayCallback = (error: (Error|null), response?: google.cloud.iot.v1.BindDeviceToGatewayResponse) => void;
+
+                    /**
+                     * Callback as used by {@link google.cloud.iot.v1.DeviceManager#unbindDeviceFromGateway}.
+                     * @param error Error, if any
+                     * @param [response] UnbindDeviceFromGatewayResponse
+                     */
+                    type UnbindDeviceFromGatewayCallback = (error: (Error|null), response?: google.cloud.iot.v1.UnbindDeviceFromGatewayResponse) => void;
+                }
+
+                /** Properties of a CreateDeviceRegistryRequest. */
+                interface ICreateDeviceRegistryRequest {
+
+                    /** CreateDeviceRegistryRequest parent */
+                    parent?: (string|null);
+
+                    /** CreateDeviceRegistryRequest deviceRegistry */
+                    deviceRegistry?: (google.cloud.iot.v1.IDeviceRegistry|null);
+                }
+
+                /** Represents a CreateDeviceRegistryRequest. */
+                class CreateDeviceRegistryRequest implements ICreateDeviceRegistryRequest {
+
+                    /**
+                     * Constructs a new CreateDeviceRegistryRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.ICreateDeviceRegistryRequest);
+
+                    /** CreateDeviceRegistryRequest parent. */
+                    public parent: string;
+
+                    /** CreateDeviceRegistryRequest deviceRegistry. */
+                    public deviceRegistry?: (google.cloud.iot.v1.IDeviceRegistry|null);
+
+                    /**
+                     * Creates a new CreateDeviceRegistryRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns CreateDeviceRegistryRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.ICreateDeviceRegistryRequest): google.cloud.iot.v1.CreateDeviceRegistryRequest;
+
+                    /**
+                     * Encodes the specified CreateDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRegistryRequest.verify|verify} messages.
+                     * @param message CreateDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.ICreateDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified CreateDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRegistryRequest.verify|verify} messages.
+                     * @param message CreateDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.ICreateDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a CreateDeviceRegistryRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns CreateDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.CreateDeviceRegistryRequest;
+
+                    /**
+                     * Decodes a CreateDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns CreateDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.CreateDeviceRegistryRequest;
+
+                    /**
+                     * Verifies a CreateDeviceRegistryRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a CreateDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns CreateDeviceRegistryRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.CreateDeviceRegistryRequest;
+
+                    /**
+                     * Creates a plain object from a CreateDeviceRegistryRequest message. Also converts values to other types if specified.
+                     * @param message CreateDeviceRegistryRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.CreateDeviceRegistryRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this CreateDeviceRegistryRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a GetDeviceRegistryRequest. */
+                interface IGetDeviceRegistryRequest {
+
+                    /** GetDeviceRegistryRequest name */
+                    name?: (string|null);
+                }
+
+                /** Represents a GetDeviceRegistryRequest. */
+                class GetDeviceRegistryRequest implements IGetDeviceRegistryRequest {
+
+                    /**
+                     * Constructs a new GetDeviceRegistryRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IGetDeviceRegistryRequest);
+
+                    /** GetDeviceRegistryRequest name. */
+                    public name: string;
+
+                    /**
+                     * Creates a new GetDeviceRegistryRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns GetDeviceRegistryRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IGetDeviceRegistryRequest): google.cloud.iot.v1.GetDeviceRegistryRequest;
+
+                    /**
+                     * Encodes the specified GetDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRegistryRequest.verify|verify} messages.
+                     * @param message GetDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IGetDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified GetDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRegistryRequest.verify|verify} messages.
+                     * @param message GetDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IGetDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a GetDeviceRegistryRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns GetDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.GetDeviceRegistryRequest;
+
+                    /**
+                     * Decodes a GetDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns GetDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.GetDeviceRegistryRequest;
+
+                    /**
+                     * Verifies a GetDeviceRegistryRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a GetDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns GetDeviceRegistryRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.GetDeviceRegistryRequest;
+
+                    /**
+                     * Creates a plain object from a GetDeviceRegistryRequest message. Also converts values to other types if specified.
+                     * @param message GetDeviceRegistryRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.GetDeviceRegistryRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this GetDeviceRegistryRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a DeleteDeviceRegistryRequest. */
+                interface IDeleteDeviceRegistryRequest {
+
+                    /** DeleteDeviceRegistryRequest name */
+                    name?: (string|null);
+                }
+
+                /** Represents a DeleteDeviceRegistryRequest. */
+                class DeleteDeviceRegistryRequest implements IDeleteDeviceRegistryRequest {
+
+                    /**
+                     * Constructs a new DeleteDeviceRegistryRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IDeleteDeviceRegistryRequest);
+
+                    /** DeleteDeviceRegistryRequest name. */
+                    public name: string;
+
+                    /**
+                     * Creates a new DeleteDeviceRegistryRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns DeleteDeviceRegistryRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IDeleteDeviceRegistryRequest): google.cloud.iot.v1.DeleteDeviceRegistryRequest;
+
+                    /**
+                     * Encodes the specified DeleteDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRegistryRequest.verify|verify} messages.
+                     * @param message DeleteDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IDeleteDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified DeleteDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRegistryRequest.verify|verify} messages.
+                     * @param message DeleteDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IDeleteDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a DeleteDeviceRegistryRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns DeleteDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.DeleteDeviceRegistryRequest;
+
+                    /**
+                     * Decodes a DeleteDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns DeleteDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.DeleteDeviceRegistryRequest;
+
+                    /**
+                     * Verifies a DeleteDeviceRegistryRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a DeleteDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns DeleteDeviceRegistryRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.DeleteDeviceRegistryRequest;
+
+                    /**
+                     * Creates a plain object from a DeleteDeviceRegistryRequest message. Also converts values to other types if specified.
+                     * @param message DeleteDeviceRegistryRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.DeleteDeviceRegistryRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this DeleteDeviceRegistryRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of an UpdateDeviceRegistryRequest. */
+                interface IUpdateDeviceRegistryRequest {
+
+                    /** UpdateDeviceRegistryRequest deviceRegistry */
+                    deviceRegistry?: (google.cloud.iot.v1.IDeviceRegistry|null);
+
+                    /** UpdateDeviceRegistryRequest updateMask */
+                    updateMask?: (google.protobuf.IFieldMask|null);
+                }
+
+                /** Represents an UpdateDeviceRegistryRequest. */
+                class UpdateDeviceRegistryRequest implements IUpdateDeviceRegistryRequest {
+
+                    /**
+                     * Constructs a new UpdateDeviceRegistryRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IUpdateDeviceRegistryRequest);
+
+                    /** UpdateDeviceRegistryRequest deviceRegistry. */
+                    public deviceRegistry?: (google.cloud.iot.v1.IDeviceRegistry|null);
+
+                    /** UpdateDeviceRegistryRequest updateMask. */
+                    public updateMask?: (google.protobuf.IFieldMask|null);
+
+                    /**
+                     * Creates a new UpdateDeviceRegistryRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns UpdateDeviceRegistryRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IUpdateDeviceRegistryRequest): google.cloud.iot.v1.UpdateDeviceRegistryRequest;
+
+                    /**
+                     * Encodes the specified UpdateDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRegistryRequest.verify|verify} messages.
+                     * @param message UpdateDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IUpdateDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified UpdateDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRegistryRequest.verify|verify} messages.
+                     * @param message UpdateDeviceRegistryRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IUpdateDeviceRegistryRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes an UpdateDeviceRegistryRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns UpdateDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.UpdateDeviceRegistryRequest;
+
+                    /**
+                     * Decodes an UpdateDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns UpdateDeviceRegistryRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.UpdateDeviceRegistryRequest;
+
+                    /**
+                     * Verifies an UpdateDeviceRegistryRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates an UpdateDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns UpdateDeviceRegistryRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.UpdateDeviceRegistryRequest;
+
+                    /**
+                     * Creates a plain object from an UpdateDeviceRegistryRequest message. Also converts values to other types if specified.
+                     * @param message UpdateDeviceRegistryRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.UpdateDeviceRegistryRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this UpdateDeviceRegistryRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDeviceRegistriesRequest. */
+                interface IListDeviceRegistriesRequest {
+
+                    /** ListDeviceRegistriesRequest parent */
+                    parent?: (string|null);
+
+                    /** ListDeviceRegistriesRequest pageSize */
+                    pageSize?: (number|null);
+
+                    /** ListDeviceRegistriesRequest pageToken */
+                    pageToken?: (string|null);
+                }
+
+                /** Represents a ListDeviceRegistriesRequest. */
+                class ListDeviceRegistriesRequest implements IListDeviceRegistriesRequest {
+
+                    /**
+                     * Constructs a new ListDeviceRegistriesRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDeviceRegistriesRequest);
+
+                    /** ListDeviceRegistriesRequest parent. */
+                    public parent: string;
+
+                    /** ListDeviceRegistriesRequest pageSize. */
+                    public pageSize: number;
+
+                    /** ListDeviceRegistriesRequest pageToken. */
+                    public pageToken: string;
+
+                    /**
+                     * Creates a new ListDeviceRegistriesRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDeviceRegistriesRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDeviceRegistriesRequest): google.cloud.iot.v1.ListDeviceRegistriesRequest;
+
+                    /**
+                     * Encodes the specified ListDeviceRegistriesRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesRequest.verify|verify} messages.
+                     * @param message ListDeviceRegistriesRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDeviceRegistriesRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDeviceRegistriesRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesRequest.verify|verify} messages.
+                     * @param message ListDeviceRegistriesRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDeviceRegistriesRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDeviceRegistriesRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDeviceRegistriesRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDeviceRegistriesRequest;
+
+                    /**
+                     * Decodes a ListDeviceRegistriesRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDeviceRegistriesRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDeviceRegistriesRequest;
+
+                    /**
+                     * Verifies a ListDeviceRegistriesRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDeviceRegistriesRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDeviceRegistriesRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDeviceRegistriesRequest;
+
+                    /**
+                     * Creates a plain object from a ListDeviceRegistriesRequest message. Also converts values to other types if specified.
+                     * @param message ListDeviceRegistriesRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDeviceRegistriesRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDeviceRegistriesRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDeviceRegistriesResponse. */
+                interface IListDeviceRegistriesResponse {
+
+                    /** ListDeviceRegistriesResponse deviceRegistries */
+                    deviceRegistries?: (google.cloud.iot.v1.IDeviceRegistry[]|null);
+
+                    /** ListDeviceRegistriesResponse nextPageToken */
+                    nextPageToken?: (string|null);
+                }
+
+                /** Represents a ListDeviceRegistriesResponse. */
+                class ListDeviceRegistriesResponse implements IListDeviceRegistriesResponse {
+
+                    /**
+                     * Constructs a new ListDeviceRegistriesResponse.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDeviceRegistriesResponse);
+
+                    /** ListDeviceRegistriesResponse deviceRegistries. */
+                    public deviceRegistries: google.cloud.iot.v1.IDeviceRegistry[];
+
+                    /** ListDeviceRegistriesResponse nextPageToken. */
+                    public nextPageToken: string;
+
+                    /**
+                     * Creates a new ListDeviceRegistriesResponse instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDeviceRegistriesResponse instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDeviceRegistriesResponse): google.cloud.iot.v1.ListDeviceRegistriesResponse;
+
+                    /**
+                     * Encodes the specified ListDeviceRegistriesResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesResponse.verify|verify} messages.
+                     * @param message ListDeviceRegistriesResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDeviceRegistriesResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDeviceRegistriesResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesResponse.verify|verify} messages.
+                     * @param message ListDeviceRegistriesResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDeviceRegistriesResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDeviceRegistriesResponse message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDeviceRegistriesResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDeviceRegistriesResponse;
+
+                    /**
+                     * Decodes a ListDeviceRegistriesResponse message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDeviceRegistriesResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDeviceRegistriesResponse;
+
+                    /**
+                     * Verifies a ListDeviceRegistriesResponse message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDeviceRegistriesResponse message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDeviceRegistriesResponse
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDeviceRegistriesResponse;
+
+                    /**
+                     * Creates a plain object from a ListDeviceRegistriesResponse message. Also converts values to other types if specified.
+                     * @param message ListDeviceRegistriesResponse
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDeviceRegistriesResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDeviceRegistriesResponse to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a CreateDeviceRequest. */
+                interface ICreateDeviceRequest {
+
+                    /** CreateDeviceRequest parent */
+                    parent?: (string|null);
+
+                    /** CreateDeviceRequest device */
+                    device?: (google.cloud.iot.v1.IDevice|null);
+                }
+
+                /** Represents a CreateDeviceRequest. */
+                class CreateDeviceRequest implements ICreateDeviceRequest {
+
+                    /**
+                     * Constructs a new CreateDeviceRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.ICreateDeviceRequest);
+
+                    /** CreateDeviceRequest parent. */
+                    public parent: string;
+
+                    /** CreateDeviceRequest device. */
+                    public device?: (google.cloud.iot.v1.IDevice|null);
+
+                    /**
+                     * Creates a new CreateDeviceRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns CreateDeviceRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.ICreateDeviceRequest): google.cloud.iot.v1.CreateDeviceRequest;
+
+                    /**
+                     * Encodes the specified CreateDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRequest.verify|verify} messages.
+                     * @param message CreateDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.ICreateDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified CreateDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRequest.verify|verify} messages.
+                     * @param message CreateDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.ICreateDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a CreateDeviceRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns CreateDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.CreateDeviceRequest;
+
+                    /**
+                     * Decodes a CreateDeviceRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns CreateDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.CreateDeviceRequest;
+
+                    /**
+                     * Verifies a CreateDeviceRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a CreateDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns CreateDeviceRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.CreateDeviceRequest;
+
+                    /**
+                     * Creates a plain object from a CreateDeviceRequest message. Also converts values to other types if specified.
+                     * @param message CreateDeviceRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.CreateDeviceRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this CreateDeviceRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a GetDeviceRequest. */
+                interface IGetDeviceRequest {
+
+                    /** GetDeviceRequest name */
+                    name?: (string|null);
+
+                    /** GetDeviceRequest fieldMask */
+                    fieldMask?: (google.protobuf.IFieldMask|null);
+                }
+
+                /** Represents a GetDeviceRequest. */
+                class GetDeviceRequest implements IGetDeviceRequest {
+
+                    /**
+                     * Constructs a new GetDeviceRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IGetDeviceRequest);
+
+                    /** GetDeviceRequest name. */
+                    public name: string;
+
+                    /** GetDeviceRequest fieldMask. */
+                    public fieldMask?: (google.protobuf.IFieldMask|null);
+
+                    /**
+                     * Creates a new GetDeviceRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns GetDeviceRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IGetDeviceRequest): google.cloud.iot.v1.GetDeviceRequest;
+
+                    /**
+                     * Encodes the specified GetDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRequest.verify|verify} messages.
+                     * @param message GetDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IGetDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified GetDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRequest.verify|verify} messages.
+                     * @param message GetDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IGetDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a GetDeviceRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns GetDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.GetDeviceRequest;
+
+                    /**
+                     * Decodes a GetDeviceRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns GetDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.GetDeviceRequest;
+
+                    /**
+                     * Verifies a GetDeviceRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a GetDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns GetDeviceRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.GetDeviceRequest;
+
+                    /**
+                     * Creates a plain object from a GetDeviceRequest message. Also converts values to other types if specified.
+                     * @param message GetDeviceRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.GetDeviceRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this GetDeviceRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of an UpdateDeviceRequest. */
+                interface IUpdateDeviceRequest {
+
+                    /** UpdateDeviceRequest device */
+                    device?: (google.cloud.iot.v1.IDevice|null);
+
+                    /** UpdateDeviceRequest updateMask */
+                    updateMask?: (google.protobuf.IFieldMask|null);
+                }
+
+                /** Represents an UpdateDeviceRequest. */
+                class UpdateDeviceRequest implements IUpdateDeviceRequest {
+
+                    /**
+                     * Constructs a new UpdateDeviceRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IUpdateDeviceRequest);
+
+                    /** UpdateDeviceRequest device. */
+                    public device?: (google.cloud.iot.v1.IDevice|null);
+
+                    /** UpdateDeviceRequest updateMask. */
+                    public updateMask?: (google.protobuf.IFieldMask|null);
+
+                    /**
+                     * Creates a new UpdateDeviceRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns UpdateDeviceRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IUpdateDeviceRequest): google.cloud.iot.v1.UpdateDeviceRequest;
+
+                    /**
+                     * Encodes the specified UpdateDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRequest.verify|verify} messages.
+                     * @param message UpdateDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IUpdateDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified UpdateDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRequest.verify|verify} messages.
+                     * @param message UpdateDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IUpdateDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes an UpdateDeviceRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns UpdateDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.UpdateDeviceRequest;
+
+                    /**
+                     * Decodes an UpdateDeviceRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns UpdateDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.UpdateDeviceRequest;
+
+                    /**
+                     * Verifies an UpdateDeviceRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates an UpdateDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns UpdateDeviceRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.UpdateDeviceRequest;
+
+                    /**
+                     * Creates a plain object from an UpdateDeviceRequest message. Also converts values to other types if specified.
+                     * @param message UpdateDeviceRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.UpdateDeviceRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this UpdateDeviceRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a DeleteDeviceRequest. */
+                interface IDeleteDeviceRequest {
+
+                    /** DeleteDeviceRequest name */
+                    name?: (string|null);
+                }
+
+                /** Represents a DeleteDeviceRequest. */
+                class DeleteDeviceRequest implements IDeleteDeviceRequest {
+
+                    /**
+                     * Constructs a new DeleteDeviceRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IDeleteDeviceRequest);
+
+                    /** DeleteDeviceRequest name. */
+                    public name: string;
+
+                    /**
+                     * Creates a new DeleteDeviceRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns DeleteDeviceRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IDeleteDeviceRequest): google.cloud.iot.v1.DeleteDeviceRequest;
+
+                    /**
+                     * Encodes the specified DeleteDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRequest.verify|verify} messages.
+                     * @param message DeleteDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IDeleteDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified DeleteDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRequest.verify|verify} messages.
+                     * @param message DeleteDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IDeleteDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a DeleteDeviceRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns DeleteDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.DeleteDeviceRequest;
+
+                    /**
+                     * Decodes a DeleteDeviceRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns DeleteDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.DeleteDeviceRequest;
+
+                    /**
+                     * Verifies a DeleteDeviceRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a DeleteDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns DeleteDeviceRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.DeleteDeviceRequest;
+
+                    /**
+                     * Creates a plain object from a DeleteDeviceRequest message. Also converts values to other types if specified.
+                     * @param message DeleteDeviceRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.DeleteDeviceRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this DeleteDeviceRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDevicesRequest. */
+                interface IListDevicesRequest {
+
+                    /** ListDevicesRequest parent */
+                    parent?: (string|null);
+
+                    /** ListDevicesRequest deviceNumIds */
+                    deviceNumIds?: ((number|Long|string)[]|null);
+
+                    /** ListDevicesRequest deviceIds */
+                    deviceIds?: (string[]|null);
+
+                    /** ListDevicesRequest fieldMask */
+                    fieldMask?: (google.protobuf.IFieldMask|null);
+
+                    /** ListDevicesRequest gatewayListOptions */
+                    gatewayListOptions?: (google.cloud.iot.v1.IGatewayListOptions|null);
+
+                    /** ListDevicesRequest pageSize */
+                    pageSize?: (number|null);
+
+                    /** ListDevicesRequest pageToken */
+                    pageToken?: (string|null);
+                }
+
+                /** Represents a ListDevicesRequest. */
+                class ListDevicesRequest implements IListDevicesRequest {
+
+                    /**
+                     * Constructs a new ListDevicesRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDevicesRequest);
+
+                    /** ListDevicesRequest parent. */
+                    public parent: string;
+
+                    /** ListDevicesRequest deviceNumIds. */
+                    public deviceNumIds: (number|Long|string)[];
+
+                    /** ListDevicesRequest deviceIds. */
+                    public deviceIds: string[];
+
+                    /** ListDevicesRequest fieldMask. */
+                    public fieldMask?: (google.protobuf.IFieldMask|null);
+
+                    /** ListDevicesRequest gatewayListOptions. */
+                    public gatewayListOptions?: (google.cloud.iot.v1.IGatewayListOptions|null);
+
+                    /** ListDevicesRequest pageSize. */
+                    public pageSize: number;
+
+                    /** ListDevicesRequest pageToken. */
+                    public pageToken: string;
+
+                    /**
+                     * Creates a new ListDevicesRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDevicesRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDevicesRequest): google.cloud.iot.v1.ListDevicesRequest;
+
+                    /**
+                     * Encodes the specified ListDevicesRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDevicesRequest.verify|verify} messages.
+                     * @param message ListDevicesRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDevicesRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDevicesRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDevicesRequest.verify|verify} messages.
+                     * @param message ListDevicesRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDevicesRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDevicesRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDevicesRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDevicesRequest;
+
+                    /**
+                     * Decodes a ListDevicesRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDevicesRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDevicesRequest;
+
+                    /**
+                     * Verifies a ListDevicesRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDevicesRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDevicesRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDevicesRequest;
+
+                    /**
+                     * Creates a plain object from a ListDevicesRequest message. Also converts values to other types if specified.
+                     * @param message ListDevicesRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDevicesRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDevicesRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a GatewayListOptions. */
+                interface IGatewayListOptions {
+
+                    /** GatewayListOptions gatewayType */
+                    gatewayType?: (google.cloud.iot.v1.GatewayType|keyof typeof google.cloud.iot.v1.GatewayType|null);
+
+                    /** GatewayListOptions associationsGatewayId */
+                    associationsGatewayId?: (string|null);
+
+                    /** GatewayListOptions associationsDeviceId */
+                    associationsDeviceId?: (string|null);
+                }
+
+                /** Represents a GatewayListOptions. */
+                class GatewayListOptions implements IGatewayListOptions {
+
+                    /**
+                     * Constructs a new GatewayListOptions.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IGatewayListOptions);
+
+                    /** GatewayListOptions gatewayType. */
+                    public gatewayType?: (google.cloud.iot.v1.GatewayType|keyof typeof google.cloud.iot.v1.GatewayType|null);
+
+                    /** GatewayListOptions associationsGatewayId. */
+                    public associationsGatewayId?: (string|null);
+
+                    /** GatewayListOptions associationsDeviceId. */
+                    public associationsDeviceId?: (string|null);
+
+                    /** GatewayListOptions filter. */
+                    public filter?: ("gatewayType"|"associationsGatewayId"|"associationsDeviceId");
+
+                    /**
+                     * Creates a new GatewayListOptions instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns GatewayListOptions instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IGatewayListOptions): google.cloud.iot.v1.GatewayListOptions;
+
+                    /**
+                     * Encodes the specified GatewayListOptions message. Does not implicitly {@link google.cloud.iot.v1.GatewayListOptions.verify|verify} messages.
+                     * @param message GatewayListOptions message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IGatewayListOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified GatewayListOptions message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GatewayListOptions.verify|verify} messages.
+                     * @param message GatewayListOptions message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IGatewayListOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a GatewayListOptions message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns GatewayListOptions
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.GatewayListOptions;
+
+                    /**
+                     * Decodes a GatewayListOptions message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns GatewayListOptions
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.GatewayListOptions;
+
+                    /**
+                     * Verifies a GatewayListOptions message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a GatewayListOptions message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns GatewayListOptions
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.GatewayListOptions;
+
+                    /**
+                     * Creates a plain object from a GatewayListOptions message. Also converts values to other types if specified.
+                     * @param message GatewayListOptions
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.GatewayListOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this GatewayListOptions to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDevicesResponse. */
+                interface IListDevicesResponse {
+
+                    /** ListDevicesResponse devices */
+                    devices?: (google.cloud.iot.v1.IDevice[]|null);
+
+                    /** ListDevicesResponse nextPageToken */
+                    nextPageToken?: (string|null);
+                }
+
+                /** Represents a ListDevicesResponse. */
+                class ListDevicesResponse implements IListDevicesResponse {
+
+                    /**
+                     * Constructs a new ListDevicesResponse.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDevicesResponse);
+
+                    /** ListDevicesResponse devices. */
+                    public devices: google.cloud.iot.v1.IDevice[];
+
+                    /** ListDevicesResponse nextPageToken. */
+                    public nextPageToken: string;
+
+                    /**
+                     * Creates a new ListDevicesResponse instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDevicesResponse instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDevicesResponse): google.cloud.iot.v1.ListDevicesResponse;
+
+                    /**
+                     * Encodes the specified ListDevicesResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDevicesResponse.verify|verify} messages.
+                     * @param message ListDevicesResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDevicesResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDevicesResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDevicesResponse.verify|verify} messages.
+                     * @param message ListDevicesResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDevicesResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDevicesResponse message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDevicesResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDevicesResponse;
+
+                    /**
+                     * Decodes a ListDevicesResponse message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDevicesResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDevicesResponse;
+
+                    /**
+                     * Verifies a ListDevicesResponse message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDevicesResponse message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDevicesResponse
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDevicesResponse;
+
+                    /**
+                     * Creates a plain object from a ListDevicesResponse message. Also converts values to other types if specified.
+                     * @param message ListDevicesResponse
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDevicesResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDevicesResponse to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ModifyCloudToDeviceConfigRequest. */
+                interface IModifyCloudToDeviceConfigRequest {
+
+                    /** ModifyCloudToDeviceConfigRequest name */
+                    name?: (string|null);
+
+                    /** ModifyCloudToDeviceConfigRequest versionToUpdate */
+                    versionToUpdate?: (number|Long|string|null);
+
+                    /** ModifyCloudToDeviceConfigRequest binaryData */
+                    binaryData?: (Uint8Array|string|null);
+                }
+
+                /** Represents a ModifyCloudToDeviceConfigRequest. */
+                class ModifyCloudToDeviceConfigRequest implements IModifyCloudToDeviceConfigRequest {
+
+                    /**
+                     * Constructs a new ModifyCloudToDeviceConfigRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest);
+
+                    /** ModifyCloudToDeviceConfigRequest name. */
+                    public name: string;
+
+                    /** ModifyCloudToDeviceConfigRequest versionToUpdate. */
+                    public versionToUpdate: (number|Long|string);
+
+                    /** ModifyCloudToDeviceConfigRequest binaryData. */
+                    public binaryData: (Uint8Array|string);
+
+                    /**
+                     * Creates a new ModifyCloudToDeviceConfigRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ModifyCloudToDeviceConfigRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest): google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest;
+
+                    /**
+                     * Encodes the specified ModifyCloudToDeviceConfigRequest message. Does not implicitly {@link google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest.verify|verify} messages.
+                     * @param message ModifyCloudToDeviceConfigRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ModifyCloudToDeviceConfigRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest.verify|verify} messages.
+                     * @param message ModifyCloudToDeviceConfigRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ModifyCloudToDeviceConfigRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ModifyCloudToDeviceConfigRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest;
+
+                    /**
+                     * Decodes a ModifyCloudToDeviceConfigRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ModifyCloudToDeviceConfigRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest;
+
+                    /**
+                     * Verifies a ModifyCloudToDeviceConfigRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ModifyCloudToDeviceConfigRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ModifyCloudToDeviceConfigRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest;
+
+                    /**
+                     * Creates a plain object from a ModifyCloudToDeviceConfigRequest message. Also converts values to other types if specified.
+                     * @param message ModifyCloudToDeviceConfigRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ModifyCloudToDeviceConfigRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDeviceConfigVersionsRequest. */
+                interface IListDeviceConfigVersionsRequest {
+
+                    /** ListDeviceConfigVersionsRequest name */
+                    name?: (string|null);
+
+                    /** ListDeviceConfigVersionsRequest numVersions */
+                    numVersions?: (number|null);
+                }
+
+                /** Represents a ListDeviceConfigVersionsRequest. */
+                class ListDeviceConfigVersionsRequest implements IListDeviceConfigVersionsRequest {
+
+                    /**
+                     * Constructs a new ListDeviceConfigVersionsRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDeviceConfigVersionsRequest);
+
+                    /** ListDeviceConfigVersionsRequest name. */
+                    public name: string;
+
+                    /** ListDeviceConfigVersionsRequest numVersions. */
+                    public numVersions: number;
+
+                    /**
+                     * Creates a new ListDeviceConfigVersionsRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDeviceConfigVersionsRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDeviceConfigVersionsRequest): google.cloud.iot.v1.ListDeviceConfigVersionsRequest;
+
+                    /**
+                     * Encodes the specified ListDeviceConfigVersionsRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsRequest.verify|verify} messages.
+                     * @param message ListDeviceConfigVersionsRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDeviceConfigVersionsRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDeviceConfigVersionsRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsRequest.verify|verify} messages.
+                     * @param message ListDeviceConfigVersionsRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDeviceConfigVersionsRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDeviceConfigVersionsRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDeviceConfigVersionsRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDeviceConfigVersionsRequest;
+
+                    /**
+                     * Decodes a ListDeviceConfigVersionsRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDeviceConfigVersionsRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDeviceConfigVersionsRequest;
+
+                    /**
+                     * Verifies a ListDeviceConfigVersionsRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDeviceConfigVersionsRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDeviceConfigVersionsRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDeviceConfigVersionsRequest;
+
+                    /**
+                     * Creates a plain object from a ListDeviceConfigVersionsRequest message. Also converts values to other types if specified.
+                     * @param message ListDeviceConfigVersionsRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDeviceConfigVersionsRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDeviceConfigVersionsRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDeviceConfigVersionsResponse. */
+                interface IListDeviceConfigVersionsResponse {
+
+                    /** ListDeviceConfigVersionsResponse deviceConfigs */
+                    deviceConfigs?: (google.cloud.iot.v1.IDeviceConfig[]|null);
+                }
+
+                /** Represents a ListDeviceConfigVersionsResponse. */
+                class ListDeviceConfigVersionsResponse implements IListDeviceConfigVersionsResponse {
+
+                    /**
+                     * Constructs a new ListDeviceConfigVersionsResponse.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDeviceConfigVersionsResponse);
+
+                    /** ListDeviceConfigVersionsResponse deviceConfigs. */
+                    public deviceConfigs: google.cloud.iot.v1.IDeviceConfig[];
+
+                    /**
+                     * Creates a new ListDeviceConfigVersionsResponse instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDeviceConfigVersionsResponse instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDeviceConfigVersionsResponse): google.cloud.iot.v1.ListDeviceConfigVersionsResponse;
+
+                    /**
+                     * Encodes the specified ListDeviceConfigVersionsResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsResponse.verify|verify} messages.
+                     * @param message ListDeviceConfigVersionsResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDeviceConfigVersionsResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDeviceConfigVersionsResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsResponse.verify|verify} messages.
+                     * @param message ListDeviceConfigVersionsResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDeviceConfigVersionsResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDeviceConfigVersionsResponse message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDeviceConfigVersionsResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDeviceConfigVersionsResponse;
+
+                    /**
+                     * Decodes a ListDeviceConfigVersionsResponse message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDeviceConfigVersionsResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDeviceConfigVersionsResponse;
+
+                    /**
+                     * Verifies a ListDeviceConfigVersionsResponse message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDeviceConfigVersionsResponse message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDeviceConfigVersionsResponse
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDeviceConfigVersionsResponse;
+
+                    /**
+                     * Creates a plain object from a ListDeviceConfigVersionsResponse message. Also converts values to other types if specified.
+                     * @param message ListDeviceConfigVersionsResponse
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDeviceConfigVersionsResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDeviceConfigVersionsResponse to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDeviceStatesRequest. */
+                interface IListDeviceStatesRequest {
+
+                    /** ListDeviceStatesRequest name */
+                    name?: (string|null);
+
+                    /** ListDeviceStatesRequest numStates */
+                    numStates?: (number|null);
+                }
+
+                /** Represents a ListDeviceStatesRequest. */
+                class ListDeviceStatesRequest implements IListDeviceStatesRequest {
+
+                    /**
+                     * Constructs a new ListDeviceStatesRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDeviceStatesRequest);
+
+                    /** ListDeviceStatesRequest name. */
+                    public name: string;
+
+                    /** ListDeviceStatesRequest numStates. */
+                    public numStates: number;
+
+                    /**
+                     * Creates a new ListDeviceStatesRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDeviceStatesRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDeviceStatesRequest): google.cloud.iot.v1.ListDeviceStatesRequest;
+
+                    /**
+                     * Encodes the specified ListDeviceStatesRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesRequest.verify|verify} messages.
+                     * @param message ListDeviceStatesRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDeviceStatesRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDeviceStatesRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesRequest.verify|verify} messages.
+                     * @param message ListDeviceStatesRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDeviceStatesRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDeviceStatesRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDeviceStatesRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDeviceStatesRequest;
+
+                    /**
+                     * Decodes a ListDeviceStatesRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDeviceStatesRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDeviceStatesRequest;
+
+                    /**
+                     * Verifies a ListDeviceStatesRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDeviceStatesRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDeviceStatesRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDeviceStatesRequest;
+
+                    /**
+                     * Creates a plain object from a ListDeviceStatesRequest message. Also converts values to other types if specified.
+                     * @param message ListDeviceStatesRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDeviceStatesRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDeviceStatesRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a ListDeviceStatesResponse. */
+                interface IListDeviceStatesResponse {
+
+                    /** ListDeviceStatesResponse deviceStates */
+                    deviceStates?: (google.cloud.iot.v1.IDeviceState[]|null);
+                }
+
+                /** Represents a ListDeviceStatesResponse. */
+                class ListDeviceStatesResponse implements IListDeviceStatesResponse {
+
+                    /**
+                     * Constructs a new ListDeviceStatesResponse.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IListDeviceStatesResponse);
+
+                    /** ListDeviceStatesResponse deviceStates. */
+                    public deviceStates: google.cloud.iot.v1.IDeviceState[];
+
+                    /**
+                     * Creates a new ListDeviceStatesResponse instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns ListDeviceStatesResponse instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IListDeviceStatesResponse): google.cloud.iot.v1.ListDeviceStatesResponse;
+
+                    /**
+                     * Encodes the specified ListDeviceStatesResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesResponse.verify|verify} messages.
+                     * @param message ListDeviceStatesResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IListDeviceStatesResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified ListDeviceStatesResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesResponse.verify|verify} messages.
+                     * @param message ListDeviceStatesResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IListDeviceStatesResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a ListDeviceStatesResponse message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns ListDeviceStatesResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.ListDeviceStatesResponse;
+
+                    /**
+                     * Decodes a ListDeviceStatesResponse message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns ListDeviceStatesResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.ListDeviceStatesResponse;
+
+                    /**
+                     * Verifies a ListDeviceStatesResponse message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a ListDeviceStatesResponse message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns ListDeviceStatesResponse
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.ListDeviceStatesResponse;
+
+                    /**
+                     * Creates a plain object from a ListDeviceStatesResponse message. Also converts values to other types if specified.
+                     * @param message ListDeviceStatesResponse
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.ListDeviceStatesResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this ListDeviceStatesResponse to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a SendCommandToDeviceRequest. */
+                interface ISendCommandToDeviceRequest {
+
+                    /** SendCommandToDeviceRequest name */
+                    name?: (string|null);
+
+                    /** SendCommandToDeviceRequest binaryData */
+                    binaryData?: (Uint8Array|string|null);
+
+                    /** SendCommandToDeviceRequest subfolder */
+                    subfolder?: (string|null);
+                }
+
+                /** Represents a SendCommandToDeviceRequest. */
+                class SendCommandToDeviceRequest implements ISendCommandToDeviceRequest {
+
+                    /**
+                     * Constructs a new SendCommandToDeviceRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.ISendCommandToDeviceRequest);
+
+                    /** SendCommandToDeviceRequest name. */
+                    public name: string;
+
+                    /** SendCommandToDeviceRequest binaryData. */
+                    public binaryData: (Uint8Array|string);
+
+                    /** SendCommandToDeviceRequest subfolder. */
+                    public subfolder: string;
+
+                    /**
+                     * Creates a new SendCommandToDeviceRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns SendCommandToDeviceRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.ISendCommandToDeviceRequest): google.cloud.iot.v1.SendCommandToDeviceRequest;
+
+                    /**
+                     * Encodes the specified SendCommandToDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceRequest.verify|verify} messages.
+                     * @param message SendCommandToDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.ISendCommandToDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified SendCommandToDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceRequest.verify|verify} messages.
+                     * @param message SendCommandToDeviceRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.ISendCommandToDeviceRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a SendCommandToDeviceRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns SendCommandToDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.SendCommandToDeviceRequest;
+
+                    /**
+                     * Decodes a SendCommandToDeviceRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns SendCommandToDeviceRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.SendCommandToDeviceRequest;
+
+                    /**
+                     * Verifies a SendCommandToDeviceRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a SendCommandToDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns SendCommandToDeviceRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.SendCommandToDeviceRequest;
+
+                    /**
+                     * Creates a plain object from a SendCommandToDeviceRequest message. Also converts values to other types if specified.
+                     * @param message SendCommandToDeviceRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.SendCommandToDeviceRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this SendCommandToDeviceRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a SendCommandToDeviceResponse. */
+                interface ISendCommandToDeviceResponse {
+                }
+
+                /** Represents a SendCommandToDeviceResponse. */
+                class SendCommandToDeviceResponse implements ISendCommandToDeviceResponse {
+
+                    /**
+                     * Constructs a new SendCommandToDeviceResponse.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.ISendCommandToDeviceResponse);
+
+                    /**
+                     * Creates a new SendCommandToDeviceResponse instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns SendCommandToDeviceResponse instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.ISendCommandToDeviceResponse): google.cloud.iot.v1.SendCommandToDeviceResponse;
+
+                    /**
+                     * Encodes the specified SendCommandToDeviceResponse message. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceResponse.verify|verify} messages.
+                     * @param message SendCommandToDeviceResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.ISendCommandToDeviceResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified SendCommandToDeviceResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceResponse.verify|verify} messages.
+                     * @param message SendCommandToDeviceResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.ISendCommandToDeviceResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a SendCommandToDeviceResponse message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns SendCommandToDeviceResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.SendCommandToDeviceResponse;
+
+                    /**
+                     * Decodes a SendCommandToDeviceResponse message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns SendCommandToDeviceResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.SendCommandToDeviceResponse;
+
+                    /**
+                     * Verifies a SendCommandToDeviceResponse message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a SendCommandToDeviceResponse message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns SendCommandToDeviceResponse
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.SendCommandToDeviceResponse;
+
+                    /**
+                     * Creates a plain object from a SendCommandToDeviceResponse message. Also converts values to other types if specified.
+                     * @param message SendCommandToDeviceResponse
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.SendCommandToDeviceResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this SendCommandToDeviceResponse to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a BindDeviceToGatewayRequest. */
+                interface IBindDeviceToGatewayRequest {
+
+                    /** BindDeviceToGatewayRequest parent */
+                    parent?: (string|null);
+
+                    /** BindDeviceToGatewayRequest gatewayId */
+                    gatewayId?: (string|null);
+
+                    /** BindDeviceToGatewayRequest deviceId */
+                    deviceId?: (string|null);
+                }
+
+                /** Represents a BindDeviceToGatewayRequest. */
+                class BindDeviceToGatewayRequest implements IBindDeviceToGatewayRequest {
+
+                    /**
+                     * Constructs a new BindDeviceToGatewayRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IBindDeviceToGatewayRequest);
+
+                    /** BindDeviceToGatewayRequest parent. */
+                    public parent: string;
+
+                    /** BindDeviceToGatewayRequest gatewayId. */
+                    public gatewayId: string;
+
+                    /** BindDeviceToGatewayRequest deviceId. */
+                    public deviceId: string;
+
+                    /**
+                     * Creates a new BindDeviceToGatewayRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns BindDeviceToGatewayRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IBindDeviceToGatewayRequest): google.cloud.iot.v1.BindDeviceToGatewayRequest;
+
+                    /**
+                     * Encodes the specified BindDeviceToGatewayRequest message. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayRequest.verify|verify} messages.
+                     * @param message BindDeviceToGatewayRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IBindDeviceToGatewayRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified BindDeviceToGatewayRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayRequest.verify|verify} messages.
+                     * @param message BindDeviceToGatewayRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IBindDeviceToGatewayRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a BindDeviceToGatewayRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns BindDeviceToGatewayRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.BindDeviceToGatewayRequest;
+
+                    /**
+                     * Decodes a BindDeviceToGatewayRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns BindDeviceToGatewayRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.BindDeviceToGatewayRequest;
+
+                    /**
+                     * Verifies a BindDeviceToGatewayRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a BindDeviceToGatewayRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns BindDeviceToGatewayRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.BindDeviceToGatewayRequest;
+
+                    /**
+                     * Creates a plain object from a BindDeviceToGatewayRequest message. Also converts values to other types if specified.
+                     * @param message BindDeviceToGatewayRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.BindDeviceToGatewayRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this BindDeviceToGatewayRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a BindDeviceToGatewayResponse. */
+                interface IBindDeviceToGatewayResponse {
+                }
+
+                /** Represents a BindDeviceToGatewayResponse. */
+                class BindDeviceToGatewayResponse implements IBindDeviceToGatewayResponse {
+
+                    /**
+                     * Constructs a new BindDeviceToGatewayResponse.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IBindDeviceToGatewayResponse);
+
+                    /**
+                     * Creates a new BindDeviceToGatewayResponse instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns BindDeviceToGatewayResponse instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IBindDeviceToGatewayResponse): google.cloud.iot.v1.BindDeviceToGatewayResponse;
+
+                    /**
+                     * Encodes the specified BindDeviceToGatewayResponse message. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayResponse.verify|verify} messages.
+                     * @param message BindDeviceToGatewayResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IBindDeviceToGatewayResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified BindDeviceToGatewayResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayResponse.verify|verify} messages.
+                     * @param message BindDeviceToGatewayResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IBindDeviceToGatewayResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a BindDeviceToGatewayResponse message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns BindDeviceToGatewayResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.BindDeviceToGatewayResponse;
+
+                    /**
+                     * Decodes a BindDeviceToGatewayResponse message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns BindDeviceToGatewayResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.BindDeviceToGatewayResponse;
+
+                    /**
+                     * Verifies a BindDeviceToGatewayResponse message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a BindDeviceToGatewayResponse message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns BindDeviceToGatewayResponse
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.BindDeviceToGatewayResponse;
+
+                    /**
+                     * Creates a plain object from a BindDeviceToGatewayResponse message. Also converts values to other types if specified.
+                     * @param message BindDeviceToGatewayResponse
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.BindDeviceToGatewayResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this BindDeviceToGatewayResponse to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of an UnbindDeviceFromGatewayRequest. */
+                interface IUnbindDeviceFromGatewayRequest {
+
+                    /** UnbindDeviceFromGatewayRequest parent */
+                    parent?: (string|null);
+
+                    /** UnbindDeviceFromGatewayRequest gatewayId */
+                    gatewayId?: (string|null);
+
+                    /** UnbindDeviceFromGatewayRequest deviceId */
+                    deviceId?: (string|null);
+                }
+
+                /** Represents an UnbindDeviceFromGatewayRequest. */
+                class UnbindDeviceFromGatewayRequest implements IUnbindDeviceFromGatewayRequest {
+
+                    /**
+                     * Constructs a new UnbindDeviceFromGatewayRequest.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest);
+
+                    /** UnbindDeviceFromGatewayRequest parent. */
+                    public parent: string;
+
+                    /** UnbindDeviceFromGatewayRequest gatewayId. */
+                    public gatewayId: string;
+
+                    /** UnbindDeviceFromGatewayRequest deviceId. */
+                    public deviceId: string;
+
+                    /**
+                     * Creates a new UnbindDeviceFromGatewayRequest instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns UnbindDeviceFromGatewayRequest instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest): google.cloud.iot.v1.UnbindDeviceFromGatewayRequest;
+
+                    /**
+                     * Encodes the specified UnbindDeviceFromGatewayRequest message. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayRequest.verify|verify} messages.
+                     * @param message UnbindDeviceFromGatewayRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified UnbindDeviceFromGatewayRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayRequest.verify|verify} messages.
+                     * @param message UnbindDeviceFromGatewayRequest message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes an UnbindDeviceFromGatewayRequest message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns UnbindDeviceFromGatewayRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.UnbindDeviceFromGatewayRequest;
+
+                    /**
+                     * Decodes an UnbindDeviceFromGatewayRequest message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns UnbindDeviceFromGatewayRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.UnbindDeviceFromGatewayRequest;
+
+                    /**
+                     * Verifies an UnbindDeviceFromGatewayRequest message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates an UnbindDeviceFromGatewayRequest message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns UnbindDeviceFromGatewayRequest
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.UnbindDeviceFromGatewayRequest;
+
+                    /**
+                     * Creates a plain object from an UnbindDeviceFromGatewayRequest message. Also converts values to other types if specified.
+                     * @param message UnbindDeviceFromGatewayRequest
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.UnbindDeviceFromGatewayRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this UnbindDeviceFromGatewayRequest to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of an UnbindDeviceFromGatewayResponse. */
+                interface IUnbindDeviceFromGatewayResponse {
+                }
+
+                /** Represents an UnbindDeviceFromGatewayResponse. */
+                class UnbindDeviceFromGatewayResponse implements IUnbindDeviceFromGatewayResponse {
+
+                    /**
+                     * Constructs a new UnbindDeviceFromGatewayResponse.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse);
+
+                    /**
+                     * Creates a new UnbindDeviceFromGatewayResponse instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns UnbindDeviceFromGatewayResponse instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse): google.cloud.iot.v1.UnbindDeviceFromGatewayResponse;
+
+                    /**
+                     * Encodes the specified UnbindDeviceFromGatewayResponse message. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayResponse.verify|verify} messages.
+                     * @param message UnbindDeviceFromGatewayResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified UnbindDeviceFromGatewayResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayResponse.verify|verify} messages.
+                     * @param message UnbindDeviceFromGatewayResponse message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes an UnbindDeviceFromGatewayResponse message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns UnbindDeviceFromGatewayResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.UnbindDeviceFromGatewayResponse;
+
+                    /**
+                     * Decodes an UnbindDeviceFromGatewayResponse message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns UnbindDeviceFromGatewayResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.UnbindDeviceFromGatewayResponse;
+
+                    /**
+                     * Verifies an UnbindDeviceFromGatewayResponse message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates an UnbindDeviceFromGatewayResponse message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns UnbindDeviceFromGatewayResponse
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.UnbindDeviceFromGatewayResponse;
+
+                    /**
+                     * Creates a plain object from an UnbindDeviceFromGatewayResponse message. Also converts values to other types if specified.
+                     * @param message UnbindDeviceFromGatewayResponse
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.UnbindDeviceFromGatewayResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this UnbindDeviceFromGatewayResponse to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a Device. */
+                interface IDevice {
+
+                    /** Device id */
+                    id?: (string|null);
+
+                    /** Device name */
+                    name?: (string|null);
+
+                    /** Device numId */
+                    numId?: (number|Long|string|null);
+
+                    /** Device credentials */
+                    credentials?: (google.cloud.iot.v1.IDeviceCredential[]|null);
+
+                    /** Device lastHeartbeatTime */
+                    lastHeartbeatTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastEventTime */
+                    lastEventTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastStateTime */
+                    lastStateTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastConfigAckTime */
+                    lastConfigAckTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastConfigSendTime */
+                    lastConfigSendTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device blocked */
+                    blocked?: (boolean|null);
+
+                    /** Device lastErrorTime */
+                    lastErrorTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastErrorStatus */
+                    lastErrorStatus?: (google.rpc.IStatus|null);
+
+                    /** Device config */
+                    config?: (google.cloud.iot.v1.IDeviceConfig|null);
+
+                    /** Device state */
+                    state?: (google.cloud.iot.v1.IDeviceState|null);
+
+                    /** Device logLevel */
+                    logLevel?: (google.cloud.iot.v1.LogLevel|keyof typeof google.cloud.iot.v1.LogLevel|null);
+
+                    /** Device metadata */
+                    metadata?: ({ [k: string]: string }|null);
+
+                    /** Device gatewayConfig */
+                    gatewayConfig?: (google.cloud.iot.v1.IGatewayConfig|null);
+                }
+
+                /** Represents a Device. */
+                class Device implements IDevice {
+
+                    /**
+                     * Constructs a new Device.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IDevice);
+
+                    /** Device id. */
+                    public id: string;
+
+                    /** Device name. */
+                    public name: string;
+
+                    /** Device numId. */
+                    public numId: (number|Long|string);
+
+                    /** Device credentials. */
+                    public credentials: google.cloud.iot.v1.IDeviceCredential[];
+
+                    /** Device lastHeartbeatTime. */
+                    public lastHeartbeatTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastEventTime. */
+                    public lastEventTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastStateTime. */
+                    public lastStateTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastConfigAckTime. */
+                    public lastConfigAckTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastConfigSendTime. */
+                    public lastConfigSendTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device blocked. */
+                    public blocked: boolean;
+
+                    /** Device lastErrorTime. */
+                    public lastErrorTime?: (google.protobuf.ITimestamp|null);
+
+                    /** Device lastErrorStatus. */
+                    public lastErrorStatus?: (google.rpc.IStatus|null);
+
+                    /** Device config. */
+                    public config?: (google.cloud.iot.v1.IDeviceConfig|null);
+
+                    /** Device state. */
+                    public state?: (google.cloud.iot.v1.IDeviceState|null);
+
+                    /** Device logLevel. */
+                    public logLevel: (google.cloud.iot.v1.LogLevel|keyof typeof google.cloud.iot.v1.LogLevel);
+
+                    /** Device metadata. */
+                    public metadata: { [k: string]: string };
+
+                    /** Device gatewayConfig. */
+                    public gatewayConfig?: (google.cloud.iot.v1.IGatewayConfig|null);
+
+                    /**
+                     * Creates a new Device instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns Device instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IDevice): google.cloud.iot.v1.Device;
+
+                    /**
+                     * Encodes the specified Device message. Does not implicitly {@link google.cloud.iot.v1.Device.verify|verify} messages.
+                     * @param message Device message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IDevice, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified Device message, length delimited. Does not implicitly {@link google.cloud.iot.v1.Device.verify|verify} messages.
+                     * @param message Device message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IDevice, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a Device message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns Device
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.Device;
+
+                    /**
+                     * Decodes a Device message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns Device
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.Device;
+
+                    /**
+                     * Verifies a Device message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a Device message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns Device
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.Device;
+
+                    /**
+                     * Creates a plain object from a Device message. Also converts values to other types if specified.
+                     * @param message Device
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.Device, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this Device to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a GatewayConfig. */
+                interface IGatewayConfig {
+
+                    /** GatewayConfig gatewayType */
+                    gatewayType?: (google.cloud.iot.v1.GatewayType|keyof typeof google.cloud.iot.v1.GatewayType|null);
+
+                    /** GatewayConfig gatewayAuthMethod */
+                    gatewayAuthMethod?: (google.cloud.iot.v1.GatewayAuthMethod|keyof typeof google.cloud.iot.v1.GatewayAuthMethod|null);
+
+                    /** GatewayConfig lastAccessedGatewayId */
+                    lastAccessedGatewayId?: (string|null);
+
+                    /** GatewayConfig lastAccessedGatewayTime */
+                    lastAccessedGatewayTime?: (google.protobuf.ITimestamp|null);
+                }
+
+                /** Represents a GatewayConfig. */
+                class GatewayConfig implements IGatewayConfig {
+
+                    /**
+                     * Constructs a new GatewayConfig.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IGatewayConfig);
+
+                    /** GatewayConfig gatewayType. */
+                    public gatewayType: (google.cloud.iot.v1.GatewayType|keyof typeof google.cloud.iot.v1.GatewayType);
+
+                    /** GatewayConfig gatewayAuthMethod. */
+                    public gatewayAuthMethod: (google.cloud.iot.v1.GatewayAuthMethod|keyof typeof google.cloud.iot.v1.GatewayAuthMethod);
+
+                    /** GatewayConfig lastAccessedGatewayId. */
+                    public lastAccessedGatewayId: string;
+
+                    /** GatewayConfig lastAccessedGatewayTime. */
+                    public lastAccessedGatewayTime?: (google.protobuf.ITimestamp|null);
+
+                    /**
+                     * Creates a new GatewayConfig instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns GatewayConfig instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IGatewayConfig): google.cloud.iot.v1.GatewayConfig;
+
+                    /**
+                     * Encodes the specified GatewayConfig message. Does not implicitly {@link google.cloud.iot.v1.GatewayConfig.verify|verify} messages.
+                     * @param message GatewayConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IGatewayConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified GatewayConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GatewayConfig.verify|verify} messages.
+                     * @param message GatewayConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IGatewayConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a GatewayConfig message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns GatewayConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.GatewayConfig;
+
+                    /**
+                     * Decodes a GatewayConfig message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns GatewayConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.GatewayConfig;
+
+                    /**
+                     * Verifies a GatewayConfig message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a GatewayConfig message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns GatewayConfig
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.GatewayConfig;
+
+                    /**
+                     * Creates a plain object from a GatewayConfig message. Also converts values to other types if specified.
+                     * @param message GatewayConfig
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.GatewayConfig, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this GatewayConfig to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a DeviceRegistry. */
+                interface IDeviceRegistry {
+
+                    /** DeviceRegistry id */
+                    id?: (string|null);
+
+                    /** DeviceRegistry name */
+                    name?: (string|null);
+
+                    /** DeviceRegistry eventNotificationConfigs */
+                    eventNotificationConfigs?: (google.cloud.iot.v1.IEventNotificationConfig[]|null);
+
+                    /** DeviceRegistry stateNotificationConfig */
+                    stateNotificationConfig?: (google.cloud.iot.v1.IStateNotificationConfig|null);
+
+                    /** DeviceRegistry mqttConfig */
+                    mqttConfig?: (google.cloud.iot.v1.IMqttConfig|null);
+
+                    /** DeviceRegistry httpConfig */
+                    httpConfig?: (google.cloud.iot.v1.IHttpConfig|null);
+
+                    /** DeviceRegistry logLevel */
+                    logLevel?: (google.cloud.iot.v1.LogLevel|keyof typeof google.cloud.iot.v1.LogLevel|null);
+
+                    /** DeviceRegistry credentials */
+                    credentials?: (google.cloud.iot.v1.IRegistryCredential[]|null);
+                }
+
+                /** Represents a DeviceRegistry. */
+                class DeviceRegistry implements IDeviceRegistry {
+
+                    /**
+                     * Constructs a new DeviceRegistry.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IDeviceRegistry);
+
+                    /** DeviceRegistry id. */
+                    public id: string;
+
+                    /** DeviceRegistry name. */
+                    public name: string;
+
+                    /** DeviceRegistry eventNotificationConfigs. */
+                    public eventNotificationConfigs: google.cloud.iot.v1.IEventNotificationConfig[];
+
+                    /** DeviceRegistry stateNotificationConfig. */
+                    public stateNotificationConfig?: (google.cloud.iot.v1.IStateNotificationConfig|null);
+
+                    /** DeviceRegistry mqttConfig. */
+                    public mqttConfig?: (google.cloud.iot.v1.IMqttConfig|null);
+
+                    /** DeviceRegistry httpConfig. */
+                    public httpConfig?: (google.cloud.iot.v1.IHttpConfig|null);
+
+                    /** DeviceRegistry logLevel. */
+                    public logLevel: (google.cloud.iot.v1.LogLevel|keyof typeof google.cloud.iot.v1.LogLevel);
+
+                    /** DeviceRegistry credentials. */
+                    public credentials: google.cloud.iot.v1.IRegistryCredential[];
+
+                    /**
+                     * Creates a new DeviceRegistry instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns DeviceRegistry instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IDeviceRegistry): google.cloud.iot.v1.DeviceRegistry;
+
+                    /**
+                     * Encodes the specified DeviceRegistry message. Does not implicitly {@link google.cloud.iot.v1.DeviceRegistry.verify|verify} messages.
+                     * @param message DeviceRegistry message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IDeviceRegistry, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified DeviceRegistry message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceRegistry.verify|verify} messages.
+                     * @param message DeviceRegistry message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IDeviceRegistry, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a DeviceRegistry message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns DeviceRegistry
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.DeviceRegistry;
+
+                    /**
+                     * Decodes a DeviceRegistry message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns DeviceRegistry
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.DeviceRegistry;
+
+                    /**
+                     * Verifies a DeviceRegistry message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a DeviceRegistry message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns DeviceRegistry
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.DeviceRegistry;
+
+                    /**
+                     * Creates a plain object from a DeviceRegistry message. Also converts values to other types if specified.
+                     * @param message DeviceRegistry
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.DeviceRegistry, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this DeviceRegistry to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a MqttConfig. */
+                interface IMqttConfig {
+
+                    /** MqttConfig mqttEnabledState */
+                    mqttEnabledState?: (google.cloud.iot.v1.MqttState|keyof typeof google.cloud.iot.v1.MqttState|null);
+                }
+
+                /** Represents a MqttConfig. */
+                class MqttConfig implements IMqttConfig {
+
+                    /**
+                     * Constructs a new MqttConfig.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IMqttConfig);
+
+                    /** MqttConfig mqttEnabledState. */
+                    public mqttEnabledState: (google.cloud.iot.v1.MqttState|keyof typeof google.cloud.iot.v1.MqttState);
+
+                    /**
+                     * Creates a new MqttConfig instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns MqttConfig instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IMqttConfig): google.cloud.iot.v1.MqttConfig;
+
+                    /**
+                     * Encodes the specified MqttConfig message. Does not implicitly {@link google.cloud.iot.v1.MqttConfig.verify|verify} messages.
+                     * @param message MqttConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IMqttConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified MqttConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.MqttConfig.verify|verify} messages.
+                     * @param message MqttConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IMqttConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a MqttConfig message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns MqttConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.MqttConfig;
+
+                    /**
+                     * Decodes a MqttConfig message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns MqttConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.MqttConfig;
+
+                    /**
+                     * Verifies a MqttConfig message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a MqttConfig message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns MqttConfig
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.MqttConfig;
+
+                    /**
+                     * Creates a plain object from a MqttConfig message. Also converts values to other types if specified.
+                     * @param message MqttConfig
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.MqttConfig, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this MqttConfig to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** MqttState enum. */
+                enum MqttState {
+                    MQTT_STATE_UNSPECIFIED = 0,
+                    MQTT_ENABLED = 1,
+                    MQTT_DISABLED = 2
+                }
+
+                /** Properties of a HttpConfig. */
+                interface IHttpConfig {
+
+                    /** HttpConfig httpEnabledState */
+                    httpEnabledState?: (google.cloud.iot.v1.HttpState|keyof typeof google.cloud.iot.v1.HttpState|null);
+                }
+
+                /** Represents a HttpConfig. */
+                class HttpConfig implements IHttpConfig {
+
+                    /**
+                     * Constructs a new HttpConfig.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IHttpConfig);
+
+                    /** HttpConfig httpEnabledState. */
+                    public httpEnabledState: (google.cloud.iot.v1.HttpState|keyof typeof google.cloud.iot.v1.HttpState);
+
+                    /**
+                     * Creates a new HttpConfig instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns HttpConfig instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IHttpConfig): google.cloud.iot.v1.HttpConfig;
+
+                    /**
+                     * Encodes the specified HttpConfig message. Does not implicitly {@link google.cloud.iot.v1.HttpConfig.verify|verify} messages.
+                     * @param message HttpConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IHttpConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified HttpConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.HttpConfig.verify|verify} messages.
+                     * @param message HttpConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IHttpConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a HttpConfig message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns HttpConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.HttpConfig;
+
+                    /**
+                     * Decodes a HttpConfig message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns HttpConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.HttpConfig;
+
+                    /**
+                     * Verifies a HttpConfig message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a HttpConfig message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns HttpConfig
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.HttpConfig;
+
+                    /**
+                     * Creates a plain object from a HttpConfig message. Also converts values to other types if specified.
+                     * @param message HttpConfig
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.HttpConfig, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this HttpConfig to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** HttpState enum. */
+                enum HttpState {
+                    HTTP_STATE_UNSPECIFIED = 0,
+                    HTTP_ENABLED = 1,
+                    HTTP_DISABLED = 2
+                }
+
+                /** LogLevel enum. */
+                enum LogLevel {
+                    LOG_LEVEL_UNSPECIFIED = 0,
+                    NONE = 10,
+                    ERROR = 20,
+                    INFO = 30,
+                    DEBUG = 40
+                }
+
+                /** GatewayType enum. */
+                enum GatewayType {
+                    GATEWAY_TYPE_UNSPECIFIED = 0,
+                    GATEWAY = 1,
+                    NON_GATEWAY = 2
+                }
+
+                /** GatewayAuthMethod enum. */
+                enum GatewayAuthMethod {
+                    GATEWAY_AUTH_METHOD_UNSPECIFIED = 0,
+                    ASSOCIATION_ONLY = 1,
+                    DEVICE_AUTH_TOKEN_ONLY = 2,
+                    ASSOCIATION_AND_DEVICE_AUTH_TOKEN = 3
+                }
+
+                /** Properties of an EventNotificationConfig. */
+                interface IEventNotificationConfig {
+
+                    /** EventNotificationConfig subfolderMatches */
+                    subfolderMatches?: (string|null);
+
+                    /** EventNotificationConfig pubsubTopicName */
+                    pubsubTopicName?: (string|null);
+                }
+
+                /** Represents an EventNotificationConfig. */
+                class EventNotificationConfig implements IEventNotificationConfig {
+
+                    /**
+                     * Constructs a new EventNotificationConfig.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IEventNotificationConfig);
+
+                    /** EventNotificationConfig subfolderMatches. */
+                    public subfolderMatches: string;
+
+                    /** EventNotificationConfig pubsubTopicName. */
+                    public pubsubTopicName: string;
+
+                    /**
+                     * Creates a new EventNotificationConfig instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns EventNotificationConfig instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IEventNotificationConfig): google.cloud.iot.v1.EventNotificationConfig;
+
+                    /**
+                     * Encodes the specified EventNotificationConfig message. Does not implicitly {@link google.cloud.iot.v1.EventNotificationConfig.verify|verify} messages.
+                     * @param message EventNotificationConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IEventNotificationConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified EventNotificationConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.EventNotificationConfig.verify|verify} messages.
+                     * @param message EventNotificationConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IEventNotificationConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes an EventNotificationConfig message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns EventNotificationConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.EventNotificationConfig;
+
+                    /**
+                     * Decodes an EventNotificationConfig message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns EventNotificationConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.EventNotificationConfig;
+
+                    /**
+                     * Verifies an EventNotificationConfig message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates an EventNotificationConfig message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns EventNotificationConfig
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.EventNotificationConfig;
+
+                    /**
+                     * Creates a plain object from an EventNotificationConfig message. Also converts values to other types if specified.
+                     * @param message EventNotificationConfig
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.EventNotificationConfig, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this EventNotificationConfig to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a StateNotificationConfig. */
+                interface IStateNotificationConfig {
+
+                    /** StateNotificationConfig pubsubTopicName */
+                    pubsubTopicName?: (string|null);
+                }
+
+                /** Represents a StateNotificationConfig. */
+                class StateNotificationConfig implements IStateNotificationConfig {
+
+                    /**
+                     * Constructs a new StateNotificationConfig.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IStateNotificationConfig);
+
+                    /** StateNotificationConfig pubsubTopicName. */
+                    public pubsubTopicName: string;
+
+                    /**
+                     * Creates a new StateNotificationConfig instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns StateNotificationConfig instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IStateNotificationConfig): google.cloud.iot.v1.StateNotificationConfig;
+
+                    /**
+                     * Encodes the specified StateNotificationConfig message. Does not implicitly {@link google.cloud.iot.v1.StateNotificationConfig.verify|verify} messages.
+                     * @param message StateNotificationConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IStateNotificationConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified StateNotificationConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.StateNotificationConfig.verify|verify} messages.
+                     * @param message StateNotificationConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IStateNotificationConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a StateNotificationConfig message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns StateNotificationConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.StateNotificationConfig;
+
+                    /**
+                     * Decodes a StateNotificationConfig message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns StateNotificationConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.StateNotificationConfig;
+
+                    /**
+                     * Verifies a StateNotificationConfig message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a StateNotificationConfig message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns StateNotificationConfig
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.StateNotificationConfig;
+
+                    /**
+                     * Creates a plain object from a StateNotificationConfig message. Also converts values to other types if specified.
+                     * @param message StateNotificationConfig
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.StateNotificationConfig, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this StateNotificationConfig to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a RegistryCredential. */
+                interface IRegistryCredential {
+
+                    /** RegistryCredential publicKeyCertificate */
+                    publicKeyCertificate?: (google.cloud.iot.v1.IPublicKeyCertificate|null);
+                }
+
+                /** Represents a RegistryCredential. */
+                class RegistryCredential implements IRegistryCredential {
+
+                    /**
+                     * Constructs a new RegistryCredential.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IRegistryCredential);
+
+                    /** RegistryCredential publicKeyCertificate. */
+                    public publicKeyCertificate?: (google.cloud.iot.v1.IPublicKeyCertificate|null);
+
+                    /** RegistryCredential credential. */
+                    public credential?: "publicKeyCertificate";
+
+                    /**
+                     * Creates a new RegistryCredential instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns RegistryCredential instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IRegistryCredential): google.cloud.iot.v1.RegistryCredential;
+
+                    /**
+                     * Encodes the specified RegistryCredential message. Does not implicitly {@link google.cloud.iot.v1.RegistryCredential.verify|verify} messages.
+                     * @param message RegistryCredential message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IRegistryCredential, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified RegistryCredential message, length delimited. Does not implicitly {@link google.cloud.iot.v1.RegistryCredential.verify|verify} messages.
+                     * @param message RegistryCredential message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IRegistryCredential, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a RegistryCredential message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns RegistryCredential
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.RegistryCredential;
+
+                    /**
+                     * Decodes a RegistryCredential message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns RegistryCredential
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.RegistryCredential;
+
+                    /**
+                     * Verifies a RegistryCredential message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a RegistryCredential message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns RegistryCredential
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.RegistryCredential;
+
+                    /**
+                     * Creates a plain object from a RegistryCredential message. Also converts values to other types if specified.
+                     * @param message RegistryCredential
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.RegistryCredential, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this RegistryCredential to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a X509CertificateDetails. */
+                interface IX509CertificateDetails {
+
+                    /** X509CertificateDetails issuer */
+                    issuer?: (string|null);
+
+                    /** X509CertificateDetails subject */
+                    subject?: (string|null);
+
+                    /** X509CertificateDetails startTime */
+                    startTime?: (google.protobuf.ITimestamp|null);
+
+                    /** X509CertificateDetails expiryTime */
+                    expiryTime?: (google.protobuf.ITimestamp|null);
+
+                    /** X509CertificateDetails signatureAlgorithm */
+                    signatureAlgorithm?: (string|null);
+
+                    /** X509CertificateDetails publicKeyType */
+                    publicKeyType?: (string|null);
+                }
+
+                /** Represents a X509CertificateDetails. */
+                class X509CertificateDetails implements IX509CertificateDetails {
+
+                    /**
+                     * Constructs a new X509CertificateDetails.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IX509CertificateDetails);
+
+                    /** X509CertificateDetails issuer. */
+                    public issuer: string;
+
+                    /** X509CertificateDetails subject. */
+                    public subject: string;
+
+                    /** X509CertificateDetails startTime. */
+                    public startTime?: (google.protobuf.ITimestamp|null);
+
+                    /** X509CertificateDetails expiryTime. */
+                    public expiryTime?: (google.protobuf.ITimestamp|null);
+
+                    /** X509CertificateDetails signatureAlgorithm. */
+                    public signatureAlgorithm: string;
+
+                    /** X509CertificateDetails publicKeyType. */
+                    public publicKeyType: string;
+
+                    /**
+                     * Creates a new X509CertificateDetails instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns X509CertificateDetails instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IX509CertificateDetails): google.cloud.iot.v1.X509CertificateDetails;
+
+                    /**
+                     * Encodes the specified X509CertificateDetails message. Does not implicitly {@link google.cloud.iot.v1.X509CertificateDetails.verify|verify} messages.
+                     * @param message X509CertificateDetails message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IX509CertificateDetails, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified X509CertificateDetails message, length delimited. Does not implicitly {@link google.cloud.iot.v1.X509CertificateDetails.verify|verify} messages.
+                     * @param message X509CertificateDetails message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IX509CertificateDetails, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a X509CertificateDetails message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns X509CertificateDetails
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.X509CertificateDetails;
+
+                    /**
+                     * Decodes a X509CertificateDetails message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns X509CertificateDetails
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.X509CertificateDetails;
+
+                    /**
+                     * Verifies a X509CertificateDetails message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a X509CertificateDetails message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns X509CertificateDetails
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.X509CertificateDetails;
+
+                    /**
+                     * Creates a plain object from a X509CertificateDetails message. Also converts values to other types if specified.
+                     * @param message X509CertificateDetails
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.X509CertificateDetails, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this X509CertificateDetails to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a PublicKeyCertificate. */
+                interface IPublicKeyCertificate {
+
+                    /** PublicKeyCertificate format */
+                    format?: (google.cloud.iot.v1.PublicKeyCertificateFormat|keyof typeof google.cloud.iot.v1.PublicKeyCertificateFormat|null);
+
+                    /** PublicKeyCertificate certificate */
+                    certificate?: (string|null);
+
+                    /** PublicKeyCertificate x509Details */
+                    x509Details?: (google.cloud.iot.v1.IX509CertificateDetails|null);
+                }
+
+                /** Represents a PublicKeyCertificate. */
+                class PublicKeyCertificate implements IPublicKeyCertificate {
+
+                    /**
+                     * Constructs a new PublicKeyCertificate.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IPublicKeyCertificate);
+
+                    /** PublicKeyCertificate format. */
+                    public format: (google.cloud.iot.v1.PublicKeyCertificateFormat|keyof typeof google.cloud.iot.v1.PublicKeyCertificateFormat);
+
+                    /** PublicKeyCertificate certificate. */
+                    public certificate: string;
+
+                    /** PublicKeyCertificate x509Details. */
+                    public x509Details?: (google.cloud.iot.v1.IX509CertificateDetails|null);
+
+                    /**
+                     * Creates a new PublicKeyCertificate instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns PublicKeyCertificate instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IPublicKeyCertificate): google.cloud.iot.v1.PublicKeyCertificate;
+
+                    /**
+                     * Encodes the specified PublicKeyCertificate message. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCertificate.verify|verify} messages.
+                     * @param message PublicKeyCertificate message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IPublicKeyCertificate, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified PublicKeyCertificate message, length delimited. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCertificate.verify|verify} messages.
+                     * @param message PublicKeyCertificate message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IPublicKeyCertificate, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a PublicKeyCertificate message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns PublicKeyCertificate
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.PublicKeyCertificate;
+
+                    /**
+                     * Decodes a PublicKeyCertificate message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns PublicKeyCertificate
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.PublicKeyCertificate;
+
+                    /**
+                     * Verifies a PublicKeyCertificate message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a PublicKeyCertificate message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns PublicKeyCertificate
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.PublicKeyCertificate;
+
+                    /**
+                     * Creates a plain object from a PublicKeyCertificate message. Also converts values to other types if specified.
+                     * @param message PublicKeyCertificate
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.PublicKeyCertificate, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this PublicKeyCertificate to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** PublicKeyCertificateFormat enum. */
+                enum PublicKeyCertificateFormat {
+                    UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT = 0,
+                    X509_CERTIFICATE_PEM = 1
+                }
+
+                /** Properties of a DeviceCredential. */
+                interface IDeviceCredential {
+
+                    /** DeviceCredential publicKey */
+                    publicKey?: (google.cloud.iot.v1.IPublicKeyCredential|null);
+
+                    /** DeviceCredential expirationTime */
+                    expirationTime?: (google.protobuf.ITimestamp|null);
+                }
+
+                /** Represents a DeviceCredential. */
+                class DeviceCredential implements IDeviceCredential {
+
+                    /**
+                     * Constructs a new DeviceCredential.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IDeviceCredential);
+
+                    /** DeviceCredential publicKey. */
+                    public publicKey?: (google.cloud.iot.v1.IPublicKeyCredential|null);
+
+                    /** DeviceCredential expirationTime. */
+                    public expirationTime?: (google.protobuf.ITimestamp|null);
+
+                    /** DeviceCredential credential. */
+                    public credential?: "publicKey";
+
+                    /**
+                     * Creates a new DeviceCredential instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns DeviceCredential instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IDeviceCredential): google.cloud.iot.v1.DeviceCredential;
+
+                    /**
+                     * Encodes the specified DeviceCredential message. Does not implicitly {@link google.cloud.iot.v1.DeviceCredential.verify|verify} messages.
+                     * @param message DeviceCredential message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IDeviceCredential, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified DeviceCredential message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceCredential.verify|verify} messages.
+                     * @param message DeviceCredential message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IDeviceCredential, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a DeviceCredential message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns DeviceCredential
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.DeviceCredential;
+
+                    /**
+                     * Decodes a DeviceCredential message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns DeviceCredential
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.DeviceCredential;
+
+                    /**
+                     * Verifies a DeviceCredential message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a DeviceCredential message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns DeviceCredential
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.DeviceCredential;
+
+                    /**
+                     * Creates a plain object from a DeviceCredential message. Also converts values to other types if specified.
+                     * @param message DeviceCredential
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.DeviceCredential, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this DeviceCredential to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a PublicKeyCredential. */
+                interface IPublicKeyCredential {
+
+                    /** PublicKeyCredential format */
+                    format?: (google.cloud.iot.v1.PublicKeyFormat|keyof typeof google.cloud.iot.v1.PublicKeyFormat|null);
+
+                    /** PublicKeyCredential key */
+                    key?: (string|null);
+                }
+
+                /** Represents a PublicKeyCredential. */
+                class PublicKeyCredential implements IPublicKeyCredential {
+
+                    /**
+                     * Constructs a new PublicKeyCredential.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IPublicKeyCredential);
+
+                    /** PublicKeyCredential format. */
+                    public format: (google.cloud.iot.v1.PublicKeyFormat|keyof typeof google.cloud.iot.v1.PublicKeyFormat);
+
+                    /** PublicKeyCredential key. */
+                    public key: string;
+
+                    /**
+                     * Creates a new PublicKeyCredential instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns PublicKeyCredential instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IPublicKeyCredential): google.cloud.iot.v1.PublicKeyCredential;
+
+                    /**
+                     * Encodes the specified PublicKeyCredential message. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCredential.verify|verify} messages.
+                     * @param message PublicKeyCredential message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IPublicKeyCredential, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified PublicKeyCredential message, length delimited. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCredential.verify|verify} messages.
+                     * @param message PublicKeyCredential message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IPublicKeyCredential, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a PublicKeyCredential message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns PublicKeyCredential
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.PublicKeyCredential;
+
+                    /**
+                     * Decodes a PublicKeyCredential message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns PublicKeyCredential
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.PublicKeyCredential;
+
+                    /**
+                     * Verifies a PublicKeyCredential message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a PublicKeyCredential message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns PublicKeyCredential
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.PublicKeyCredential;
+
+                    /**
+                     * Creates a plain object from a PublicKeyCredential message. Also converts values to other types if specified.
+                     * @param message PublicKeyCredential
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.PublicKeyCredential, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this PublicKeyCredential to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** PublicKeyFormat enum. */
+                enum PublicKeyFormat {
+                    UNSPECIFIED_PUBLIC_KEY_FORMAT = 0,
+                    RSA_PEM = 3,
+                    RSA_X509_PEM = 1,
+                    ES256_PEM = 2,
+                    ES256_X509_PEM = 4
+                }
+
+                /** Properties of a DeviceConfig. */
+                interface IDeviceConfig {
+
+                    /** DeviceConfig version */
+                    version?: (number|Long|string|null);
+
+                    /** DeviceConfig cloudUpdateTime */
+                    cloudUpdateTime?: (google.protobuf.ITimestamp|null);
+
+                    /** DeviceConfig deviceAckTime */
+                    deviceAckTime?: (google.protobuf.ITimestamp|null);
+
+                    /** DeviceConfig binaryData */
+                    binaryData?: (Uint8Array|string|null);
+                }
+
+                /** Represents a DeviceConfig. */
+                class DeviceConfig implements IDeviceConfig {
+
+                    /**
+                     * Constructs a new DeviceConfig.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IDeviceConfig);
+
+                    /** DeviceConfig version. */
+                    public version: (number|Long|string);
+
+                    /** DeviceConfig cloudUpdateTime. */
+                    public cloudUpdateTime?: (google.protobuf.ITimestamp|null);
+
+                    /** DeviceConfig deviceAckTime. */
+                    public deviceAckTime?: (google.protobuf.ITimestamp|null);
+
+                    /** DeviceConfig binaryData. */
+                    public binaryData: (Uint8Array|string);
+
+                    /**
+                     * Creates a new DeviceConfig instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns DeviceConfig instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IDeviceConfig): google.cloud.iot.v1.DeviceConfig;
+
+                    /**
+                     * Encodes the specified DeviceConfig message. Does not implicitly {@link google.cloud.iot.v1.DeviceConfig.verify|verify} messages.
+                     * @param message DeviceConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IDeviceConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified DeviceConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceConfig.verify|verify} messages.
+                     * @param message DeviceConfig message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IDeviceConfig, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a DeviceConfig message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns DeviceConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.DeviceConfig;
+
+                    /**
+                     * Decodes a DeviceConfig message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns DeviceConfig
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.DeviceConfig;
+
+                    /**
+                     * Verifies a DeviceConfig message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a DeviceConfig message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns DeviceConfig
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.DeviceConfig;
+
+                    /**
+                     * Creates a plain object from a DeviceConfig message. Also converts values to other types if specified.
+                     * @param message DeviceConfig
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.DeviceConfig, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this DeviceConfig to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+
+                /** Properties of a DeviceState. */
+                interface IDeviceState {
+
+                    /** DeviceState updateTime */
+                    updateTime?: (google.protobuf.ITimestamp|null);
+
+                    /** DeviceState binaryData */
+                    binaryData?: (Uint8Array|string|null);
+                }
+
+                /** Represents a DeviceState. */
+                class DeviceState implements IDeviceState {
+
+                    /**
+                     * Constructs a new DeviceState.
+                     * @param [properties] Properties to set
+                     */
+                    constructor(properties?: google.cloud.iot.v1.IDeviceState);
+
+                    /** DeviceState updateTime. */
+                    public updateTime?: (google.protobuf.ITimestamp|null);
+
+                    /** DeviceState binaryData. */
+                    public binaryData: (Uint8Array|string);
+
+                    /**
+                     * Creates a new DeviceState instance using the specified properties.
+                     * @param [properties] Properties to set
+                     * @returns DeviceState instance
+                     */
+                    public static create(properties?: google.cloud.iot.v1.IDeviceState): google.cloud.iot.v1.DeviceState;
+
+                    /**
+                     * Encodes the specified DeviceState message. Does not implicitly {@link google.cloud.iot.v1.DeviceState.verify|verify} messages.
+                     * @param message DeviceState message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encode(message: google.cloud.iot.v1.IDeviceState, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Encodes the specified DeviceState message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceState.verify|verify} messages.
+                     * @param message DeviceState message or plain object to encode
+                     * @param [writer] Writer to encode to
+                     * @returns Writer
+                     */
+                    public static encodeDelimited(message: google.cloud.iot.v1.IDeviceState, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                    /**
+                     * Decodes a DeviceState message from the specified reader or buffer.
+                     * @param reader Reader or buffer to decode from
+                     * @param [length] Message length if known beforehand
+                     * @returns DeviceState
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.cloud.iot.v1.DeviceState;
+
+                    /**
+                     * Decodes a DeviceState message from the specified reader or buffer, length delimited.
+                     * @param reader Reader or buffer to decode from
+                     * @returns DeviceState
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.cloud.iot.v1.DeviceState;
+
+                    /**
+                     * Verifies a DeviceState message.
+                     * @param message Plain object to verify
+                     * @returns `null` if valid, otherwise the reason why it is not
+                     */
+                    public static verify(message: { [k: string]: any }): (string|null);
+
+                    /**
+                     * Creates a DeviceState message from a plain object. Also converts values to their respective internal types.
+                     * @param object Plain object
+                     * @returns DeviceState
+                     */
+                    public static fromObject(object: { [k: string]: any }): google.cloud.iot.v1.DeviceState;
+
+                    /**
+                     * Creates a plain object from a DeviceState message. Also converts values to other types if specified.
+                     * @param message DeviceState
+                     * @param [options] Conversion options
+                     * @returns Plain object
+                     */
+                    public static toObject(message: google.cloud.iot.v1.DeviceState, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                    /**
+                     * Converts this DeviceState to JSON.
+                     * @returns JSON object
+                     */
+                    public toJSON(): { [k: string]: any };
+                }
+            }
+        }
+    }
+
+    /** Namespace api. */
+    namespace api {
+
+        /** Properties of a Http. */
+        interface IHttp {
+
+            /** Http rules */
+            rules?: (google.api.IHttpRule[]|null);
+
+            /** Http fullyDecodeReservedExpansion */
+            fullyDecodeReservedExpansion?: (boolean|null);
+        }
+
+        /** Represents a Http. */
+        class Http implements IHttp {
+
+            /**
+             * Constructs a new Http.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.api.IHttp);
+
+            /** Http rules. */
+            public rules: google.api.IHttpRule[];
+
+            /** Http fullyDecodeReservedExpansion. */
+            public fullyDecodeReservedExpansion: boolean;
+
+            /**
+             * Creates a new Http instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns Http instance
+             */
+            public static create(properties?: google.api.IHttp): google.api.Http;
+
+            /**
+             * Encodes the specified Http message. Does not implicitly {@link google.api.Http.verify|verify} messages.
+             * @param message Http message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.api.IHttp, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified Http message, length delimited. Does not implicitly {@link google.api.Http.verify|verify} messages.
+             * @param message Http message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.api.IHttp, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a Http message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns Http
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.api.Http;
+
+            /**
+             * Decodes a Http message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns Http
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.api.Http;
+
+            /**
+             * Verifies a Http message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a Http message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns Http
+             */
+            public static fromObject(object: { [k: string]: any }): google.api.Http;
+
+            /**
+             * Creates a plain object from a Http message. Also converts values to other types if specified.
+             * @param message Http
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.api.Http, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this Http to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a HttpRule. */
+        interface IHttpRule {
+
+            /** HttpRule selector */
+            selector?: (string|null);
+
+            /** HttpRule get */
+            get?: (string|null);
+
+            /** HttpRule put */
+            put?: (string|null);
+
+            /** HttpRule post */
+            post?: (string|null);
+
+            /** HttpRule delete */
+            "delete"?: (string|null);
+
+            /** HttpRule patch */
+            patch?: (string|null);
+
+            /** HttpRule custom */
+            custom?: (google.api.ICustomHttpPattern|null);
+
+            /** HttpRule body */
+            body?: (string|null);
+
+            /** HttpRule responseBody */
+            responseBody?: (string|null);
+
+            /** HttpRule additionalBindings */
+            additionalBindings?: (google.api.IHttpRule[]|null);
+        }
+
+        /** Represents a HttpRule. */
+        class HttpRule implements IHttpRule {
+
+            /**
+             * Constructs a new HttpRule.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.api.IHttpRule);
+
+            /** HttpRule selector. */
+            public selector: string;
+
+            /** HttpRule get. */
+            public get?: (string|null);
+
+            /** HttpRule put. */
+            public put?: (string|null);
+
+            /** HttpRule post. */
+            public post?: (string|null);
+
+            /** HttpRule delete. */
+            public delete?: (string|null);
+
+            /** HttpRule patch. */
+            public patch?: (string|null);
+
+            /** HttpRule custom. */
+            public custom?: (google.api.ICustomHttpPattern|null);
+
+            /** HttpRule body. */
+            public body: string;
+
+            /** HttpRule responseBody. */
+            public responseBody: string;
+
+            /** HttpRule additionalBindings. */
+            public additionalBindings: google.api.IHttpRule[];
+
+            /** HttpRule pattern. */
+            public pattern?: ("get"|"put"|"post"|"delete"|"patch"|"custom");
+
+            /**
+             * Creates a new HttpRule instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns HttpRule instance
+             */
+            public static create(properties?: google.api.IHttpRule): google.api.HttpRule;
+
+            /**
+             * Encodes the specified HttpRule message. Does not implicitly {@link google.api.HttpRule.verify|verify} messages.
+             * @param message HttpRule message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.api.IHttpRule, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified HttpRule message, length delimited. Does not implicitly {@link google.api.HttpRule.verify|verify} messages.
+             * @param message HttpRule message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.api.IHttpRule, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a HttpRule message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns HttpRule
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.api.HttpRule;
+
+            /**
+             * Decodes a HttpRule message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns HttpRule
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.api.HttpRule;
+
+            /**
+             * Verifies a HttpRule message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a HttpRule message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns HttpRule
+             */
+            public static fromObject(object: { [k: string]: any }): google.api.HttpRule;
+
+            /**
+             * Creates a plain object from a HttpRule message. Also converts values to other types if specified.
+             * @param message HttpRule
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.api.HttpRule, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this HttpRule to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a CustomHttpPattern. */
+        interface ICustomHttpPattern {
+
+            /** CustomHttpPattern kind */
+            kind?: (string|null);
+
+            /** CustomHttpPattern path */
+            path?: (string|null);
+        }
+
+        /** Represents a CustomHttpPattern. */
+        class CustomHttpPattern implements ICustomHttpPattern {
+
+            /**
+             * Constructs a new CustomHttpPattern.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.api.ICustomHttpPattern);
+
+            /** CustomHttpPattern kind. */
+            public kind: string;
+
+            /** CustomHttpPattern path. */
+            public path: string;
+
+            /**
+             * Creates a new CustomHttpPattern instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns CustomHttpPattern instance
+             */
+            public static create(properties?: google.api.ICustomHttpPattern): google.api.CustomHttpPattern;
+
+            /**
+             * Encodes the specified CustomHttpPattern message. Does not implicitly {@link google.api.CustomHttpPattern.verify|verify} messages.
+             * @param message CustomHttpPattern message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.api.ICustomHttpPattern, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified CustomHttpPattern message, length delimited. Does not implicitly {@link google.api.CustomHttpPattern.verify|verify} messages.
+             * @param message CustomHttpPattern message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.api.ICustomHttpPattern, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a CustomHttpPattern message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns CustomHttpPattern
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.api.CustomHttpPattern;
+
+            /**
+             * Decodes a CustomHttpPattern message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns CustomHttpPattern
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.api.CustomHttpPattern;
+
+            /**
+             * Verifies a CustomHttpPattern message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a CustomHttpPattern message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns CustomHttpPattern
+             */
+            public static fromObject(object: { [k: string]: any }): google.api.CustomHttpPattern;
+
+            /**
+             * Creates a plain object from a CustomHttpPattern message. Also converts values to other types if specified.
+             * @param message CustomHttpPattern
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.api.CustomHttpPattern, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this CustomHttpPattern to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** FieldBehavior enum. */
+        enum FieldBehavior {
+            FIELD_BEHAVIOR_UNSPECIFIED = 0,
+            OPTIONAL = 1,
+            REQUIRED = 2,
+            OUTPUT_ONLY = 3,
+            INPUT_ONLY = 4,
+            IMMUTABLE = 5,
+            UNORDERED_LIST = 6,
+            NON_EMPTY_DEFAULT = 7
+        }
+
+        /** Properties of a ResourceDescriptor. */
+        interface IResourceDescriptor {
+
+            /** ResourceDescriptor type */
+            type?: (string|null);
+
+            /** ResourceDescriptor pattern */
+            pattern?: (string[]|null);
+
+            /** ResourceDescriptor nameField */
+            nameField?: (string|null);
+
+            /** ResourceDescriptor history */
+            history?: (google.api.ResourceDescriptor.History|keyof typeof google.api.ResourceDescriptor.History|null);
+
+            /** ResourceDescriptor plural */
+            plural?: (string|null);
+
+            /** ResourceDescriptor singular */
+            singular?: (string|null);
+
+            /** ResourceDescriptor style */
+            style?: (google.api.ResourceDescriptor.Style[]|null);
+        }
+
+        /** Represents a ResourceDescriptor. */
+        class ResourceDescriptor implements IResourceDescriptor {
+
+            /**
+             * Constructs a new ResourceDescriptor.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.api.IResourceDescriptor);
+
+            /** ResourceDescriptor type. */
+            public type: string;
+
+            /** ResourceDescriptor pattern. */
+            public pattern: string[];
+
+            /** ResourceDescriptor nameField. */
+            public nameField: string;
+
+            /** ResourceDescriptor history. */
+            public history: (google.api.ResourceDescriptor.History|keyof typeof google.api.ResourceDescriptor.History);
+
+            /** ResourceDescriptor plural. */
+            public plural: string;
+
+            /** ResourceDescriptor singular. */
+            public singular: string;
+
+            /** ResourceDescriptor style. */
+            public style: google.api.ResourceDescriptor.Style[];
+
+            /**
+             * Creates a new ResourceDescriptor instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns ResourceDescriptor instance
+             */
+            public static create(properties?: google.api.IResourceDescriptor): google.api.ResourceDescriptor;
+
+            /**
+             * Encodes the specified ResourceDescriptor message. Does not implicitly {@link google.api.ResourceDescriptor.verify|verify} messages.
+             * @param message ResourceDescriptor message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.api.IResourceDescriptor, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified ResourceDescriptor message, length delimited. Does not implicitly {@link google.api.ResourceDescriptor.verify|verify} messages.
+             * @param message ResourceDescriptor message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.api.IResourceDescriptor, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a ResourceDescriptor message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns ResourceDescriptor
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.api.ResourceDescriptor;
+
+            /**
+             * Decodes a ResourceDescriptor message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns ResourceDescriptor
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.api.ResourceDescriptor;
+
+            /**
+             * Verifies a ResourceDescriptor message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a ResourceDescriptor message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns ResourceDescriptor
+             */
+            public static fromObject(object: { [k: string]: any }): google.api.ResourceDescriptor;
+
+            /**
+             * Creates a plain object from a ResourceDescriptor message. Also converts values to other types if specified.
+             * @param message ResourceDescriptor
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.api.ResourceDescriptor, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this ResourceDescriptor to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace ResourceDescriptor {
+
+            /** History enum. */
+            enum History {
+                HISTORY_UNSPECIFIED = 0,
+                ORIGINALLY_SINGLE_PATTERN = 1,
+                FUTURE_MULTI_PATTERN = 2
+            }
+
+            /** Style enum. */
+            enum Style {
+                STYLE_UNSPECIFIED = 0,
+                DECLARATIVE_FRIENDLY = 1
+            }
+        }
+
+        /** Properties of a ResourceReference. */
+        interface IResourceReference {
+
+            /** ResourceReference type */
+            type?: (string|null);
+
+            /** ResourceReference childType */
+            childType?: (string|null);
+        }
+
+        /** Represents a ResourceReference. */
+        class ResourceReference implements IResourceReference {
+
+            /**
+             * Constructs a new ResourceReference.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.api.IResourceReference);
+
+            /** ResourceReference type. */
+            public type: string;
+
+            /** ResourceReference childType. */
+            public childType: string;
+
+            /**
+             * Creates a new ResourceReference instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns ResourceReference instance
+             */
+            public static create(properties?: google.api.IResourceReference): google.api.ResourceReference;
+
+            /**
+             * Encodes the specified ResourceReference message. Does not implicitly {@link google.api.ResourceReference.verify|verify} messages.
+             * @param message ResourceReference message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.api.IResourceReference, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified ResourceReference message, length delimited. Does not implicitly {@link google.api.ResourceReference.verify|verify} messages.
+             * @param message ResourceReference message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.api.IResourceReference, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a ResourceReference message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns ResourceReference
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.api.ResourceReference;
+
+            /**
+             * Decodes a ResourceReference message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns ResourceReference
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.api.ResourceReference;
+
+            /**
+             * Verifies a ResourceReference message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a ResourceReference message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns ResourceReference
+             */
+            public static fromObject(object: { [k: string]: any }): google.api.ResourceReference;
+
+            /**
+             * Creates a plain object from a ResourceReference message. Also converts values to other types if specified.
+             * @param message ResourceReference
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.api.ResourceReference, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this ResourceReference to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+    }
+
+    /** Namespace protobuf. */
+    namespace protobuf {
+
+        /** Properties of a FileDescriptorSet. */
+        interface IFileDescriptorSet {
+
+            /** FileDescriptorSet file */
+            file?: (google.protobuf.IFileDescriptorProto[]|null);
+        }
+
+        /** Represents a FileDescriptorSet. */
+        class FileDescriptorSet implements IFileDescriptorSet {
+
+            /**
+             * Constructs a new FileDescriptorSet.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IFileDescriptorSet);
+
+            /** FileDescriptorSet file. */
+            public file: google.protobuf.IFileDescriptorProto[];
+
+            /**
+             * Creates a new FileDescriptorSet instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns FileDescriptorSet instance
+             */
+            public static create(properties?: google.protobuf.IFileDescriptorSet): google.protobuf.FileDescriptorSet;
+
+            /**
+             * Encodes the specified FileDescriptorSet message. Does not implicitly {@link google.protobuf.FileDescriptorSet.verify|verify} messages.
+             * @param message FileDescriptorSet message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IFileDescriptorSet, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified FileDescriptorSet message, length delimited. Does not implicitly {@link google.protobuf.FileDescriptorSet.verify|verify} messages.
+             * @param message FileDescriptorSet message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IFileDescriptorSet, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a FileDescriptorSet message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns FileDescriptorSet
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.FileDescriptorSet;
+
+            /**
+             * Decodes a FileDescriptorSet message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns FileDescriptorSet
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.FileDescriptorSet;
+
+            /**
+             * Verifies a FileDescriptorSet message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a FileDescriptorSet message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns FileDescriptorSet
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.FileDescriptorSet;
+
+            /**
+             * Creates a plain object from a FileDescriptorSet message. Also converts values to other types if specified.
+             * @param message FileDescriptorSet
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.FileDescriptorSet, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this FileDescriptorSet to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a FileDescriptorProto. */
+        interface IFileDescriptorProto {
+
+            /** FileDescriptorProto name */
+            name?: (string|null);
+
+            /** FileDescriptorProto package */
+            "package"?: (string|null);
+
+            /** FileDescriptorProto dependency */
+            dependency?: (string[]|null);
+
+            /** FileDescriptorProto publicDependency */
+            publicDependency?: (number[]|null);
+
+            /** FileDescriptorProto weakDependency */
+            weakDependency?: (number[]|null);
+
+            /** FileDescriptorProto messageType */
+            messageType?: (google.protobuf.IDescriptorProto[]|null);
+
+            /** FileDescriptorProto enumType */
+            enumType?: (google.protobuf.IEnumDescriptorProto[]|null);
+
+            /** FileDescriptorProto service */
+            service?: (google.protobuf.IServiceDescriptorProto[]|null);
+
+            /** FileDescriptorProto extension */
+            extension?: (google.protobuf.IFieldDescriptorProto[]|null);
+
+            /** FileDescriptorProto options */
+            options?: (google.protobuf.IFileOptions|null);
+
+            /** FileDescriptorProto sourceCodeInfo */
+            sourceCodeInfo?: (google.protobuf.ISourceCodeInfo|null);
+
+            /** FileDescriptorProto syntax */
+            syntax?: (string|null);
+        }
+
+        /** Represents a FileDescriptorProto. */
+        class FileDescriptorProto implements IFileDescriptorProto {
+
+            /**
+             * Constructs a new FileDescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IFileDescriptorProto);
+
+            /** FileDescriptorProto name. */
+            public name: string;
+
+            /** FileDescriptorProto package. */
+            public package: string;
+
+            /** FileDescriptorProto dependency. */
+            public dependency: string[];
+
+            /** FileDescriptorProto publicDependency. */
+            public publicDependency: number[];
+
+            /** FileDescriptorProto weakDependency. */
+            public weakDependency: number[];
+
+            /** FileDescriptorProto messageType. */
+            public messageType: google.protobuf.IDescriptorProto[];
+
+            /** FileDescriptorProto enumType. */
+            public enumType: google.protobuf.IEnumDescriptorProto[];
+
+            /** FileDescriptorProto service. */
+            public service: google.protobuf.IServiceDescriptorProto[];
+
+            /** FileDescriptorProto extension. */
+            public extension: google.protobuf.IFieldDescriptorProto[];
+
+            /** FileDescriptorProto options. */
+            public options?: (google.protobuf.IFileOptions|null);
+
+            /** FileDescriptorProto sourceCodeInfo. */
+            public sourceCodeInfo?: (google.protobuf.ISourceCodeInfo|null);
+
+            /** FileDescriptorProto syntax. */
+            public syntax: string;
+
+            /**
+             * Creates a new FileDescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns FileDescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IFileDescriptorProto): google.protobuf.FileDescriptorProto;
+
+            /**
+             * Encodes the specified FileDescriptorProto message. Does not implicitly {@link google.protobuf.FileDescriptorProto.verify|verify} messages.
+             * @param message FileDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IFileDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified FileDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.FileDescriptorProto.verify|verify} messages.
+             * @param message FileDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IFileDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a FileDescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns FileDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.FileDescriptorProto;
+
+            /**
+             * Decodes a FileDescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns FileDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.FileDescriptorProto;
+
+            /**
+             * Verifies a FileDescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a FileDescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns FileDescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.FileDescriptorProto;
+
+            /**
+             * Creates a plain object from a FileDescriptorProto message. Also converts values to other types if specified.
+             * @param message FileDescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.FileDescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this FileDescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a DescriptorProto. */
+        interface IDescriptorProto {
+
+            /** DescriptorProto name */
+            name?: (string|null);
+
+            /** DescriptorProto field */
+            field?: (google.protobuf.IFieldDescriptorProto[]|null);
+
+            /** DescriptorProto extension */
+            extension?: (google.protobuf.IFieldDescriptorProto[]|null);
+
+            /** DescriptorProto nestedType */
+            nestedType?: (google.protobuf.IDescriptorProto[]|null);
+
+            /** DescriptorProto enumType */
+            enumType?: (google.protobuf.IEnumDescriptorProto[]|null);
+
+            /** DescriptorProto extensionRange */
+            extensionRange?: (google.protobuf.DescriptorProto.IExtensionRange[]|null);
+
+            /** DescriptorProto oneofDecl */
+            oneofDecl?: (google.protobuf.IOneofDescriptorProto[]|null);
+
+            /** DescriptorProto options */
+            options?: (google.protobuf.IMessageOptions|null);
+
+            /** DescriptorProto reservedRange */
+            reservedRange?: (google.protobuf.DescriptorProto.IReservedRange[]|null);
+
+            /** DescriptorProto reservedName */
+            reservedName?: (string[]|null);
+        }
+
+        /** Represents a DescriptorProto. */
+        class DescriptorProto implements IDescriptorProto {
+
+            /**
+             * Constructs a new DescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IDescriptorProto);
+
+            /** DescriptorProto name. */
+            public name: string;
+
+            /** DescriptorProto field. */
+            public field: google.protobuf.IFieldDescriptorProto[];
+
+            /** DescriptorProto extension. */
+            public extension: google.protobuf.IFieldDescriptorProto[];
+
+            /** DescriptorProto nestedType. */
+            public nestedType: google.protobuf.IDescriptorProto[];
+
+            /** DescriptorProto enumType. */
+            public enumType: google.protobuf.IEnumDescriptorProto[];
+
+            /** DescriptorProto extensionRange. */
+            public extensionRange: google.protobuf.DescriptorProto.IExtensionRange[];
+
+            /** DescriptorProto oneofDecl. */
+            public oneofDecl: google.protobuf.IOneofDescriptorProto[];
+
+            /** DescriptorProto options. */
+            public options?: (google.protobuf.IMessageOptions|null);
+
+            /** DescriptorProto reservedRange. */
+            public reservedRange: google.protobuf.DescriptorProto.IReservedRange[];
+
+            /** DescriptorProto reservedName. */
+            public reservedName: string[];
+
+            /**
+             * Creates a new DescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns DescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IDescriptorProto): google.protobuf.DescriptorProto;
+
+            /**
+             * Encodes the specified DescriptorProto message. Does not implicitly {@link google.protobuf.DescriptorProto.verify|verify} messages.
+             * @param message DescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified DescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.DescriptorProto.verify|verify} messages.
+             * @param message DescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a DescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns DescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.DescriptorProto;
+
+            /**
+             * Decodes a DescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns DescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.DescriptorProto;
+
+            /**
+             * Verifies a DescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a DescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns DescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.DescriptorProto;
+
+            /**
+             * Creates a plain object from a DescriptorProto message. Also converts values to other types if specified.
+             * @param message DescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.DescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this DescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace DescriptorProto {
+
+            /** Properties of an ExtensionRange. */
+            interface IExtensionRange {
+
+                /** ExtensionRange start */
+                start?: (number|null);
+
+                /** ExtensionRange end */
+                end?: (number|null);
+
+                /** ExtensionRange options */
+                options?: (google.protobuf.IExtensionRangeOptions|null);
+            }
+
+            /** Represents an ExtensionRange. */
+            class ExtensionRange implements IExtensionRange {
+
+                /**
+                 * Constructs a new ExtensionRange.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.protobuf.DescriptorProto.IExtensionRange);
+
+                /** ExtensionRange start. */
+                public start: number;
+
+                /** ExtensionRange end. */
+                public end: number;
+
+                /** ExtensionRange options. */
+                public options?: (google.protobuf.IExtensionRangeOptions|null);
+
+                /**
+                 * Creates a new ExtensionRange instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns ExtensionRange instance
+                 */
+                public static create(properties?: google.protobuf.DescriptorProto.IExtensionRange): google.protobuf.DescriptorProto.ExtensionRange;
+
+                /**
+                 * Encodes the specified ExtensionRange message. Does not implicitly {@link google.protobuf.DescriptorProto.ExtensionRange.verify|verify} messages.
+                 * @param message ExtensionRange message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.protobuf.DescriptorProto.IExtensionRange, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified ExtensionRange message, length delimited. Does not implicitly {@link google.protobuf.DescriptorProto.ExtensionRange.verify|verify} messages.
+                 * @param message ExtensionRange message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.protobuf.DescriptorProto.IExtensionRange, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes an ExtensionRange message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns ExtensionRange
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.DescriptorProto.ExtensionRange;
+
+                /**
+                 * Decodes an ExtensionRange message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns ExtensionRange
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.DescriptorProto.ExtensionRange;
+
+                /**
+                 * Verifies an ExtensionRange message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates an ExtensionRange message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns ExtensionRange
+                 */
+                public static fromObject(object: { [k: string]: any }): google.protobuf.DescriptorProto.ExtensionRange;
+
+                /**
+                 * Creates a plain object from an ExtensionRange message. Also converts values to other types if specified.
+                 * @param message ExtensionRange
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.protobuf.DescriptorProto.ExtensionRange, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this ExtensionRange to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a ReservedRange. */
+            interface IReservedRange {
+
+                /** ReservedRange start */
+                start?: (number|null);
+
+                /** ReservedRange end */
+                end?: (number|null);
+            }
+
+            /** Represents a ReservedRange. */
+            class ReservedRange implements IReservedRange {
+
+                /**
+                 * Constructs a new ReservedRange.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.protobuf.DescriptorProto.IReservedRange);
+
+                /** ReservedRange start. */
+                public start: number;
+
+                /** ReservedRange end. */
+                public end: number;
+
+                /**
+                 * Creates a new ReservedRange instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns ReservedRange instance
+                 */
+                public static create(properties?: google.protobuf.DescriptorProto.IReservedRange): google.protobuf.DescriptorProto.ReservedRange;
+
+                /**
+                 * Encodes the specified ReservedRange message. Does not implicitly {@link google.protobuf.DescriptorProto.ReservedRange.verify|verify} messages.
+                 * @param message ReservedRange message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.protobuf.DescriptorProto.IReservedRange, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified ReservedRange message, length delimited. Does not implicitly {@link google.protobuf.DescriptorProto.ReservedRange.verify|verify} messages.
+                 * @param message ReservedRange message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.protobuf.DescriptorProto.IReservedRange, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a ReservedRange message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns ReservedRange
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.DescriptorProto.ReservedRange;
+
+                /**
+                 * Decodes a ReservedRange message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns ReservedRange
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.DescriptorProto.ReservedRange;
+
+                /**
+                 * Verifies a ReservedRange message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a ReservedRange message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns ReservedRange
+                 */
+                public static fromObject(object: { [k: string]: any }): google.protobuf.DescriptorProto.ReservedRange;
+
+                /**
+                 * Creates a plain object from a ReservedRange message. Also converts values to other types if specified.
+                 * @param message ReservedRange
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.protobuf.DescriptorProto.ReservedRange, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this ReservedRange to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+        }
+
+        /** Properties of an ExtensionRangeOptions. */
+        interface IExtensionRangeOptions {
+
+            /** ExtensionRangeOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+        }
+
+        /** Represents an ExtensionRangeOptions. */
+        class ExtensionRangeOptions implements IExtensionRangeOptions {
+
+            /**
+             * Constructs a new ExtensionRangeOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IExtensionRangeOptions);
+
+            /** ExtensionRangeOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new ExtensionRangeOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns ExtensionRangeOptions instance
+             */
+            public static create(properties?: google.protobuf.IExtensionRangeOptions): google.protobuf.ExtensionRangeOptions;
+
+            /**
+             * Encodes the specified ExtensionRangeOptions message. Does not implicitly {@link google.protobuf.ExtensionRangeOptions.verify|verify} messages.
+             * @param message ExtensionRangeOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IExtensionRangeOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified ExtensionRangeOptions message, length delimited. Does not implicitly {@link google.protobuf.ExtensionRangeOptions.verify|verify} messages.
+             * @param message ExtensionRangeOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IExtensionRangeOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an ExtensionRangeOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns ExtensionRangeOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.ExtensionRangeOptions;
+
+            /**
+             * Decodes an ExtensionRangeOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns ExtensionRangeOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.ExtensionRangeOptions;
+
+            /**
+             * Verifies an ExtensionRangeOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an ExtensionRangeOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns ExtensionRangeOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.ExtensionRangeOptions;
+
+            /**
+             * Creates a plain object from an ExtensionRangeOptions message. Also converts values to other types if specified.
+             * @param message ExtensionRangeOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.ExtensionRangeOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this ExtensionRangeOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a FieldDescriptorProto. */
+        interface IFieldDescriptorProto {
+
+            /** FieldDescriptorProto name */
+            name?: (string|null);
+
+            /** FieldDescriptorProto number */
+            number?: (number|null);
+
+            /** FieldDescriptorProto label */
+            label?: (google.protobuf.FieldDescriptorProto.Label|keyof typeof google.protobuf.FieldDescriptorProto.Label|null);
+
+            /** FieldDescriptorProto type */
+            type?: (google.protobuf.FieldDescriptorProto.Type|keyof typeof google.protobuf.FieldDescriptorProto.Type|null);
+
+            /** FieldDescriptorProto typeName */
+            typeName?: (string|null);
+
+            /** FieldDescriptorProto extendee */
+            extendee?: (string|null);
+
+            /** FieldDescriptorProto defaultValue */
+            defaultValue?: (string|null);
+
+            /** FieldDescriptorProto oneofIndex */
+            oneofIndex?: (number|null);
+
+            /** FieldDescriptorProto jsonName */
+            jsonName?: (string|null);
+
+            /** FieldDescriptorProto options */
+            options?: (google.protobuf.IFieldOptions|null);
+
+            /** FieldDescriptorProto proto3Optional */
+            proto3Optional?: (boolean|null);
+        }
+
+        /** Represents a FieldDescriptorProto. */
+        class FieldDescriptorProto implements IFieldDescriptorProto {
+
+            /**
+             * Constructs a new FieldDescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IFieldDescriptorProto);
+
+            /** FieldDescriptorProto name. */
+            public name: string;
+
+            /** FieldDescriptorProto number. */
+            public number: number;
+
+            /** FieldDescriptorProto label. */
+            public label: (google.protobuf.FieldDescriptorProto.Label|keyof typeof google.protobuf.FieldDescriptorProto.Label);
+
+            /** FieldDescriptorProto type. */
+            public type: (google.protobuf.FieldDescriptorProto.Type|keyof typeof google.protobuf.FieldDescriptorProto.Type);
+
+            /** FieldDescriptorProto typeName. */
+            public typeName: string;
+
+            /** FieldDescriptorProto extendee. */
+            public extendee: string;
+
+            /** FieldDescriptorProto defaultValue. */
+            public defaultValue: string;
+
+            /** FieldDescriptorProto oneofIndex. */
+            public oneofIndex: number;
+
+            /** FieldDescriptorProto jsonName. */
+            public jsonName: string;
+
+            /** FieldDescriptorProto options. */
+            public options?: (google.protobuf.IFieldOptions|null);
+
+            /** FieldDescriptorProto proto3Optional. */
+            public proto3Optional: boolean;
+
+            /**
+             * Creates a new FieldDescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns FieldDescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IFieldDescriptorProto): google.protobuf.FieldDescriptorProto;
+
+            /**
+             * Encodes the specified FieldDescriptorProto message. Does not implicitly {@link google.protobuf.FieldDescriptorProto.verify|verify} messages.
+             * @param message FieldDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IFieldDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified FieldDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.FieldDescriptorProto.verify|verify} messages.
+             * @param message FieldDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IFieldDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a FieldDescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns FieldDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.FieldDescriptorProto;
+
+            /**
+             * Decodes a FieldDescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns FieldDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.FieldDescriptorProto;
+
+            /**
+             * Verifies a FieldDescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a FieldDescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns FieldDescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.FieldDescriptorProto;
+
+            /**
+             * Creates a plain object from a FieldDescriptorProto message. Also converts values to other types if specified.
+             * @param message FieldDescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.FieldDescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this FieldDescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace FieldDescriptorProto {
+
+            /** Type enum. */
+            enum Type {
+                TYPE_DOUBLE = 1,
+                TYPE_FLOAT = 2,
+                TYPE_INT64 = 3,
+                TYPE_UINT64 = 4,
+                TYPE_INT32 = 5,
+                TYPE_FIXED64 = 6,
+                TYPE_FIXED32 = 7,
+                TYPE_BOOL = 8,
+                TYPE_STRING = 9,
+                TYPE_GROUP = 10,
+                TYPE_MESSAGE = 11,
+                TYPE_BYTES = 12,
+                TYPE_UINT32 = 13,
+                TYPE_ENUM = 14,
+                TYPE_SFIXED32 = 15,
+                TYPE_SFIXED64 = 16,
+                TYPE_SINT32 = 17,
+                TYPE_SINT64 = 18
+            }
+
+            /** Label enum. */
+            enum Label {
+                LABEL_OPTIONAL = 1,
+                LABEL_REQUIRED = 2,
+                LABEL_REPEATED = 3
+            }
+        }
+
+        /** Properties of an OneofDescriptorProto. */
+        interface IOneofDescriptorProto {
+
+            /** OneofDescriptorProto name */
+            name?: (string|null);
+
+            /** OneofDescriptorProto options */
+            options?: (google.protobuf.IOneofOptions|null);
+        }
+
+        /** Represents an OneofDescriptorProto. */
+        class OneofDescriptorProto implements IOneofDescriptorProto {
+
+            /**
+             * Constructs a new OneofDescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IOneofDescriptorProto);
+
+            /** OneofDescriptorProto name. */
+            public name: string;
+
+            /** OneofDescriptorProto options. */
+            public options?: (google.protobuf.IOneofOptions|null);
+
+            /**
+             * Creates a new OneofDescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns OneofDescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IOneofDescriptorProto): google.protobuf.OneofDescriptorProto;
+
+            /**
+             * Encodes the specified OneofDescriptorProto message. Does not implicitly {@link google.protobuf.OneofDescriptorProto.verify|verify} messages.
+             * @param message OneofDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IOneofDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified OneofDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.OneofDescriptorProto.verify|verify} messages.
+             * @param message OneofDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IOneofDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an OneofDescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns OneofDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.OneofDescriptorProto;
+
+            /**
+             * Decodes an OneofDescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns OneofDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.OneofDescriptorProto;
+
+            /**
+             * Verifies an OneofDescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an OneofDescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns OneofDescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.OneofDescriptorProto;
+
+            /**
+             * Creates a plain object from an OneofDescriptorProto message. Also converts values to other types if specified.
+             * @param message OneofDescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.OneofDescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this OneofDescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of an EnumDescriptorProto. */
+        interface IEnumDescriptorProto {
+
+            /** EnumDescriptorProto name */
+            name?: (string|null);
+
+            /** EnumDescriptorProto value */
+            value?: (google.protobuf.IEnumValueDescriptorProto[]|null);
+
+            /** EnumDescriptorProto options */
+            options?: (google.protobuf.IEnumOptions|null);
+
+            /** EnumDescriptorProto reservedRange */
+            reservedRange?: (google.protobuf.EnumDescriptorProto.IEnumReservedRange[]|null);
+
+            /** EnumDescriptorProto reservedName */
+            reservedName?: (string[]|null);
+        }
+
+        /** Represents an EnumDescriptorProto. */
+        class EnumDescriptorProto implements IEnumDescriptorProto {
+
+            /**
+             * Constructs a new EnumDescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IEnumDescriptorProto);
+
+            /** EnumDescriptorProto name. */
+            public name: string;
+
+            /** EnumDescriptorProto value. */
+            public value: google.protobuf.IEnumValueDescriptorProto[];
+
+            /** EnumDescriptorProto options. */
+            public options?: (google.protobuf.IEnumOptions|null);
+
+            /** EnumDescriptorProto reservedRange. */
+            public reservedRange: google.protobuf.EnumDescriptorProto.IEnumReservedRange[];
+
+            /** EnumDescriptorProto reservedName. */
+            public reservedName: string[];
+
+            /**
+             * Creates a new EnumDescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns EnumDescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IEnumDescriptorProto): google.protobuf.EnumDescriptorProto;
+
+            /**
+             * Encodes the specified EnumDescriptorProto message. Does not implicitly {@link google.protobuf.EnumDescriptorProto.verify|verify} messages.
+             * @param message EnumDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IEnumDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified EnumDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.EnumDescriptorProto.verify|verify} messages.
+             * @param message EnumDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IEnumDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an EnumDescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns EnumDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.EnumDescriptorProto;
+
+            /**
+             * Decodes an EnumDescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns EnumDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.EnumDescriptorProto;
+
+            /**
+             * Verifies an EnumDescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an EnumDescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns EnumDescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.EnumDescriptorProto;
+
+            /**
+             * Creates a plain object from an EnumDescriptorProto message. Also converts values to other types if specified.
+             * @param message EnumDescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.EnumDescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this EnumDescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace EnumDescriptorProto {
+
+            /** Properties of an EnumReservedRange. */
+            interface IEnumReservedRange {
+
+                /** EnumReservedRange start */
+                start?: (number|null);
+
+                /** EnumReservedRange end */
+                end?: (number|null);
+            }
+
+            /** Represents an EnumReservedRange. */
+            class EnumReservedRange implements IEnumReservedRange {
+
+                /**
+                 * Constructs a new EnumReservedRange.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.protobuf.EnumDescriptorProto.IEnumReservedRange);
+
+                /** EnumReservedRange start. */
+                public start: number;
+
+                /** EnumReservedRange end. */
+                public end: number;
+
+                /**
+                 * Creates a new EnumReservedRange instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns EnumReservedRange instance
+                 */
+                public static create(properties?: google.protobuf.EnumDescriptorProto.IEnumReservedRange): google.protobuf.EnumDescriptorProto.EnumReservedRange;
+
+                /**
+                 * Encodes the specified EnumReservedRange message. Does not implicitly {@link google.protobuf.EnumDescriptorProto.EnumReservedRange.verify|verify} messages.
+                 * @param message EnumReservedRange message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.protobuf.EnumDescriptorProto.IEnumReservedRange, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified EnumReservedRange message, length delimited. Does not implicitly {@link google.protobuf.EnumDescriptorProto.EnumReservedRange.verify|verify} messages.
+                 * @param message EnumReservedRange message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.protobuf.EnumDescriptorProto.IEnumReservedRange, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes an EnumReservedRange message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns EnumReservedRange
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.EnumDescriptorProto.EnumReservedRange;
+
+                /**
+                 * Decodes an EnumReservedRange message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns EnumReservedRange
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.EnumDescriptorProto.EnumReservedRange;
+
+                /**
+                 * Verifies an EnumReservedRange message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates an EnumReservedRange message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns EnumReservedRange
+                 */
+                public static fromObject(object: { [k: string]: any }): google.protobuf.EnumDescriptorProto.EnumReservedRange;
+
+                /**
+                 * Creates a plain object from an EnumReservedRange message. Also converts values to other types if specified.
+                 * @param message EnumReservedRange
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.protobuf.EnumDescriptorProto.EnumReservedRange, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this EnumReservedRange to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+        }
+
+        /** Properties of an EnumValueDescriptorProto. */
+        interface IEnumValueDescriptorProto {
+
+            /** EnumValueDescriptorProto name */
+            name?: (string|null);
+
+            /** EnumValueDescriptorProto number */
+            number?: (number|null);
+
+            /** EnumValueDescriptorProto options */
+            options?: (google.protobuf.IEnumValueOptions|null);
+        }
+
+        /** Represents an EnumValueDescriptorProto. */
+        class EnumValueDescriptorProto implements IEnumValueDescriptorProto {
+
+            /**
+             * Constructs a new EnumValueDescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IEnumValueDescriptorProto);
+
+            /** EnumValueDescriptorProto name. */
+            public name: string;
+
+            /** EnumValueDescriptorProto number. */
+            public number: number;
+
+            /** EnumValueDescriptorProto options. */
+            public options?: (google.protobuf.IEnumValueOptions|null);
+
+            /**
+             * Creates a new EnumValueDescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns EnumValueDescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IEnumValueDescriptorProto): google.protobuf.EnumValueDescriptorProto;
+
+            /**
+             * Encodes the specified EnumValueDescriptorProto message. Does not implicitly {@link google.protobuf.EnumValueDescriptorProto.verify|verify} messages.
+             * @param message EnumValueDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IEnumValueDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified EnumValueDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.EnumValueDescriptorProto.verify|verify} messages.
+             * @param message EnumValueDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IEnumValueDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an EnumValueDescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns EnumValueDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.EnumValueDescriptorProto;
+
+            /**
+             * Decodes an EnumValueDescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns EnumValueDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.EnumValueDescriptorProto;
+
+            /**
+             * Verifies an EnumValueDescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an EnumValueDescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns EnumValueDescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.EnumValueDescriptorProto;
+
+            /**
+             * Creates a plain object from an EnumValueDescriptorProto message. Also converts values to other types if specified.
+             * @param message EnumValueDescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.EnumValueDescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this EnumValueDescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a ServiceDescriptorProto. */
+        interface IServiceDescriptorProto {
+
+            /** ServiceDescriptorProto name */
+            name?: (string|null);
+
+            /** ServiceDescriptorProto method */
+            method?: (google.protobuf.IMethodDescriptorProto[]|null);
+
+            /** ServiceDescriptorProto options */
+            options?: (google.protobuf.IServiceOptions|null);
+        }
+
+        /** Represents a ServiceDescriptorProto. */
+        class ServiceDescriptorProto implements IServiceDescriptorProto {
+
+            /**
+             * Constructs a new ServiceDescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IServiceDescriptorProto);
+
+            /** ServiceDescriptorProto name. */
+            public name: string;
+
+            /** ServiceDescriptorProto method. */
+            public method: google.protobuf.IMethodDescriptorProto[];
+
+            /** ServiceDescriptorProto options. */
+            public options?: (google.protobuf.IServiceOptions|null);
+
+            /**
+             * Creates a new ServiceDescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns ServiceDescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IServiceDescriptorProto): google.protobuf.ServiceDescriptorProto;
+
+            /**
+             * Encodes the specified ServiceDescriptorProto message. Does not implicitly {@link google.protobuf.ServiceDescriptorProto.verify|verify} messages.
+             * @param message ServiceDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IServiceDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified ServiceDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.ServiceDescriptorProto.verify|verify} messages.
+             * @param message ServiceDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IServiceDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a ServiceDescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns ServiceDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.ServiceDescriptorProto;
+
+            /**
+             * Decodes a ServiceDescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns ServiceDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.ServiceDescriptorProto;
+
+            /**
+             * Verifies a ServiceDescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a ServiceDescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns ServiceDescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.ServiceDescriptorProto;
+
+            /**
+             * Creates a plain object from a ServiceDescriptorProto message. Also converts values to other types if specified.
+             * @param message ServiceDescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.ServiceDescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this ServiceDescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a MethodDescriptorProto. */
+        interface IMethodDescriptorProto {
+
+            /** MethodDescriptorProto name */
+            name?: (string|null);
+
+            /** MethodDescriptorProto inputType */
+            inputType?: (string|null);
+
+            /** MethodDescriptorProto outputType */
+            outputType?: (string|null);
+
+            /** MethodDescriptorProto options */
+            options?: (google.protobuf.IMethodOptions|null);
+
+            /** MethodDescriptorProto clientStreaming */
+            clientStreaming?: (boolean|null);
+
+            /** MethodDescriptorProto serverStreaming */
+            serverStreaming?: (boolean|null);
+        }
+
+        /** Represents a MethodDescriptorProto. */
+        class MethodDescriptorProto implements IMethodDescriptorProto {
+
+            /**
+             * Constructs a new MethodDescriptorProto.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IMethodDescriptorProto);
+
+            /** MethodDescriptorProto name. */
+            public name: string;
+
+            /** MethodDescriptorProto inputType. */
+            public inputType: string;
+
+            /** MethodDescriptorProto outputType. */
+            public outputType: string;
+
+            /** MethodDescriptorProto options. */
+            public options?: (google.protobuf.IMethodOptions|null);
+
+            /** MethodDescriptorProto clientStreaming. */
+            public clientStreaming: boolean;
+
+            /** MethodDescriptorProto serverStreaming. */
+            public serverStreaming: boolean;
+
+            /**
+             * Creates a new MethodDescriptorProto instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns MethodDescriptorProto instance
+             */
+            public static create(properties?: google.protobuf.IMethodDescriptorProto): google.protobuf.MethodDescriptorProto;
+
+            /**
+             * Encodes the specified MethodDescriptorProto message. Does not implicitly {@link google.protobuf.MethodDescriptorProto.verify|verify} messages.
+             * @param message MethodDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IMethodDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified MethodDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.MethodDescriptorProto.verify|verify} messages.
+             * @param message MethodDescriptorProto message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IMethodDescriptorProto, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a MethodDescriptorProto message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns MethodDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.MethodDescriptorProto;
+
+            /**
+             * Decodes a MethodDescriptorProto message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns MethodDescriptorProto
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.MethodDescriptorProto;
+
+            /**
+             * Verifies a MethodDescriptorProto message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a MethodDescriptorProto message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns MethodDescriptorProto
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.MethodDescriptorProto;
+
+            /**
+             * Creates a plain object from a MethodDescriptorProto message. Also converts values to other types if specified.
+             * @param message MethodDescriptorProto
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.MethodDescriptorProto, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this MethodDescriptorProto to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a FileOptions. */
+        interface IFileOptions {
+
+            /** FileOptions javaPackage */
+            javaPackage?: (string|null);
+
+            /** FileOptions javaOuterClassname */
+            javaOuterClassname?: (string|null);
+
+            /** FileOptions javaMultipleFiles */
+            javaMultipleFiles?: (boolean|null);
+
+            /** FileOptions javaGenerateEqualsAndHash */
+            javaGenerateEqualsAndHash?: (boolean|null);
+
+            /** FileOptions javaStringCheckUtf8 */
+            javaStringCheckUtf8?: (boolean|null);
+
+            /** FileOptions optimizeFor */
+            optimizeFor?: (google.protobuf.FileOptions.OptimizeMode|keyof typeof google.protobuf.FileOptions.OptimizeMode|null);
+
+            /** FileOptions goPackage */
+            goPackage?: (string|null);
+
+            /** FileOptions ccGenericServices */
+            ccGenericServices?: (boolean|null);
+
+            /** FileOptions javaGenericServices */
+            javaGenericServices?: (boolean|null);
+
+            /** FileOptions pyGenericServices */
+            pyGenericServices?: (boolean|null);
+
+            /** FileOptions phpGenericServices */
+            phpGenericServices?: (boolean|null);
+
+            /** FileOptions deprecated */
+            deprecated?: (boolean|null);
+
+            /** FileOptions ccEnableArenas */
+            ccEnableArenas?: (boolean|null);
+
+            /** FileOptions objcClassPrefix */
+            objcClassPrefix?: (string|null);
+
+            /** FileOptions csharpNamespace */
+            csharpNamespace?: (string|null);
+
+            /** FileOptions swiftPrefix */
+            swiftPrefix?: (string|null);
+
+            /** FileOptions phpClassPrefix */
+            phpClassPrefix?: (string|null);
+
+            /** FileOptions phpNamespace */
+            phpNamespace?: (string|null);
+
+            /** FileOptions phpMetadataNamespace */
+            phpMetadataNamespace?: (string|null);
+
+            /** FileOptions rubyPackage */
+            rubyPackage?: (string|null);
+
+            /** FileOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+
+            /** FileOptions .google.api.resourceDefinition */
+            ".google.api.resourceDefinition"?: (google.api.IResourceDescriptor[]|null);
+        }
+
+        /** Represents a FileOptions. */
+        class FileOptions implements IFileOptions {
+
+            /**
+             * Constructs a new FileOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IFileOptions);
+
+            /** FileOptions javaPackage. */
+            public javaPackage: string;
+
+            /** FileOptions javaOuterClassname. */
+            public javaOuterClassname: string;
+
+            /** FileOptions javaMultipleFiles. */
+            public javaMultipleFiles: boolean;
+
+            /** FileOptions javaGenerateEqualsAndHash. */
+            public javaGenerateEqualsAndHash: boolean;
+
+            /** FileOptions javaStringCheckUtf8. */
+            public javaStringCheckUtf8: boolean;
+
+            /** FileOptions optimizeFor. */
+            public optimizeFor: (google.protobuf.FileOptions.OptimizeMode|keyof typeof google.protobuf.FileOptions.OptimizeMode);
+
+            /** FileOptions goPackage. */
+            public goPackage: string;
+
+            /** FileOptions ccGenericServices. */
+            public ccGenericServices: boolean;
+
+            /** FileOptions javaGenericServices. */
+            public javaGenericServices: boolean;
+
+            /** FileOptions pyGenericServices. */
+            public pyGenericServices: boolean;
+
+            /** FileOptions phpGenericServices. */
+            public phpGenericServices: boolean;
+
+            /** FileOptions deprecated. */
+            public deprecated: boolean;
+
+            /** FileOptions ccEnableArenas. */
+            public ccEnableArenas: boolean;
+
+            /** FileOptions objcClassPrefix. */
+            public objcClassPrefix: string;
+
+            /** FileOptions csharpNamespace. */
+            public csharpNamespace: string;
+
+            /** FileOptions swiftPrefix. */
+            public swiftPrefix: string;
+
+            /** FileOptions phpClassPrefix. */
+            public phpClassPrefix: string;
+
+            /** FileOptions phpNamespace. */
+            public phpNamespace: string;
+
+            /** FileOptions phpMetadataNamespace. */
+            public phpMetadataNamespace: string;
+
+            /** FileOptions rubyPackage. */
+            public rubyPackage: string;
+
+            /** FileOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new FileOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns FileOptions instance
+             */
+            public static create(properties?: google.protobuf.IFileOptions): google.protobuf.FileOptions;
+
+            /**
+             * Encodes the specified FileOptions message. Does not implicitly {@link google.protobuf.FileOptions.verify|verify} messages.
+             * @param message FileOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IFileOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified FileOptions message, length delimited. Does not implicitly {@link google.protobuf.FileOptions.verify|verify} messages.
+             * @param message FileOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IFileOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a FileOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns FileOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.FileOptions;
+
+            /**
+             * Decodes a FileOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns FileOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.FileOptions;
+
+            /**
+             * Verifies a FileOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a FileOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns FileOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.FileOptions;
+
+            /**
+             * Creates a plain object from a FileOptions message. Also converts values to other types if specified.
+             * @param message FileOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.FileOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this FileOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace FileOptions {
+
+            /** OptimizeMode enum. */
+            enum OptimizeMode {
+                SPEED = 1,
+                CODE_SIZE = 2,
+                LITE_RUNTIME = 3
+            }
+        }
+
+        /** Properties of a MessageOptions. */
+        interface IMessageOptions {
+
+            /** MessageOptions messageSetWireFormat */
+            messageSetWireFormat?: (boolean|null);
+
+            /** MessageOptions noStandardDescriptorAccessor */
+            noStandardDescriptorAccessor?: (boolean|null);
+
+            /** MessageOptions deprecated */
+            deprecated?: (boolean|null);
+
+            /** MessageOptions mapEntry */
+            mapEntry?: (boolean|null);
+
+            /** MessageOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+
+            /** MessageOptions .google.api.resource */
+            ".google.api.resource"?: (google.api.IResourceDescriptor|null);
+        }
+
+        /** Represents a MessageOptions. */
+        class MessageOptions implements IMessageOptions {
+
+            /**
+             * Constructs a new MessageOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IMessageOptions);
+
+            /** MessageOptions messageSetWireFormat. */
+            public messageSetWireFormat: boolean;
+
+            /** MessageOptions noStandardDescriptorAccessor. */
+            public noStandardDescriptorAccessor: boolean;
+
+            /** MessageOptions deprecated. */
+            public deprecated: boolean;
+
+            /** MessageOptions mapEntry. */
+            public mapEntry: boolean;
+
+            /** MessageOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new MessageOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns MessageOptions instance
+             */
+            public static create(properties?: google.protobuf.IMessageOptions): google.protobuf.MessageOptions;
+
+            /**
+             * Encodes the specified MessageOptions message. Does not implicitly {@link google.protobuf.MessageOptions.verify|verify} messages.
+             * @param message MessageOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IMessageOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified MessageOptions message, length delimited. Does not implicitly {@link google.protobuf.MessageOptions.verify|verify} messages.
+             * @param message MessageOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IMessageOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a MessageOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns MessageOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.MessageOptions;
+
+            /**
+             * Decodes a MessageOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns MessageOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.MessageOptions;
+
+            /**
+             * Verifies a MessageOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a MessageOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns MessageOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.MessageOptions;
+
+            /**
+             * Creates a plain object from a MessageOptions message. Also converts values to other types if specified.
+             * @param message MessageOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.MessageOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this MessageOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a FieldOptions. */
+        interface IFieldOptions {
+
+            /** FieldOptions ctype */
+            ctype?: (google.protobuf.FieldOptions.CType|keyof typeof google.protobuf.FieldOptions.CType|null);
+
+            /** FieldOptions packed */
+            packed?: (boolean|null);
+
+            /** FieldOptions jstype */
+            jstype?: (google.protobuf.FieldOptions.JSType|keyof typeof google.protobuf.FieldOptions.JSType|null);
+
+            /** FieldOptions lazy */
+            lazy?: (boolean|null);
+
+            /** FieldOptions deprecated */
+            deprecated?: (boolean|null);
+
+            /** FieldOptions weak */
+            weak?: (boolean|null);
+
+            /** FieldOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+
+            /** FieldOptions .google.api.fieldBehavior */
+            ".google.api.fieldBehavior"?: (google.api.FieldBehavior[]|null);
+
+            /** FieldOptions .google.api.resourceReference */
+            ".google.api.resourceReference"?: (google.api.IResourceReference|null);
+        }
+
+        /** Represents a FieldOptions. */
+        class FieldOptions implements IFieldOptions {
+
+            /**
+             * Constructs a new FieldOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IFieldOptions);
+
+            /** FieldOptions ctype. */
+            public ctype: (google.protobuf.FieldOptions.CType|keyof typeof google.protobuf.FieldOptions.CType);
+
+            /** FieldOptions packed. */
+            public packed: boolean;
+
+            /** FieldOptions jstype. */
+            public jstype: (google.protobuf.FieldOptions.JSType|keyof typeof google.protobuf.FieldOptions.JSType);
+
+            /** FieldOptions lazy. */
+            public lazy: boolean;
+
+            /** FieldOptions deprecated. */
+            public deprecated: boolean;
+
+            /** FieldOptions weak. */
+            public weak: boolean;
+
+            /** FieldOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new FieldOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns FieldOptions instance
+             */
+            public static create(properties?: google.protobuf.IFieldOptions): google.protobuf.FieldOptions;
+
+            /**
+             * Encodes the specified FieldOptions message. Does not implicitly {@link google.protobuf.FieldOptions.verify|verify} messages.
+             * @param message FieldOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IFieldOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified FieldOptions message, length delimited. Does not implicitly {@link google.protobuf.FieldOptions.verify|verify} messages.
+             * @param message FieldOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IFieldOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a FieldOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns FieldOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.FieldOptions;
+
+            /**
+             * Decodes a FieldOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns FieldOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.FieldOptions;
+
+            /**
+             * Verifies a FieldOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a FieldOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns FieldOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.FieldOptions;
+
+            /**
+             * Creates a plain object from a FieldOptions message. Also converts values to other types if specified.
+             * @param message FieldOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.FieldOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this FieldOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace FieldOptions {
+
+            /** CType enum. */
+            enum CType {
+                STRING = 0,
+                CORD = 1,
+                STRING_PIECE = 2
+            }
+
+            /** JSType enum. */
+            enum JSType {
+                JS_NORMAL = 0,
+                JS_STRING = 1,
+                JS_NUMBER = 2
+            }
+        }
+
+        /** Properties of an OneofOptions. */
+        interface IOneofOptions {
+
+            /** OneofOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+        }
+
+        /** Represents an OneofOptions. */
+        class OneofOptions implements IOneofOptions {
+
+            /**
+             * Constructs a new OneofOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IOneofOptions);
+
+            /** OneofOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new OneofOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns OneofOptions instance
+             */
+            public static create(properties?: google.protobuf.IOneofOptions): google.protobuf.OneofOptions;
+
+            /**
+             * Encodes the specified OneofOptions message. Does not implicitly {@link google.protobuf.OneofOptions.verify|verify} messages.
+             * @param message OneofOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IOneofOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified OneofOptions message, length delimited. Does not implicitly {@link google.protobuf.OneofOptions.verify|verify} messages.
+             * @param message OneofOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IOneofOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an OneofOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns OneofOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.OneofOptions;
+
+            /**
+             * Decodes an OneofOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns OneofOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.OneofOptions;
+
+            /**
+             * Verifies an OneofOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an OneofOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns OneofOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.OneofOptions;
+
+            /**
+             * Creates a plain object from an OneofOptions message. Also converts values to other types if specified.
+             * @param message OneofOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.OneofOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this OneofOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of an EnumOptions. */
+        interface IEnumOptions {
+
+            /** EnumOptions allowAlias */
+            allowAlias?: (boolean|null);
+
+            /** EnumOptions deprecated */
+            deprecated?: (boolean|null);
+
+            /** EnumOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+        }
+
+        /** Represents an EnumOptions. */
+        class EnumOptions implements IEnumOptions {
+
+            /**
+             * Constructs a new EnumOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IEnumOptions);
+
+            /** EnumOptions allowAlias. */
+            public allowAlias: boolean;
+
+            /** EnumOptions deprecated. */
+            public deprecated: boolean;
+
+            /** EnumOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new EnumOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns EnumOptions instance
+             */
+            public static create(properties?: google.protobuf.IEnumOptions): google.protobuf.EnumOptions;
+
+            /**
+             * Encodes the specified EnumOptions message. Does not implicitly {@link google.protobuf.EnumOptions.verify|verify} messages.
+             * @param message EnumOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IEnumOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified EnumOptions message, length delimited. Does not implicitly {@link google.protobuf.EnumOptions.verify|verify} messages.
+             * @param message EnumOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IEnumOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an EnumOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns EnumOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.EnumOptions;
+
+            /**
+             * Decodes an EnumOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns EnumOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.EnumOptions;
+
+            /**
+             * Verifies an EnumOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an EnumOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns EnumOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.EnumOptions;
+
+            /**
+             * Creates a plain object from an EnumOptions message. Also converts values to other types if specified.
+             * @param message EnumOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.EnumOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this EnumOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of an EnumValueOptions. */
+        interface IEnumValueOptions {
+
+            /** EnumValueOptions deprecated */
+            deprecated?: (boolean|null);
+
+            /** EnumValueOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+        }
+
+        /** Represents an EnumValueOptions. */
+        class EnumValueOptions implements IEnumValueOptions {
+
+            /**
+             * Constructs a new EnumValueOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IEnumValueOptions);
+
+            /** EnumValueOptions deprecated. */
+            public deprecated: boolean;
+
+            /** EnumValueOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new EnumValueOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns EnumValueOptions instance
+             */
+            public static create(properties?: google.protobuf.IEnumValueOptions): google.protobuf.EnumValueOptions;
+
+            /**
+             * Encodes the specified EnumValueOptions message. Does not implicitly {@link google.protobuf.EnumValueOptions.verify|verify} messages.
+             * @param message EnumValueOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IEnumValueOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified EnumValueOptions message, length delimited. Does not implicitly {@link google.protobuf.EnumValueOptions.verify|verify} messages.
+             * @param message EnumValueOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IEnumValueOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an EnumValueOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns EnumValueOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.EnumValueOptions;
+
+            /**
+             * Decodes an EnumValueOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns EnumValueOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.EnumValueOptions;
+
+            /**
+             * Verifies an EnumValueOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an EnumValueOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns EnumValueOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.EnumValueOptions;
+
+            /**
+             * Creates a plain object from an EnumValueOptions message. Also converts values to other types if specified.
+             * @param message EnumValueOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.EnumValueOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this EnumValueOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a ServiceOptions. */
+        interface IServiceOptions {
+
+            /** ServiceOptions deprecated */
+            deprecated?: (boolean|null);
+
+            /** ServiceOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+
+            /** ServiceOptions .google.api.defaultHost */
+            ".google.api.defaultHost"?: (string|null);
+
+            /** ServiceOptions .google.api.oauthScopes */
+            ".google.api.oauthScopes"?: (string|null);
+        }
+
+        /** Represents a ServiceOptions. */
+        class ServiceOptions implements IServiceOptions {
+
+            /**
+             * Constructs a new ServiceOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IServiceOptions);
+
+            /** ServiceOptions deprecated. */
+            public deprecated: boolean;
+
+            /** ServiceOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new ServiceOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns ServiceOptions instance
+             */
+            public static create(properties?: google.protobuf.IServiceOptions): google.protobuf.ServiceOptions;
+
+            /**
+             * Encodes the specified ServiceOptions message. Does not implicitly {@link google.protobuf.ServiceOptions.verify|verify} messages.
+             * @param message ServiceOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IServiceOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified ServiceOptions message, length delimited. Does not implicitly {@link google.protobuf.ServiceOptions.verify|verify} messages.
+             * @param message ServiceOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IServiceOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a ServiceOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns ServiceOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.ServiceOptions;
+
+            /**
+             * Decodes a ServiceOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns ServiceOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.ServiceOptions;
+
+            /**
+             * Verifies a ServiceOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a ServiceOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns ServiceOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.ServiceOptions;
+
+            /**
+             * Creates a plain object from a ServiceOptions message. Also converts values to other types if specified.
+             * @param message ServiceOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.ServiceOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this ServiceOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a MethodOptions. */
+        interface IMethodOptions {
+
+            /** MethodOptions deprecated */
+            deprecated?: (boolean|null);
+
+            /** MethodOptions idempotencyLevel */
+            idempotencyLevel?: (google.protobuf.MethodOptions.IdempotencyLevel|keyof typeof google.protobuf.MethodOptions.IdempotencyLevel|null);
+
+            /** MethodOptions uninterpretedOption */
+            uninterpretedOption?: (google.protobuf.IUninterpretedOption[]|null);
+
+            /** MethodOptions .google.api.http */
+            ".google.api.http"?: (google.api.IHttpRule|null);
+
+            /** MethodOptions .google.api.methodSignature */
+            ".google.api.methodSignature"?: (string[]|null);
+        }
+
+        /** Represents a MethodOptions. */
+        class MethodOptions implements IMethodOptions {
+
+            /**
+             * Constructs a new MethodOptions.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IMethodOptions);
+
+            /** MethodOptions deprecated. */
+            public deprecated: boolean;
+
+            /** MethodOptions idempotencyLevel. */
+            public idempotencyLevel: (google.protobuf.MethodOptions.IdempotencyLevel|keyof typeof google.protobuf.MethodOptions.IdempotencyLevel);
+
+            /** MethodOptions uninterpretedOption. */
+            public uninterpretedOption: google.protobuf.IUninterpretedOption[];
+
+            /**
+             * Creates a new MethodOptions instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns MethodOptions instance
+             */
+            public static create(properties?: google.protobuf.IMethodOptions): google.protobuf.MethodOptions;
+
+            /**
+             * Encodes the specified MethodOptions message. Does not implicitly {@link google.protobuf.MethodOptions.verify|verify} messages.
+             * @param message MethodOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IMethodOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified MethodOptions message, length delimited. Does not implicitly {@link google.protobuf.MethodOptions.verify|verify} messages.
+             * @param message MethodOptions message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IMethodOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a MethodOptions message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns MethodOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.MethodOptions;
+
+            /**
+             * Decodes a MethodOptions message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns MethodOptions
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.MethodOptions;
+
+            /**
+             * Verifies a MethodOptions message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a MethodOptions message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns MethodOptions
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.MethodOptions;
+
+            /**
+             * Creates a plain object from a MethodOptions message. Also converts values to other types if specified.
+             * @param message MethodOptions
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.MethodOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this MethodOptions to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace MethodOptions {
+
+            /** IdempotencyLevel enum. */
+            enum IdempotencyLevel {
+                IDEMPOTENCY_UNKNOWN = 0,
+                NO_SIDE_EFFECTS = 1,
+                IDEMPOTENT = 2
+            }
+        }
+
+        /** Properties of an UninterpretedOption. */
+        interface IUninterpretedOption {
+
+            /** UninterpretedOption name */
+            name?: (google.protobuf.UninterpretedOption.INamePart[]|null);
+
+            /** UninterpretedOption identifierValue */
+            identifierValue?: (string|null);
+
+            /** UninterpretedOption positiveIntValue */
+            positiveIntValue?: (number|Long|string|null);
+
+            /** UninterpretedOption negativeIntValue */
+            negativeIntValue?: (number|Long|string|null);
+
+            /** UninterpretedOption doubleValue */
+            doubleValue?: (number|null);
+
+            /** UninterpretedOption stringValue */
+            stringValue?: (Uint8Array|string|null);
+
+            /** UninterpretedOption aggregateValue */
+            aggregateValue?: (string|null);
+        }
+
+        /** Represents an UninterpretedOption. */
+        class UninterpretedOption implements IUninterpretedOption {
+
+            /**
+             * Constructs a new UninterpretedOption.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IUninterpretedOption);
+
+            /** UninterpretedOption name. */
+            public name: google.protobuf.UninterpretedOption.INamePart[];
+
+            /** UninterpretedOption identifierValue. */
+            public identifierValue: string;
+
+            /** UninterpretedOption positiveIntValue. */
+            public positiveIntValue: (number|Long|string);
+
+            /** UninterpretedOption negativeIntValue. */
+            public negativeIntValue: (number|Long|string);
+
+            /** UninterpretedOption doubleValue. */
+            public doubleValue: number;
+
+            /** UninterpretedOption stringValue. */
+            public stringValue: (Uint8Array|string);
+
+            /** UninterpretedOption aggregateValue. */
+            public aggregateValue: string;
+
+            /**
+             * Creates a new UninterpretedOption instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns UninterpretedOption instance
+             */
+            public static create(properties?: google.protobuf.IUninterpretedOption): google.protobuf.UninterpretedOption;
+
+            /**
+             * Encodes the specified UninterpretedOption message. Does not implicitly {@link google.protobuf.UninterpretedOption.verify|verify} messages.
+             * @param message UninterpretedOption message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IUninterpretedOption, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified UninterpretedOption message, length delimited. Does not implicitly {@link google.protobuf.UninterpretedOption.verify|verify} messages.
+             * @param message UninterpretedOption message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IUninterpretedOption, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an UninterpretedOption message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns UninterpretedOption
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.UninterpretedOption;
+
+            /**
+             * Decodes an UninterpretedOption message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns UninterpretedOption
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.UninterpretedOption;
+
+            /**
+             * Verifies an UninterpretedOption message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an UninterpretedOption message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns UninterpretedOption
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.UninterpretedOption;
+
+            /**
+             * Creates a plain object from an UninterpretedOption message. Also converts values to other types if specified.
+             * @param message UninterpretedOption
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.UninterpretedOption, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this UninterpretedOption to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace UninterpretedOption {
+
+            /** Properties of a NamePart. */
+            interface INamePart {
+
+                /** NamePart namePart */
+                namePart: string;
+
+                /** NamePart isExtension */
+                isExtension: boolean;
+            }
+
+            /** Represents a NamePart. */
+            class NamePart implements INamePart {
+
+                /**
+                 * Constructs a new NamePart.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.protobuf.UninterpretedOption.INamePart);
+
+                /** NamePart namePart. */
+                public namePart: string;
+
+                /** NamePart isExtension. */
+                public isExtension: boolean;
+
+                /**
+                 * Creates a new NamePart instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns NamePart instance
+                 */
+                public static create(properties?: google.protobuf.UninterpretedOption.INamePart): google.protobuf.UninterpretedOption.NamePart;
+
+                /**
+                 * Encodes the specified NamePart message. Does not implicitly {@link google.protobuf.UninterpretedOption.NamePart.verify|verify} messages.
+                 * @param message NamePart message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.protobuf.UninterpretedOption.INamePart, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified NamePart message, length delimited. Does not implicitly {@link google.protobuf.UninterpretedOption.NamePart.verify|verify} messages.
+                 * @param message NamePart message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.protobuf.UninterpretedOption.INamePart, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a NamePart message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns NamePart
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.UninterpretedOption.NamePart;
+
+                /**
+                 * Decodes a NamePart message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns NamePart
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.UninterpretedOption.NamePart;
+
+                /**
+                 * Verifies a NamePart message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a NamePart message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns NamePart
+                 */
+                public static fromObject(object: { [k: string]: any }): google.protobuf.UninterpretedOption.NamePart;
+
+                /**
+                 * Creates a plain object from a NamePart message. Also converts values to other types if specified.
+                 * @param message NamePart
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.protobuf.UninterpretedOption.NamePart, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this NamePart to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+        }
+
+        /** Properties of a SourceCodeInfo. */
+        interface ISourceCodeInfo {
+
+            /** SourceCodeInfo location */
+            location?: (google.protobuf.SourceCodeInfo.ILocation[]|null);
+        }
+
+        /** Represents a SourceCodeInfo. */
+        class SourceCodeInfo implements ISourceCodeInfo {
+
+            /**
+             * Constructs a new SourceCodeInfo.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.ISourceCodeInfo);
+
+            /** SourceCodeInfo location. */
+            public location: google.protobuf.SourceCodeInfo.ILocation[];
+
+            /**
+             * Creates a new SourceCodeInfo instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns SourceCodeInfo instance
+             */
+            public static create(properties?: google.protobuf.ISourceCodeInfo): google.protobuf.SourceCodeInfo;
+
+            /**
+             * Encodes the specified SourceCodeInfo message. Does not implicitly {@link google.protobuf.SourceCodeInfo.verify|verify} messages.
+             * @param message SourceCodeInfo message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.ISourceCodeInfo, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified SourceCodeInfo message, length delimited. Does not implicitly {@link google.protobuf.SourceCodeInfo.verify|verify} messages.
+             * @param message SourceCodeInfo message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.ISourceCodeInfo, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a SourceCodeInfo message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns SourceCodeInfo
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.SourceCodeInfo;
+
+            /**
+             * Decodes a SourceCodeInfo message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns SourceCodeInfo
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.SourceCodeInfo;
+
+            /**
+             * Verifies a SourceCodeInfo message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a SourceCodeInfo message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns SourceCodeInfo
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.SourceCodeInfo;
+
+            /**
+             * Creates a plain object from a SourceCodeInfo message. Also converts values to other types if specified.
+             * @param message SourceCodeInfo
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.SourceCodeInfo, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this SourceCodeInfo to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace SourceCodeInfo {
+
+            /** Properties of a Location. */
+            interface ILocation {
+
+                /** Location path */
+                path?: (number[]|null);
+
+                /** Location span */
+                span?: (number[]|null);
+
+                /** Location leadingComments */
+                leadingComments?: (string|null);
+
+                /** Location trailingComments */
+                trailingComments?: (string|null);
+
+                /** Location leadingDetachedComments */
+                leadingDetachedComments?: (string[]|null);
+            }
+
+            /** Represents a Location. */
+            class Location implements ILocation {
+
+                /**
+                 * Constructs a new Location.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.protobuf.SourceCodeInfo.ILocation);
+
+                /** Location path. */
+                public path: number[];
+
+                /** Location span. */
+                public span: number[];
+
+                /** Location leadingComments. */
+                public leadingComments: string;
+
+                /** Location trailingComments. */
+                public trailingComments: string;
+
+                /** Location leadingDetachedComments. */
+                public leadingDetachedComments: string[];
+
+                /**
+                 * Creates a new Location instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns Location instance
+                 */
+                public static create(properties?: google.protobuf.SourceCodeInfo.ILocation): google.protobuf.SourceCodeInfo.Location;
+
+                /**
+                 * Encodes the specified Location message. Does not implicitly {@link google.protobuf.SourceCodeInfo.Location.verify|verify} messages.
+                 * @param message Location message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.protobuf.SourceCodeInfo.ILocation, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified Location message, length delimited. Does not implicitly {@link google.protobuf.SourceCodeInfo.Location.verify|verify} messages.
+                 * @param message Location message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.protobuf.SourceCodeInfo.ILocation, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a Location message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns Location
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.SourceCodeInfo.Location;
+
+                /**
+                 * Decodes a Location message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns Location
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.SourceCodeInfo.Location;
+
+                /**
+                 * Verifies a Location message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a Location message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns Location
+                 */
+                public static fromObject(object: { [k: string]: any }): google.protobuf.SourceCodeInfo.Location;
+
+                /**
+                 * Creates a plain object from a Location message. Also converts values to other types if specified.
+                 * @param message Location
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.protobuf.SourceCodeInfo.Location, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this Location to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+        }
+
+        /** Properties of a GeneratedCodeInfo. */
+        interface IGeneratedCodeInfo {
+
+            /** GeneratedCodeInfo annotation */
+            annotation?: (google.protobuf.GeneratedCodeInfo.IAnnotation[]|null);
+        }
+
+        /** Represents a GeneratedCodeInfo. */
+        class GeneratedCodeInfo implements IGeneratedCodeInfo {
+
+            /**
+             * Constructs a new GeneratedCodeInfo.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IGeneratedCodeInfo);
+
+            /** GeneratedCodeInfo annotation. */
+            public annotation: google.protobuf.GeneratedCodeInfo.IAnnotation[];
+
+            /**
+             * Creates a new GeneratedCodeInfo instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns GeneratedCodeInfo instance
+             */
+            public static create(properties?: google.protobuf.IGeneratedCodeInfo): google.protobuf.GeneratedCodeInfo;
+
+            /**
+             * Encodes the specified GeneratedCodeInfo message. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.verify|verify} messages.
+             * @param message GeneratedCodeInfo message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IGeneratedCodeInfo, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified GeneratedCodeInfo message, length delimited. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.verify|verify} messages.
+             * @param message GeneratedCodeInfo message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IGeneratedCodeInfo, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a GeneratedCodeInfo message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns GeneratedCodeInfo
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.GeneratedCodeInfo;
+
+            /**
+             * Decodes a GeneratedCodeInfo message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns GeneratedCodeInfo
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.GeneratedCodeInfo;
+
+            /**
+             * Verifies a GeneratedCodeInfo message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a GeneratedCodeInfo message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns GeneratedCodeInfo
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.GeneratedCodeInfo;
+
+            /**
+             * Creates a plain object from a GeneratedCodeInfo message. Also converts values to other types if specified.
+             * @param message GeneratedCodeInfo
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.GeneratedCodeInfo, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this GeneratedCodeInfo to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        namespace GeneratedCodeInfo {
+
+            /** Properties of an Annotation. */
+            interface IAnnotation {
+
+                /** Annotation path */
+                path?: (number[]|null);
+
+                /** Annotation sourceFile */
+                sourceFile?: (string|null);
+
+                /** Annotation begin */
+                begin?: (number|null);
+
+                /** Annotation end */
+                end?: (number|null);
+            }
+
+            /** Represents an Annotation. */
+            class Annotation implements IAnnotation {
+
+                /**
+                 * Constructs a new Annotation.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.protobuf.GeneratedCodeInfo.IAnnotation);
+
+                /** Annotation path. */
+                public path: number[];
+
+                /** Annotation sourceFile. */
+                public sourceFile: string;
+
+                /** Annotation begin. */
+                public begin: number;
+
+                /** Annotation end. */
+                public end: number;
+
+                /**
+                 * Creates a new Annotation instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns Annotation instance
+                 */
+                public static create(properties?: google.protobuf.GeneratedCodeInfo.IAnnotation): google.protobuf.GeneratedCodeInfo.Annotation;
+
+                /**
+                 * Encodes the specified Annotation message. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.Annotation.verify|verify} messages.
+                 * @param message Annotation message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.protobuf.GeneratedCodeInfo.IAnnotation, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified Annotation message, length delimited. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.Annotation.verify|verify} messages.
+                 * @param message Annotation message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.protobuf.GeneratedCodeInfo.IAnnotation, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes an Annotation message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns Annotation
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.GeneratedCodeInfo.Annotation;
+
+                /**
+                 * Decodes an Annotation message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns Annotation
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.GeneratedCodeInfo.Annotation;
+
+                /**
+                 * Verifies an Annotation message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates an Annotation message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns Annotation
+                 */
+                public static fromObject(object: { [k: string]: any }): google.protobuf.GeneratedCodeInfo.Annotation;
+
+                /**
+                 * Creates a plain object from an Annotation message. Also converts values to other types if specified.
+                 * @param message Annotation
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.protobuf.GeneratedCodeInfo.Annotation, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this Annotation to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+        }
+
+        /** Properties of a Timestamp. */
+        interface ITimestamp {
+
+            /** Timestamp seconds */
+            seconds?: (number|Long|string|null);
+
+            /** Timestamp nanos */
+            nanos?: (number|null);
+        }
+
+        /** Represents a Timestamp. */
+        class Timestamp implements ITimestamp {
+
+            /**
+             * Constructs a new Timestamp.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.ITimestamp);
+
+            /** Timestamp seconds. */
+            public seconds: (number|Long|string);
+
+            /** Timestamp nanos. */
+            public nanos: number;
+
+            /**
+             * Creates a new Timestamp instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns Timestamp instance
+             */
+            public static create(properties?: google.protobuf.ITimestamp): google.protobuf.Timestamp;
+
+            /**
+             * Encodes the specified Timestamp message. Does not implicitly {@link google.protobuf.Timestamp.verify|verify} messages.
+             * @param message Timestamp message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.ITimestamp, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified Timestamp message, length delimited. Does not implicitly {@link google.protobuf.Timestamp.verify|verify} messages.
+             * @param message Timestamp message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.ITimestamp, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a Timestamp message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns Timestamp
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.Timestamp;
+
+            /**
+             * Decodes a Timestamp message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns Timestamp
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.Timestamp;
+
+            /**
+             * Verifies a Timestamp message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a Timestamp message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns Timestamp
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.Timestamp;
+
+            /**
+             * Creates a plain object from a Timestamp message. Also converts values to other types if specified.
+             * @param message Timestamp
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.Timestamp, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this Timestamp to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of an Any. */
+        interface IAny {
+
+            /** Any type_url */
+            type_url?: (string|null);
+
+            /** Any value */
+            value?: (Uint8Array|string|null);
+        }
+
+        /** Represents an Any. */
+        class Any implements IAny {
+
+            /**
+             * Constructs a new Any.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IAny);
+
+            /** Any type_url. */
+            public type_url: string;
+
+            /** Any value. */
+            public value: (Uint8Array|string);
+
+            /**
+             * Creates a new Any instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns Any instance
+             */
+            public static create(properties?: google.protobuf.IAny): google.protobuf.Any;
+
+            /**
+             * Encodes the specified Any message. Does not implicitly {@link google.protobuf.Any.verify|verify} messages.
+             * @param message Any message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IAny, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified Any message, length delimited. Does not implicitly {@link google.protobuf.Any.verify|verify} messages.
+             * @param message Any message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IAny, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an Any message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns Any
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.Any;
+
+            /**
+             * Decodes an Any message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns Any
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.Any;
+
+            /**
+             * Verifies an Any message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an Any message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns Any
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.Any;
+
+            /**
+             * Creates a plain object from an Any message. Also converts values to other types if specified.
+             * @param message Any
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.Any, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this Any to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of an Empty. */
+        interface IEmpty {
+        }
+
+        /** Represents an Empty. */
+        class Empty implements IEmpty {
+
+            /**
+             * Constructs a new Empty.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IEmpty);
+
+            /**
+             * Creates a new Empty instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns Empty instance
+             */
+            public static create(properties?: google.protobuf.IEmpty): google.protobuf.Empty;
+
+            /**
+             * Encodes the specified Empty message. Does not implicitly {@link google.protobuf.Empty.verify|verify} messages.
+             * @param message Empty message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IEmpty, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified Empty message, length delimited. Does not implicitly {@link google.protobuf.Empty.verify|verify} messages.
+             * @param message Empty message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IEmpty, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an Empty message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns Empty
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.Empty;
+
+            /**
+             * Decodes an Empty message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns Empty
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.Empty;
+
+            /**
+             * Verifies an Empty message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an Empty message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns Empty
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.Empty;
+
+            /**
+             * Creates a plain object from an Empty message. Also converts values to other types if specified.
+             * @param message Empty
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.Empty, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this Empty to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+
+        /** Properties of a FieldMask. */
+        interface IFieldMask {
+
+            /** FieldMask paths */
+            paths?: (string[]|null);
+        }
+
+        /** Represents a FieldMask. */
+        class FieldMask implements IFieldMask {
+
+            /**
+             * Constructs a new FieldMask.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.protobuf.IFieldMask);
+
+            /** FieldMask paths. */
+            public paths: string[];
+
+            /**
+             * Creates a new FieldMask instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns FieldMask instance
+             */
+            public static create(properties?: google.protobuf.IFieldMask): google.protobuf.FieldMask;
+
+            /**
+             * Encodes the specified FieldMask message. Does not implicitly {@link google.protobuf.FieldMask.verify|verify} messages.
+             * @param message FieldMask message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.protobuf.IFieldMask, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified FieldMask message, length delimited. Does not implicitly {@link google.protobuf.FieldMask.verify|verify} messages.
+             * @param message FieldMask message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.protobuf.IFieldMask, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a FieldMask message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns FieldMask
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.protobuf.FieldMask;
+
+            /**
+             * Decodes a FieldMask message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns FieldMask
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.protobuf.FieldMask;
+
+            /**
+             * Verifies a FieldMask message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a FieldMask message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns FieldMask
+             */
+            public static fromObject(object: { [k: string]: any }): google.protobuf.FieldMask;
+
+            /**
+             * Creates a plain object from a FieldMask message. Also converts values to other types if specified.
+             * @param message FieldMask
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.protobuf.FieldMask, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this FieldMask to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+    }
+
+    /** Namespace rpc. */
+    namespace rpc {
+
+        /** Properties of a Status. */
+        interface IStatus {
+
+            /** Status code */
+            code?: (number|null);
+
+            /** Status message */
+            message?: (string|null);
+
+            /** Status details */
+            details?: (google.protobuf.IAny[]|null);
+        }
+
+        /** Represents a Status. */
+        class Status implements IStatus {
+
+            /**
+             * Constructs a new Status.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.rpc.IStatus);
+
+            /** Status code. */
+            public code: number;
+
+            /** Status message. */
+            public message: string;
+
+            /** Status details. */
+            public details: google.protobuf.IAny[];
+
+            /**
+             * Creates a new Status instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns Status instance
+             */
+            public static create(properties?: google.rpc.IStatus): google.rpc.Status;
+
+            /**
+             * Encodes the specified Status message. Does not implicitly {@link google.rpc.Status.verify|verify} messages.
+             * @param message Status message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.rpc.IStatus, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified Status message, length delimited. Does not implicitly {@link google.rpc.Status.verify|verify} messages.
+             * @param message Status message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.rpc.IStatus, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes a Status message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns Status
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.rpc.Status;
+
+            /**
+             * Decodes a Status message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns Status
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.rpc.Status;
+
+            /**
+             * Verifies a Status message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates a Status message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns Status
+             */
+            public static fromObject(object: { [k: string]: any }): google.rpc.Status;
+
+            /**
+             * Creates a plain object from a Status message. Also converts values to other types if specified.
+             * @param message Status
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.rpc.Status, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this Status to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+    }
+
+    /** Namespace iam. */
+    namespace iam {
+
+        /** Namespace v1. */
+        namespace v1 {
+
+            /** Represents a IAMPolicy */
+            class IAMPolicy extends $protobuf.rpc.Service {
+
+                /**
+                 * Constructs a new IAMPolicy service.
+                 * @param rpcImpl RPC implementation
+                 * @param [requestDelimited=false] Whether requests are length-delimited
+                 * @param [responseDelimited=false] Whether responses are length-delimited
+                 */
+                constructor(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean);
+
+                /**
+                 * Creates new IAMPolicy service using the specified rpc implementation.
+                 * @param rpcImpl RPC implementation
+                 * @param [requestDelimited=false] Whether requests are length-delimited
+                 * @param [responseDelimited=false] Whether responses are length-delimited
+                 * @returns RPC service. Useful where requests and/or responses are streamed.
+                 */
+                public static create(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): IAMPolicy;
+
+                /**
+                 * Calls SetIamPolicy.
+                 * @param request SetIamPolicyRequest message or plain object
+                 * @param callback Node-style callback called with the error, if any, and Policy
+                 */
+                public setIamPolicy(request: google.iam.v1.ISetIamPolicyRequest, callback: google.iam.v1.IAMPolicy.SetIamPolicyCallback): void;
+
+                /**
+                 * Calls SetIamPolicy.
+                 * @param request SetIamPolicyRequest message or plain object
+                 * @returns Promise
+                 */
+                public setIamPolicy(request: google.iam.v1.ISetIamPolicyRequest): Promise<google.iam.v1.Policy>;
+
+                /**
+                 * Calls GetIamPolicy.
+                 * @param request GetIamPolicyRequest message or plain object
+                 * @param callback Node-style callback called with the error, if any, and Policy
+                 */
+                public getIamPolicy(request: google.iam.v1.IGetIamPolicyRequest, callback: google.iam.v1.IAMPolicy.GetIamPolicyCallback): void;
+
+                /**
+                 * Calls GetIamPolicy.
+                 * @param request GetIamPolicyRequest message or plain object
+                 * @returns Promise
+                 */
+                public getIamPolicy(request: google.iam.v1.IGetIamPolicyRequest): Promise<google.iam.v1.Policy>;
+
+                /**
+                 * Calls TestIamPermissions.
+                 * @param request TestIamPermissionsRequest message or plain object
+                 * @param callback Node-style callback called with the error, if any, and TestIamPermissionsResponse
+                 */
+                public testIamPermissions(request: google.iam.v1.ITestIamPermissionsRequest, callback: google.iam.v1.IAMPolicy.TestIamPermissionsCallback): void;
+
+                /**
+                 * Calls TestIamPermissions.
+                 * @param request TestIamPermissionsRequest message or plain object
+                 * @returns Promise
+                 */
+                public testIamPermissions(request: google.iam.v1.ITestIamPermissionsRequest): Promise<google.iam.v1.TestIamPermissionsResponse>;
+            }
+
+            namespace IAMPolicy {
+
+                /**
+                 * Callback as used by {@link google.iam.v1.IAMPolicy#setIamPolicy}.
+                 * @param error Error, if any
+                 * @param [response] Policy
+                 */
+                type SetIamPolicyCallback = (error: (Error|null), response?: google.iam.v1.Policy) => void;
+
+                /**
+                 * Callback as used by {@link google.iam.v1.IAMPolicy#getIamPolicy}.
+                 * @param error Error, if any
+                 * @param [response] Policy
+                 */
+                type GetIamPolicyCallback = (error: (Error|null), response?: google.iam.v1.Policy) => void;
+
+                /**
+                 * Callback as used by {@link google.iam.v1.IAMPolicy#testIamPermissions}.
+                 * @param error Error, if any
+                 * @param [response] TestIamPermissionsResponse
+                 */
+                type TestIamPermissionsCallback = (error: (Error|null), response?: google.iam.v1.TestIamPermissionsResponse) => void;
+            }
+
+            /** Properties of a SetIamPolicyRequest. */
+            interface ISetIamPolicyRequest {
+
+                /** SetIamPolicyRequest resource */
+                resource?: (string|null);
+
+                /** SetIamPolicyRequest policy */
+                policy?: (google.iam.v1.IPolicy|null);
+            }
+
+            /** Represents a SetIamPolicyRequest. */
+            class SetIamPolicyRequest implements ISetIamPolicyRequest {
+
+                /**
+                 * Constructs a new SetIamPolicyRequest.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.ISetIamPolicyRequest);
+
+                /** SetIamPolicyRequest resource. */
+                public resource: string;
+
+                /** SetIamPolicyRequest policy. */
+                public policy?: (google.iam.v1.IPolicy|null);
+
+                /**
+                 * Creates a new SetIamPolicyRequest instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns SetIamPolicyRequest instance
+                 */
+                public static create(properties?: google.iam.v1.ISetIamPolicyRequest): google.iam.v1.SetIamPolicyRequest;
+
+                /**
+                 * Encodes the specified SetIamPolicyRequest message. Does not implicitly {@link google.iam.v1.SetIamPolicyRequest.verify|verify} messages.
+                 * @param message SetIamPolicyRequest message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.ISetIamPolicyRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified SetIamPolicyRequest message, length delimited. Does not implicitly {@link google.iam.v1.SetIamPolicyRequest.verify|verify} messages.
+                 * @param message SetIamPolicyRequest message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.ISetIamPolicyRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a SetIamPolicyRequest message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns SetIamPolicyRequest
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.SetIamPolicyRequest;
+
+                /**
+                 * Decodes a SetIamPolicyRequest message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns SetIamPolicyRequest
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.SetIamPolicyRequest;
+
+                /**
+                 * Verifies a SetIamPolicyRequest message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a SetIamPolicyRequest message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns SetIamPolicyRequest
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.SetIamPolicyRequest;
+
+                /**
+                 * Creates a plain object from a SetIamPolicyRequest message. Also converts values to other types if specified.
+                 * @param message SetIamPolicyRequest
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.SetIamPolicyRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this SetIamPolicyRequest to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a GetIamPolicyRequest. */
+            interface IGetIamPolicyRequest {
+
+                /** GetIamPolicyRequest resource */
+                resource?: (string|null);
+
+                /** GetIamPolicyRequest options */
+                options?: (google.iam.v1.IGetPolicyOptions|null);
+            }
+
+            /** Represents a GetIamPolicyRequest. */
+            class GetIamPolicyRequest implements IGetIamPolicyRequest {
+
+                /**
+                 * Constructs a new GetIamPolicyRequest.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.IGetIamPolicyRequest);
+
+                /** GetIamPolicyRequest resource. */
+                public resource: string;
+
+                /** GetIamPolicyRequest options. */
+                public options?: (google.iam.v1.IGetPolicyOptions|null);
+
+                /**
+                 * Creates a new GetIamPolicyRequest instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns GetIamPolicyRequest instance
+                 */
+                public static create(properties?: google.iam.v1.IGetIamPolicyRequest): google.iam.v1.GetIamPolicyRequest;
+
+                /**
+                 * Encodes the specified GetIamPolicyRequest message. Does not implicitly {@link google.iam.v1.GetIamPolicyRequest.verify|verify} messages.
+                 * @param message GetIamPolicyRequest message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.IGetIamPolicyRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified GetIamPolicyRequest message, length delimited. Does not implicitly {@link google.iam.v1.GetIamPolicyRequest.verify|verify} messages.
+                 * @param message GetIamPolicyRequest message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.IGetIamPolicyRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a GetIamPolicyRequest message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns GetIamPolicyRequest
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.GetIamPolicyRequest;
+
+                /**
+                 * Decodes a GetIamPolicyRequest message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns GetIamPolicyRequest
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.GetIamPolicyRequest;
+
+                /**
+                 * Verifies a GetIamPolicyRequest message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a GetIamPolicyRequest message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns GetIamPolicyRequest
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.GetIamPolicyRequest;
+
+                /**
+                 * Creates a plain object from a GetIamPolicyRequest message. Also converts values to other types if specified.
+                 * @param message GetIamPolicyRequest
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.GetIamPolicyRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this GetIamPolicyRequest to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a TestIamPermissionsRequest. */
+            interface ITestIamPermissionsRequest {
+
+                /** TestIamPermissionsRequest resource */
+                resource?: (string|null);
+
+                /** TestIamPermissionsRequest permissions */
+                permissions?: (string[]|null);
+            }
+
+            /** Represents a TestIamPermissionsRequest. */
+            class TestIamPermissionsRequest implements ITestIamPermissionsRequest {
+
+                /**
+                 * Constructs a new TestIamPermissionsRequest.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.ITestIamPermissionsRequest);
+
+                /** TestIamPermissionsRequest resource. */
+                public resource: string;
+
+                /** TestIamPermissionsRequest permissions. */
+                public permissions: string[];
+
+                /**
+                 * Creates a new TestIamPermissionsRequest instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns TestIamPermissionsRequest instance
+                 */
+                public static create(properties?: google.iam.v1.ITestIamPermissionsRequest): google.iam.v1.TestIamPermissionsRequest;
+
+                /**
+                 * Encodes the specified TestIamPermissionsRequest message. Does not implicitly {@link google.iam.v1.TestIamPermissionsRequest.verify|verify} messages.
+                 * @param message TestIamPermissionsRequest message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.ITestIamPermissionsRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified TestIamPermissionsRequest message, length delimited. Does not implicitly {@link google.iam.v1.TestIamPermissionsRequest.verify|verify} messages.
+                 * @param message TestIamPermissionsRequest message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.ITestIamPermissionsRequest, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a TestIamPermissionsRequest message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns TestIamPermissionsRequest
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.TestIamPermissionsRequest;
+
+                /**
+                 * Decodes a TestIamPermissionsRequest message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns TestIamPermissionsRequest
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.TestIamPermissionsRequest;
+
+                /**
+                 * Verifies a TestIamPermissionsRequest message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a TestIamPermissionsRequest message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns TestIamPermissionsRequest
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.TestIamPermissionsRequest;
+
+                /**
+                 * Creates a plain object from a TestIamPermissionsRequest message. Also converts values to other types if specified.
+                 * @param message TestIamPermissionsRequest
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.TestIamPermissionsRequest, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this TestIamPermissionsRequest to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a TestIamPermissionsResponse. */
+            interface ITestIamPermissionsResponse {
+
+                /** TestIamPermissionsResponse permissions */
+                permissions?: (string[]|null);
+            }
+
+            /** Represents a TestIamPermissionsResponse. */
+            class TestIamPermissionsResponse implements ITestIamPermissionsResponse {
+
+                /**
+                 * Constructs a new TestIamPermissionsResponse.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.ITestIamPermissionsResponse);
+
+                /** TestIamPermissionsResponse permissions. */
+                public permissions: string[];
+
+                /**
+                 * Creates a new TestIamPermissionsResponse instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns TestIamPermissionsResponse instance
+                 */
+                public static create(properties?: google.iam.v1.ITestIamPermissionsResponse): google.iam.v1.TestIamPermissionsResponse;
+
+                /**
+                 * Encodes the specified TestIamPermissionsResponse message. Does not implicitly {@link google.iam.v1.TestIamPermissionsResponse.verify|verify} messages.
+                 * @param message TestIamPermissionsResponse message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.ITestIamPermissionsResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified TestIamPermissionsResponse message, length delimited. Does not implicitly {@link google.iam.v1.TestIamPermissionsResponse.verify|verify} messages.
+                 * @param message TestIamPermissionsResponse message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.ITestIamPermissionsResponse, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a TestIamPermissionsResponse message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns TestIamPermissionsResponse
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.TestIamPermissionsResponse;
+
+                /**
+                 * Decodes a TestIamPermissionsResponse message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns TestIamPermissionsResponse
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.TestIamPermissionsResponse;
+
+                /**
+                 * Verifies a TestIamPermissionsResponse message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a TestIamPermissionsResponse message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns TestIamPermissionsResponse
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.TestIamPermissionsResponse;
+
+                /**
+                 * Creates a plain object from a TestIamPermissionsResponse message. Also converts values to other types if specified.
+                 * @param message TestIamPermissionsResponse
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.TestIamPermissionsResponse, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this TestIamPermissionsResponse to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a GetPolicyOptions. */
+            interface IGetPolicyOptions {
+
+                /** GetPolicyOptions requestedPolicyVersion */
+                requestedPolicyVersion?: (number|null);
+            }
+
+            /** Represents a GetPolicyOptions. */
+            class GetPolicyOptions implements IGetPolicyOptions {
+
+                /**
+                 * Constructs a new GetPolicyOptions.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.IGetPolicyOptions);
+
+                /** GetPolicyOptions requestedPolicyVersion. */
+                public requestedPolicyVersion: number;
+
+                /**
+                 * Creates a new GetPolicyOptions instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns GetPolicyOptions instance
+                 */
+                public static create(properties?: google.iam.v1.IGetPolicyOptions): google.iam.v1.GetPolicyOptions;
+
+                /**
+                 * Encodes the specified GetPolicyOptions message. Does not implicitly {@link google.iam.v1.GetPolicyOptions.verify|verify} messages.
+                 * @param message GetPolicyOptions message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.IGetPolicyOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified GetPolicyOptions message, length delimited. Does not implicitly {@link google.iam.v1.GetPolicyOptions.verify|verify} messages.
+                 * @param message GetPolicyOptions message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.IGetPolicyOptions, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a GetPolicyOptions message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns GetPolicyOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.GetPolicyOptions;
+
+                /**
+                 * Decodes a GetPolicyOptions message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns GetPolicyOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.GetPolicyOptions;
+
+                /**
+                 * Verifies a GetPolicyOptions message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a GetPolicyOptions message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns GetPolicyOptions
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.GetPolicyOptions;
+
+                /**
+                 * Creates a plain object from a GetPolicyOptions message. Also converts values to other types if specified.
+                 * @param message GetPolicyOptions
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.GetPolicyOptions, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this GetPolicyOptions to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a Policy. */
+            interface IPolicy {
+
+                /** Policy version */
+                version?: (number|null);
+
+                /** Policy bindings */
+                bindings?: (google.iam.v1.IBinding[]|null);
+
+                /** Policy etag */
+                etag?: (Uint8Array|string|null);
+            }
+
+            /** Represents a Policy. */
+            class Policy implements IPolicy {
+
+                /**
+                 * Constructs a new Policy.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.IPolicy);
+
+                /** Policy version. */
+                public version: number;
+
+                /** Policy bindings. */
+                public bindings: google.iam.v1.IBinding[];
+
+                /** Policy etag. */
+                public etag: (Uint8Array|string);
+
+                /**
+                 * Creates a new Policy instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns Policy instance
+                 */
+                public static create(properties?: google.iam.v1.IPolicy): google.iam.v1.Policy;
+
+                /**
+                 * Encodes the specified Policy message. Does not implicitly {@link google.iam.v1.Policy.verify|verify} messages.
+                 * @param message Policy message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.IPolicy, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified Policy message, length delimited. Does not implicitly {@link google.iam.v1.Policy.verify|verify} messages.
+                 * @param message Policy message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.IPolicy, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a Policy message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns Policy
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.Policy;
+
+                /**
+                 * Decodes a Policy message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns Policy
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.Policy;
+
+                /**
+                 * Verifies a Policy message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a Policy message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns Policy
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.Policy;
+
+                /**
+                 * Creates a plain object from a Policy message. Also converts values to other types if specified.
+                 * @param message Policy
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.Policy, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this Policy to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a Binding. */
+            interface IBinding {
+
+                /** Binding role */
+                role?: (string|null);
+
+                /** Binding members */
+                members?: (string[]|null);
+
+                /** Binding condition */
+                condition?: (google.type.IExpr|null);
+            }
+
+            /** Represents a Binding. */
+            class Binding implements IBinding {
+
+                /**
+                 * Constructs a new Binding.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.IBinding);
+
+                /** Binding role. */
+                public role: string;
+
+                /** Binding members. */
+                public members: string[];
+
+                /** Binding condition. */
+                public condition?: (google.type.IExpr|null);
+
+                /**
+                 * Creates a new Binding instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns Binding instance
+                 */
+                public static create(properties?: google.iam.v1.IBinding): google.iam.v1.Binding;
+
+                /**
+                 * Encodes the specified Binding message. Does not implicitly {@link google.iam.v1.Binding.verify|verify} messages.
+                 * @param message Binding message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.IBinding, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified Binding message, length delimited. Does not implicitly {@link google.iam.v1.Binding.verify|verify} messages.
+                 * @param message Binding message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.IBinding, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a Binding message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns Binding
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.Binding;
+
+                /**
+                 * Decodes a Binding message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns Binding
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.Binding;
+
+                /**
+                 * Verifies a Binding message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a Binding message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns Binding
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.Binding;
+
+                /**
+                 * Creates a plain object from a Binding message. Also converts values to other types if specified.
+                 * @param message Binding
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.Binding, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this Binding to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a PolicyDelta. */
+            interface IPolicyDelta {
+
+                /** PolicyDelta bindingDeltas */
+                bindingDeltas?: (google.iam.v1.IBindingDelta[]|null);
+
+                /** PolicyDelta auditConfigDeltas */
+                auditConfigDeltas?: (google.iam.v1.IAuditConfigDelta[]|null);
+            }
+
+            /** Represents a PolicyDelta. */
+            class PolicyDelta implements IPolicyDelta {
+
+                /**
+                 * Constructs a new PolicyDelta.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.IPolicyDelta);
+
+                /** PolicyDelta bindingDeltas. */
+                public bindingDeltas: google.iam.v1.IBindingDelta[];
+
+                /** PolicyDelta auditConfigDeltas. */
+                public auditConfigDeltas: google.iam.v1.IAuditConfigDelta[];
+
+                /**
+                 * Creates a new PolicyDelta instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns PolicyDelta instance
+                 */
+                public static create(properties?: google.iam.v1.IPolicyDelta): google.iam.v1.PolicyDelta;
+
+                /**
+                 * Encodes the specified PolicyDelta message. Does not implicitly {@link google.iam.v1.PolicyDelta.verify|verify} messages.
+                 * @param message PolicyDelta message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.IPolicyDelta, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified PolicyDelta message, length delimited. Does not implicitly {@link google.iam.v1.PolicyDelta.verify|verify} messages.
+                 * @param message PolicyDelta message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.IPolicyDelta, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a PolicyDelta message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns PolicyDelta
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.PolicyDelta;
+
+                /**
+                 * Decodes a PolicyDelta message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns PolicyDelta
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.PolicyDelta;
+
+                /**
+                 * Verifies a PolicyDelta message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a PolicyDelta message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns PolicyDelta
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.PolicyDelta;
+
+                /**
+                 * Creates a plain object from a PolicyDelta message. Also converts values to other types if specified.
+                 * @param message PolicyDelta
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.PolicyDelta, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this PolicyDelta to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            /** Properties of a BindingDelta. */
+            interface IBindingDelta {
+
+                /** BindingDelta action */
+                action?: (google.iam.v1.BindingDelta.Action|keyof typeof google.iam.v1.BindingDelta.Action|null);
+
+                /** BindingDelta role */
+                role?: (string|null);
+
+                /** BindingDelta member */
+                member?: (string|null);
+
+                /** BindingDelta condition */
+                condition?: (google.type.IExpr|null);
+            }
+
+            /** Represents a BindingDelta. */
+            class BindingDelta implements IBindingDelta {
+
+                /**
+                 * Constructs a new BindingDelta.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.IBindingDelta);
+
+                /** BindingDelta action. */
+                public action: (google.iam.v1.BindingDelta.Action|keyof typeof google.iam.v1.BindingDelta.Action);
+
+                /** BindingDelta role. */
+                public role: string;
+
+                /** BindingDelta member. */
+                public member: string;
+
+                /** BindingDelta condition. */
+                public condition?: (google.type.IExpr|null);
+
+                /**
+                 * Creates a new BindingDelta instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns BindingDelta instance
+                 */
+                public static create(properties?: google.iam.v1.IBindingDelta): google.iam.v1.BindingDelta;
+
+                /**
+                 * Encodes the specified BindingDelta message. Does not implicitly {@link google.iam.v1.BindingDelta.verify|verify} messages.
+                 * @param message BindingDelta message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.IBindingDelta, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified BindingDelta message, length delimited. Does not implicitly {@link google.iam.v1.BindingDelta.verify|verify} messages.
+                 * @param message BindingDelta message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.IBindingDelta, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes a BindingDelta message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns BindingDelta
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.BindingDelta;
+
+                /**
+                 * Decodes a BindingDelta message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns BindingDelta
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.BindingDelta;
+
+                /**
+                 * Verifies a BindingDelta message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates a BindingDelta message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns BindingDelta
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.BindingDelta;
+
+                /**
+                 * Creates a plain object from a BindingDelta message. Also converts values to other types if specified.
+                 * @param message BindingDelta
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.BindingDelta, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this BindingDelta to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            namespace BindingDelta {
+
+                /** Action enum. */
+                enum Action {
+                    ACTION_UNSPECIFIED = 0,
+                    ADD = 1,
+                    REMOVE = 2
+                }
+            }
+
+            /** Properties of an AuditConfigDelta. */
+            interface IAuditConfigDelta {
+
+                /** AuditConfigDelta action */
+                action?: (google.iam.v1.AuditConfigDelta.Action|keyof typeof google.iam.v1.AuditConfigDelta.Action|null);
+
+                /** AuditConfigDelta service */
+                service?: (string|null);
+
+                /** AuditConfigDelta exemptedMember */
+                exemptedMember?: (string|null);
+
+                /** AuditConfigDelta logType */
+                logType?: (string|null);
+            }
+
+            /** Represents an AuditConfigDelta. */
+            class AuditConfigDelta implements IAuditConfigDelta {
+
+                /**
+                 * Constructs a new AuditConfigDelta.
+                 * @param [properties] Properties to set
+                 */
+                constructor(properties?: google.iam.v1.IAuditConfigDelta);
+
+                /** AuditConfigDelta action. */
+                public action: (google.iam.v1.AuditConfigDelta.Action|keyof typeof google.iam.v1.AuditConfigDelta.Action);
+
+                /** AuditConfigDelta service. */
+                public service: string;
+
+                /** AuditConfigDelta exemptedMember. */
+                public exemptedMember: string;
+
+                /** AuditConfigDelta logType. */
+                public logType: string;
+
+                /**
+                 * Creates a new AuditConfigDelta instance using the specified properties.
+                 * @param [properties] Properties to set
+                 * @returns AuditConfigDelta instance
+                 */
+                public static create(properties?: google.iam.v1.IAuditConfigDelta): google.iam.v1.AuditConfigDelta;
+
+                /**
+                 * Encodes the specified AuditConfigDelta message. Does not implicitly {@link google.iam.v1.AuditConfigDelta.verify|verify} messages.
+                 * @param message AuditConfigDelta message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encode(message: google.iam.v1.IAuditConfigDelta, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Encodes the specified AuditConfigDelta message, length delimited. Does not implicitly {@link google.iam.v1.AuditConfigDelta.verify|verify} messages.
+                 * @param message AuditConfigDelta message or plain object to encode
+                 * @param [writer] Writer to encode to
+                 * @returns Writer
+                 */
+                public static encodeDelimited(message: google.iam.v1.IAuditConfigDelta, writer?: $protobuf.Writer): $protobuf.Writer;
+
+                /**
+                 * Decodes an AuditConfigDelta message from the specified reader or buffer.
+                 * @param reader Reader or buffer to decode from
+                 * @param [length] Message length if known beforehand
+                 * @returns AuditConfigDelta
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.iam.v1.AuditConfigDelta;
+
+                /**
+                 * Decodes an AuditConfigDelta message from the specified reader or buffer, length delimited.
+                 * @param reader Reader or buffer to decode from
+                 * @returns AuditConfigDelta
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.iam.v1.AuditConfigDelta;
+
+                /**
+                 * Verifies an AuditConfigDelta message.
+                 * @param message Plain object to verify
+                 * @returns `null` if valid, otherwise the reason why it is not
+                 */
+                public static verify(message: { [k: string]: any }): (string|null);
+
+                /**
+                 * Creates an AuditConfigDelta message from a plain object. Also converts values to their respective internal types.
+                 * @param object Plain object
+                 * @returns AuditConfigDelta
+                 */
+                public static fromObject(object: { [k: string]: any }): google.iam.v1.AuditConfigDelta;
+
+                /**
+                 * Creates a plain object from an AuditConfigDelta message. Also converts values to other types if specified.
+                 * @param message AuditConfigDelta
+                 * @param [options] Conversion options
+                 * @returns Plain object
+                 */
+                public static toObject(message: google.iam.v1.AuditConfigDelta, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+                /**
+                 * Converts this AuditConfigDelta to JSON.
+                 * @returns JSON object
+                 */
+                public toJSON(): { [k: string]: any };
+            }
+
+            namespace AuditConfigDelta {
+
+                /** Action enum. */
+                enum Action {
+                    ACTION_UNSPECIFIED = 0,
+                    ADD = 1,
+                    REMOVE = 2
+                }
+            }
+        }
+    }
+
+    /** Namespace type. */
+    namespace type {
+
+        /** Properties of an Expr. */
+        interface IExpr {
+
+            /** Expr expression */
+            expression?: (string|null);
+
+            /** Expr title */
+            title?: (string|null);
+
+            /** Expr description */
+            description?: (string|null);
+
+            /** Expr location */
+            location?: (string|null);
+        }
+
+        /** Represents an Expr. */
+        class Expr implements IExpr {
+
+            /**
+             * Constructs a new Expr.
+             * @param [properties] Properties to set
+             */
+            constructor(properties?: google.type.IExpr);
+
+            /** Expr expression. */
+            public expression: string;
+
+            /** Expr title. */
+            public title: string;
+
+            /** Expr description. */
+            public description: string;
+
+            /** Expr location. */
+            public location: string;
+
+            /**
+             * Creates a new Expr instance using the specified properties.
+             * @param [properties] Properties to set
+             * @returns Expr instance
+             */
+            public static create(properties?: google.type.IExpr): google.type.Expr;
+
+            /**
+             * Encodes the specified Expr message. Does not implicitly {@link google.type.Expr.verify|verify} messages.
+             * @param message Expr message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encode(message: google.type.IExpr, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Encodes the specified Expr message, length delimited. Does not implicitly {@link google.type.Expr.verify|verify} messages.
+             * @param message Expr message or plain object to encode
+             * @param [writer] Writer to encode to
+             * @returns Writer
+             */
+            public static encodeDelimited(message: google.type.IExpr, writer?: $protobuf.Writer): $protobuf.Writer;
+
+            /**
+             * Decodes an Expr message from the specified reader or buffer.
+             * @param reader Reader or buffer to decode from
+             * @param [length] Message length if known beforehand
+             * @returns Expr
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): google.type.Expr;
+
+            /**
+             * Decodes an Expr message from the specified reader or buffer, length delimited.
+             * @param reader Reader or buffer to decode from
+             * @returns Expr
+             * @throws {Error} If the payload is not a reader or valid buffer
+             * @throws {$protobuf.util.ProtocolError} If required fields are missing
+             */
+            public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): google.type.Expr;
+
+            /**
+             * Verifies an Expr message.
+             * @param message Plain object to verify
+             * @returns `null` if valid, otherwise the reason why it is not
+             */
+            public static verify(message: { [k: string]: any }): (string|null);
+
+            /**
+             * Creates an Expr message from a plain object. Also converts values to their respective internal types.
+             * @param object Plain object
+             * @returns Expr
+             */
+            public static fromObject(object: { [k: string]: any }): google.type.Expr;
+
+            /**
+             * Creates a plain object from an Expr message. Also converts values to other types if specified.
+             * @param message Expr
+             * @param [options] Conversion options
+             * @returns Plain object
+             */
+            public static toObject(message: google.type.Expr, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+            /**
+             * Converts this Expr to JSON.
+             * @returns JSON object
+             */
+            public toJSON(): { [k: string]: any };
+        }
+    }
+}
diff --git a/protos/protos.js b/protos/protos.js
new file mode 100644
index 0000000000000000000000000000000000000000..cc370934adb0c3942fce28acc464ebcd2e5b3727
--- /dev/null
+++ b/protos/protos.js
@@ -0,0 +1,24290 @@
+// Copyright 2022 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 block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/
+(function(global, factory) { /* global define, require, module */
+
+    /* AMD */ if (typeof define === 'function' && define.amd)
+        define(["protobufjs/minimal"], factory);
+
+    /* CommonJS */ else if (typeof require === 'function' && typeof module === 'object' && module && module.exports)
+        module.exports = factory(require("google-gax").protobufMinimal);
+
+})(this, function($protobuf) {
+    "use strict";
+
+    // Common aliases
+    var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
+    
+    // Exported root namespace
+    var $root = $protobuf.roots._google_cloud_iot_protos || ($protobuf.roots._google_cloud_iot_protos = {});
+    
+    $root.google = (function() {
+    
+        /**
+         * Namespace google.
+         * @exports google
+         * @namespace
+         */
+        var google = {};
+    
+        google.cloud = (function() {
+    
+            /**
+             * Namespace cloud.
+             * @memberof google
+             * @namespace
+             */
+            var cloud = {};
+    
+            cloud.iot = (function() {
+    
+                /**
+                 * Namespace iot.
+                 * @memberof google.cloud
+                 * @namespace
+                 */
+                var iot = {};
+    
+                iot.v1 = (function() {
+    
+                    /**
+                     * Namespace v1.
+                     * @memberof google.cloud.iot
+                     * @namespace
+                     */
+                    var v1 = {};
+    
+                    v1.DeviceManager = (function() {
+    
+                        /**
+                         * Constructs a new DeviceManager service.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a DeviceManager
+                         * @extends $protobuf.rpc.Service
+                         * @constructor
+                         * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
+                         * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
+                         * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
+                         */
+                        function DeviceManager(rpcImpl, requestDelimited, responseDelimited) {
+                            $protobuf.rpc.Service.call(this, rpcImpl, requestDelimited, responseDelimited);
+                        }
+    
+                        (DeviceManager.prototype = Object.create($protobuf.rpc.Service.prototype)).constructor = DeviceManager;
+    
+                        /**
+                         * Creates new DeviceManager service using the specified rpc implementation.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @static
+                         * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
+                         * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
+                         * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
+                         * @returns {DeviceManager} RPC service. Useful where requests and/or responses are streamed.
+                         */
+                        DeviceManager.create = function create(rpcImpl, requestDelimited, responseDelimited) {
+                            return new this(rpcImpl, requestDelimited, responseDelimited);
+                        };
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#createDeviceRegistry}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef CreateDeviceRegistryCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.DeviceRegistry} [response] DeviceRegistry
+                         */
+    
+                        /**
+                         * Calls CreateDeviceRegistry.
+                         * @function createDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.ICreateDeviceRegistryRequest} request CreateDeviceRegistryRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.CreateDeviceRegistryCallback} callback Node-style callback called with the error, if any, and DeviceRegistry
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.createDeviceRegistry = function createDeviceRegistry(request, callback) {
+                            return this.rpcCall(createDeviceRegistry, $root.google.cloud.iot.v1.CreateDeviceRegistryRequest, $root.google.cloud.iot.v1.DeviceRegistry, request, callback);
+                        }, "name", { value: "CreateDeviceRegistry" });
+    
+                        /**
+                         * Calls CreateDeviceRegistry.
+                         * @function createDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.ICreateDeviceRegistryRequest} request CreateDeviceRegistryRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.DeviceRegistry>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#getDeviceRegistry}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef GetDeviceRegistryCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.DeviceRegistry} [response] DeviceRegistry
+                         */
+    
+                        /**
+                         * Calls GetDeviceRegistry.
+                         * @function getDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IGetDeviceRegistryRequest} request GetDeviceRegistryRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.GetDeviceRegistryCallback} callback Node-style callback called with the error, if any, and DeviceRegistry
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.getDeviceRegistry = function getDeviceRegistry(request, callback) {
+                            return this.rpcCall(getDeviceRegistry, $root.google.cloud.iot.v1.GetDeviceRegistryRequest, $root.google.cloud.iot.v1.DeviceRegistry, request, callback);
+                        }, "name", { value: "GetDeviceRegistry" });
+    
+                        /**
+                         * Calls GetDeviceRegistry.
+                         * @function getDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IGetDeviceRegistryRequest} request GetDeviceRegistryRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.DeviceRegistry>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#updateDeviceRegistry}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef UpdateDeviceRegistryCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.DeviceRegistry} [response] DeviceRegistry
+                         */
+    
+                        /**
+                         * Calls UpdateDeviceRegistry.
+                         * @function updateDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRegistryRequest} request UpdateDeviceRegistryRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.UpdateDeviceRegistryCallback} callback Node-style callback called with the error, if any, and DeviceRegistry
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.updateDeviceRegistry = function updateDeviceRegistry(request, callback) {
+                            return this.rpcCall(updateDeviceRegistry, $root.google.cloud.iot.v1.UpdateDeviceRegistryRequest, $root.google.cloud.iot.v1.DeviceRegistry, request, callback);
+                        }, "name", { value: "UpdateDeviceRegistry" });
+    
+                        /**
+                         * Calls UpdateDeviceRegistry.
+                         * @function updateDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRegistryRequest} request UpdateDeviceRegistryRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.DeviceRegistry>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#deleteDeviceRegistry}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef DeleteDeviceRegistryCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.protobuf.Empty} [response] Empty
+                         */
+    
+                        /**
+                         * Calls DeleteDeviceRegistry.
+                         * @function deleteDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRegistryRequest} request DeleteDeviceRegistryRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.DeleteDeviceRegistryCallback} callback Node-style callback called with the error, if any, and Empty
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.deleteDeviceRegistry = function deleteDeviceRegistry(request, callback) {
+                            return this.rpcCall(deleteDeviceRegistry, $root.google.cloud.iot.v1.DeleteDeviceRegistryRequest, $root.google.protobuf.Empty, request, callback);
+                        }, "name", { value: "DeleteDeviceRegistry" });
+    
+                        /**
+                         * Calls DeleteDeviceRegistry.
+                         * @function deleteDeviceRegistry
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRegistryRequest} request DeleteDeviceRegistryRequest message or plain object
+                         * @returns {Promise<google.protobuf.Empty>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDeviceRegistries}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef ListDeviceRegistriesCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.ListDeviceRegistriesResponse} [response] ListDeviceRegistriesResponse
+                         */
+    
+                        /**
+                         * Calls ListDeviceRegistries.
+                         * @function listDeviceRegistries
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesRequest} request ListDeviceRegistriesRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.ListDeviceRegistriesCallback} callback Node-style callback called with the error, if any, and ListDeviceRegistriesResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.listDeviceRegistries = function listDeviceRegistries(request, callback) {
+                            return this.rpcCall(listDeviceRegistries, $root.google.cloud.iot.v1.ListDeviceRegistriesRequest, $root.google.cloud.iot.v1.ListDeviceRegistriesResponse, request, callback);
+                        }, "name", { value: "ListDeviceRegistries" });
+    
+                        /**
+                         * Calls ListDeviceRegistries.
+                         * @function listDeviceRegistries
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesRequest} request ListDeviceRegistriesRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.ListDeviceRegistriesResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#createDevice}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef CreateDeviceCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.Device} [response] Device
+                         */
+    
+                        /**
+                         * Calls CreateDevice.
+                         * @function createDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.ICreateDeviceRequest} request CreateDeviceRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.CreateDeviceCallback} callback Node-style callback called with the error, if any, and Device
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.createDevice = function createDevice(request, callback) {
+                            return this.rpcCall(createDevice, $root.google.cloud.iot.v1.CreateDeviceRequest, $root.google.cloud.iot.v1.Device, request, callback);
+                        }, "name", { value: "CreateDevice" });
+    
+                        /**
+                         * Calls CreateDevice.
+                         * @function createDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.ICreateDeviceRequest} request CreateDeviceRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.Device>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#getDevice}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef GetDeviceCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.Device} [response] Device
+                         */
+    
+                        /**
+                         * Calls GetDevice.
+                         * @function getDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IGetDeviceRequest} request GetDeviceRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.GetDeviceCallback} callback Node-style callback called with the error, if any, and Device
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.getDevice = function getDevice(request, callback) {
+                            return this.rpcCall(getDevice, $root.google.cloud.iot.v1.GetDeviceRequest, $root.google.cloud.iot.v1.Device, request, callback);
+                        }, "name", { value: "GetDevice" });
+    
+                        /**
+                         * Calls GetDevice.
+                         * @function getDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IGetDeviceRequest} request GetDeviceRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.Device>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#updateDevice}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef UpdateDeviceCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.Device} [response] Device
+                         */
+    
+                        /**
+                         * Calls UpdateDevice.
+                         * @function updateDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRequest} request UpdateDeviceRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.UpdateDeviceCallback} callback Node-style callback called with the error, if any, and Device
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.updateDevice = function updateDevice(request, callback) {
+                            return this.rpcCall(updateDevice, $root.google.cloud.iot.v1.UpdateDeviceRequest, $root.google.cloud.iot.v1.Device, request, callback);
+                        }, "name", { value: "UpdateDevice" });
+    
+                        /**
+                         * Calls UpdateDevice.
+                         * @function updateDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRequest} request UpdateDeviceRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.Device>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#deleteDevice}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef DeleteDeviceCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.protobuf.Empty} [response] Empty
+                         */
+    
+                        /**
+                         * Calls DeleteDevice.
+                         * @function deleteDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRequest} request DeleteDeviceRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.DeleteDeviceCallback} callback Node-style callback called with the error, if any, and Empty
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.deleteDevice = function deleteDevice(request, callback) {
+                            return this.rpcCall(deleteDevice, $root.google.cloud.iot.v1.DeleteDeviceRequest, $root.google.protobuf.Empty, request, callback);
+                        }, "name", { value: "DeleteDevice" });
+    
+                        /**
+                         * Calls DeleteDevice.
+                         * @function deleteDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRequest} request DeleteDeviceRequest message or plain object
+                         * @returns {Promise<google.protobuf.Empty>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDevices}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef ListDevicesCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.ListDevicesResponse} [response] ListDevicesResponse
+                         */
+    
+                        /**
+                         * Calls ListDevices.
+                         * @function listDevices
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDevicesRequest} request ListDevicesRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.ListDevicesCallback} callback Node-style callback called with the error, if any, and ListDevicesResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.listDevices = function listDevices(request, callback) {
+                            return this.rpcCall(listDevices, $root.google.cloud.iot.v1.ListDevicesRequest, $root.google.cloud.iot.v1.ListDevicesResponse, request, callback);
+                        }, "name", { value: "ListDevices" });
+    
+                        /**
+                         * Calls ListDevices.
+                         * @function listDevices
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDevicesRequest} request ListDevicesRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.ListDevicesResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#modifyCloudToDeviceConfig}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef ModifyCloudToDeviceConfigCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.DeviceConfig} [response] DeviceConfig
+                         */
+    
+                        /**
+                         * Calls ModifyCloudToDeviceConfig.
+                         * @function modifyCloudToDeviceConfig
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest} request ModifyCloudToDeviceConfigRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.ModifyCloudToDeviceConfigCallback} callback Node-style callback called with the error, if any, and DeviceConfig
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.modifyCloudToDeviceConfig = function modifyCloudToDeviceConfig(request, callback) {
+                            return this.rpcCall(modifyCloudToDeviceConfig, $root.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest, $root.google.cloud.iot.v1.DeviceConfig, request, callback);
+                        }, "name", { value: "ModifyCloudToDeviceConfig" });
+    
+                        /**
+                         * Calls ModifyCloudToDeviceConfig.
+                         * @function modifyCloudToDeviceConfig
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest} request ModifyCloudToDeviceConfigRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.DeviceConfig>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDeviceConfigVersions}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef ListDeviceConfigVersionsCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.ListDeviceConfigVersionsResponse} [response] ListDeviceConfigVersionsResponse
+                         */
+    
+                        /**
+                         * Calls ListDeviceConfigVersions.
+                         * @function listDeviceConfigVersions
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsRequest} request ListDeviceConfigVersionsRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.ListDeviceConfigVersionsCallback} callback Node-style callback called with the error, if any, and ListDeviceConfigVersionsResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.listDeviceConfigVersions = function listDeviceConfigVersions(request, callback) {
+                            return this.rpcCall(listDeviceConfigVersions, $root.google.cloud.iot.v1.ListDeviceConfigVersionsRequest, $root.google.cloud.iot.v1.ListDeviceConfigVersionsResponse, request, callback);
+                        }, "name", { value: "ListDeviceConfigVersions" });
+    
+                        /**
+                         * Calls ListDeviceConfigVersions.
+                         * @function listDeviceConfigVersions
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsRequest} request ListDeviceConfigVersionsRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.ListDeviceConfigVersionsResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#listDeviceStates}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef ListDeviceStatesCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.ListDeviceStatesResponse} [response] ListDeviceStatesResponse
+                         */
+    
+                        /**
+                         * Calls ListDeviceStates.
+                         * @function listDeviceStates
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDeviceStatesRequest} request ListDeviceStatesRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.ListDeviceStatesCallback} callback Node-style callback called with the error, if any, and ListDeviceStatesResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.listDeviceStates = function listDeviceStates(request, callback) {
+                            return this.rpcCall(listDeviceStates, $root.google.cloud.iot.v1.ListDeviceStatesRequest, $root.google.cloud.iot.v1.ListDeviceStatesResponse, request, callback);
+                        }, "name", { value: "ListDeviceStates" });
+    
+                        /**
+                         * Calls ListDeviceStates.
+                         * @function listDeviceStates
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IListDeviceStatesRequest} request ListDeviceStatesRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.ListDeviceStatesResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#setIamPolicy}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef SetIamPolicyCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.iam.v1.Policy} [response] Policy
+                         */
+    
+                        /**
+                         * Calls SetIamPolicy.
+                         * @function setIamPolicy
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.iam.v1.ISetIamPolicyRequest} request SetIamPolicyRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.SetIamPolicyCallback} callback Node-style callback called with the error, if any, and Policy
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.setIamPolicy = function setIamPolicy(request, callback) {
+                            return this.rpcCall(setIamPolicy, $root.google.iam.v1.SetIamPolicyRequest, $root.google.iam.v1.Policy, request, callback);
+                        }, "name", { value: "SetIamPolicy" });
+    
+                        /**
+                         * Calls SetIamPolicy.
+                         * @function setIamPolicy
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.iam.v1.ISetIamPolicyRequest} request SetIamPolicyRequest message or plain object
+                         * @returns {Promise<google.iam.v1.Policy>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#getIamPolicy}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef GetIamPolicyCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.iam.v1.Policy} [response] Policy
+                         */
+    
+                        /**
+                         * Calls GetIamPolicy.
+                         * @function getIamPolicy
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.iam.v1.IGetIamPolicyRequest} request GetIamPolicyRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.GetIamPolicyCallback} callback Node-style callback called with the error, if any, and Policy
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.getIamPolicy = function getIamPolicy(request, callback) {
+                            return this.rpcCall(getIamPolicy, $root.google.iam.v1.GetIamPolicyRequest, $root.google.iam.v1.Policy, request, callback);
+                        }, "name", { value: "GetIamPolicy" });
+    
+                        /**
+                         * Calls GetIamPolicy.
+                         * @function getIamPolicy
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.iam.v1.IGetIamPolicyRequest} request GetIamPolicyRequest message or plain object
+                         * @returns {Promise<google.iam.v1.Policy>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#testIamPermissions}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef TestIamPermissionsCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.iam.v1.TestIamPermissionsResponse} [response] TestIamPermissionsResponse
+                         */
+    
+                        /**
+                         * Calls TestIamPermissions.
+                         * @function testIamPermissions
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.iam.v1.ITestIamPermissionsRequest} request TestIamPermissionsRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.TestIamPermissionsCallback} callback Node-style callback called with the error, if any, and TestIamPermissionsResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.testIamPermissions = function testIamPermissions(request, callback) {
+                            return this.rpcCall(testIamPermissions, $root.google.iam.v1.TestIamPermissionsRequest, $root.google.iam.v1.TestIamPermissionsResponse, request, callback);
+                        }, "name", { value: "TestIamPermissions" });
+    
+                        /**
+                         * Calls TestIamPermissions.
+                         * @function testIamPermissions
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.iam.v1.ITestIamPermissionsRequest} request TestIamPermissionsRequest message or plain object
+                         * @returns {Promise<google.iam.v1.TestIamPermissionsResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#sendCommandToDevice}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef SendCommandToDeviceCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.SendCommandToDeviceResponse} [response] SendCommandToDeviceResponse
+                         */
+    
+                        /**
+                         * Calls SendCommandToDevice.
+                         * @function sendCommandToDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceRequest} request SendCommandToDeviceRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.SendCommandToDeviceCallback} callback Node-style callback called with the error, if any, and SendCommandToDeviceResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.sendCommandToDevice = function sendCommandToDevice(request, callback) {
+                            return this.rpcCall(sendCommandToDevice, $root.google.cloud.iot.v1.SendCommandToDeviceRequest, $root.google.cloud.iot.v1.SendCommandToDeviceResponse, request, callback);
+                        }, "name", { value: "SendCommandToDevice" });
+    
+                        /**
+                         * Calls SendCommandToDevice.
+                         * @function sendCommandToDevice
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceRequest} request SendCommandToDeviceRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.SendCommandToDeviceResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#bindDeviceToGateway}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef BindDeviceToGatewayCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.BindDeviceToGatewayResponse} [response] BindDeviceToGatewayResponse
+                         */
+    
+                        /**
+                         * Calls BindDeviceToGateway.
+                         * @function bindDeviceToGateway
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayRequest} request BindDeviceToGatewayRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.BindDeviceToGatewayCallback} callback Node-style callback called with the error, if any, and BindDeviceToGatewayResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.bindDeviceToGateway = function bindDeviceToGateway(request, callback) {
+                            return this.rpcCall(bindDeviceToGateway, $root.google.cloud.iot.v1.BindDeviceToGatewayRequest, $root.google.cloud.iot.v1.BindDeviceToGatewayResponse, request, callback);
+                        }, "name", { value: "BindDeviceToGateway" });
+    
+                        /**
+                         * Calls BindDeviceToGateway.
+                         * @function bindDeviceToGateway
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayRequest} request BindDeviceToGatewayRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.BindDeviceToGatewayResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        /**
+                         * Callback as used by {@link google.cloud.iot.v1.DeviceManager#unbindDeviceFromGateway}.
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @typedef UnbindDeviceFromGatewayCallback
+                         * @type {function}
+                         * @param {Error|null} error Error, if any
+                         * @param {google.cloud.iot.v1.UnbindDeviceFromGatewayResponse} [response] UnbindDeviceFromGatewayResponse
+                         */
+    
+                        /**
+                         * Calls UnbindDeviceFromGateway.
+                         * @function unbindDeviceFromGateway
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest} request UnbindDeviceFromGatewayRequest message or plain object
+                         * @param {google.cloud.iot.v1.DeviceManager.UnbindDeviceFromGatewayCallback} callback Node-style callback called with the error, if any, and UnbindDeviceFromGatewayResponse
+                         * @returns {undefined}
+                         * @variation 1
+                         */
+                        Object.defineProperty(DeviceManager.prototype.unbindDeviceFromGateway = function unbindDeviceFromGateway(request, callback) {
+                            return this.rpcCall(unbindDeviceFromGateway, $root.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest, $root.google.cloud.iot.v1.UnbindDeviceFromGatewayResponse, request, callback);
+                        }, "name", { value: "UnbindDeviceFromGateway" });
+    
+                        /**
+                         * Calls UnbindDeviceFromGateway.
+                         * @function unbindDeviceFromGateway
+                         * @memberof google.cloud.iot.v1.DeviceManager
+                         * @instance
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest} request UnbindDeviceFromGatewayRequest message or plain object
+                         * @returns {Promise<google.cloud.iot.v1.UnbindDeviceFromGatewayResponse>} Promise
+                         * @variation 2
+                         */
+    
+                        return DeviceManager;
+                    })();
+    
+                    v1.CreateDeviceRegistryRequest = (function() {
+    
+                        /**
+                         * Properties of a CreateDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface ICreateDeviceRegistryRequest
+                         * @property {string|null} [parent] CreateDeviceRegistryRequest parent
+                         * @property {google.cloud.iot.v1.IDeviceRegistry|null} [deviceRegistry] CreateDeviceRegistryRequest deviceRegistry
+                         */
+    
+                        /**
+                         * Constructs a new CreateDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a CreateDeviceRegistryRequest.
+                         * @implements ICreateDeviceRegistryRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.ICreateDeviceRegistryRequest=} [properties] Properties to set
+                         */
+                        function CreateDeviceRegistryRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * CreateDeviceRegistryRequest parent.
+                         * @member {string} parent
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @instance
+                         */
+                        CreateDeviceRegistryRequest.prototype.parent = "";
+    
+                        /**
+                         * CreateDeviceRegistryRequest deviceRegistry.
+                         * @member {google.cloud.iot.v1.IDeviceRegistry|null|undefined} deviceRegistry
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @instance
+                         */
+                        CreateDeviceRegistryRequest.prototype.deviceRegistry = null;
+    
+                        /**
+                         * Creates a new CreateDeviceRegistryRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ICreateDeviceRegistryRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.CreateDeviceRegistryRequest} CreateDeviceRegistryRequest instance
+                         */
+                        CreateDeviceRegistryRequest.create = function create(properties) {
+                            return new CreateDeviceRegistryRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified CreateDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRegistryRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ICreateDeviceRegistryRequest} message CreateDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        CreateDeviceRegistryRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.parent != null && Object.hasOwnProperty.call(message, "parent"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.parent);
+                            if (message.deviceRegistry != null && Object.hasOwnProperty.call(message, "deviceRegistry"))
+                                $root.google.cloud.iot.v1.DeviceRegistry.encode(message.deviceRegistry, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified CreateDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRegistryRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ICreateDeviceRegistryRequest} message CreateDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        CreateDeviceRegistryRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a CreateDeviceRegistryRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.CreateDeviceRegistryRequest} CreateDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        CreateDeviceRegistryRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.CreateDeviceRegistryRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.parent = reader.string();
+                                    break;
+                                case 2:
+                                    message.deviceRegistry = $root.google.cloud.iot.v1.DeviceRegistry.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a CreateDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.CreateDeviceRegistryRequest} CreateDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        CreateDeviceRegistryRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a CreateDeviceRegistryRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        CreateDeviceRegistryRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                if (!$util.isString(message.parent))
+                                    return "parent: string expected";
+                            if (message.deviceRegistry != null && message.hasOwnProperty("deviceRegistry")) {
+                                var error = $root.google.cloud.iot.v1.DeviceRegistry.verify(message.deviceRegistry);
+                                if (error)
+                                    return "deviceRegistry." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a CreateDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.CreateDeviceRegistryRequest} CreateDeviceRegistryRequest
+                         */
+                        CreateDeviceRegistryRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.CreateDeviceRegistryRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.CreateDeviceRegistryRequest();
+                            if (object.parent != null)
+                                message.parent = String(object.parent);
+                            if (object.deviceRegistry != null) {
+                                if (typeof object.deviceRegistry !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.CreateDeviceRegistryRequest.deviceRegistry: object expected");
+                                message.deviceRegistry = $root.google.cloud.iot.v1.DeviceRegistry.fromObject(object.deviceRegistry);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a CreateDeviceRegistryRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.CreateDeviceRegistryRequest} message CreateDeviceRegistryRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        CreateDeviceRegistryRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.parent = "";
+                                object.deviceRegistry = null;
+                            }
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                object.parent = message.parent;
+                            if (message.deviceRegistry != null && message.hasOwnProperty("deviceRegistry"))
+                                object.deviceRegistry = $root.google.cloud.iot.v1.DeviceRegistry.toObject(message.deviceRegistry, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this CreateDeviceRegistryRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.CreateDeviceRegistryRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        CreateDeviceRegistryRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return CreateDeviceRegistryRequest;
+                    })();
+    
+                    v1.GetDeviceRegistryRequest = (function() {
+    
+                        /**
+                         * Properties of a GetDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IGetDeviceRegistryRequest
+                         * @property {string|null} [name] GetDeviceRegistryRequest name
+                         */
+    
+                        /**
+                         * Constructs a new GetDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a GetDeviceRegistryRequest.
+                         * @implements IGetDeviceRegistryRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IGetDeviceRegistryRequest=} [properties] Properties to set
+                         */
+                        function GetDeviceRegistryRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * GetDeviceRegistryRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @instance
+                         */
+                        GetDeviceRegistryRequest.prototype.name = "";
+    
+                        /**
+                         * Creates a new GetDeviceRegistryRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IGetDeviceRegistryRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.GetDeviceRegistryRequest} GetDeviceRegistryRequest instance
+                         */
+                        GetDeviceRegistryRequest.create = function create(properties) {
+                            return new GetDeviceRegistryRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified GetDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRegistryRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IGetDeviceRegistryRequest} message GetDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GetDeviceRegistryRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified GetDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRegistryRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IGetDeviceRegistryRequest} message GetDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GetDeviceRegistryRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a GetDeviceRegistryRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.GetDeviceRegistryRequest} GetDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GetDeviceRegistryRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.GetDeviceRegistryRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a GetDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.GetDeviceRegistryRequest} GetDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GetDeviceRegistryRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a GetDeviceRegistryRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        GetDeviceRegistryRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a GetDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.GetDeviceRegistryRequest} GetDeviceRegistryRequest
+                         */
+                        GetDeviceRegistryRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.GetDeviceRegistryRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.GetDeviceRegistryRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a GetDeviceRegistryRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.GetDeviceRegistryRequest} message GetDeviceRegistryRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        GetDeviceRegistryRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults)
+                                object.name = "";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this GetDeviceRegistryRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.GetDeviceRegistryRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        GetDeviceRegistryRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return GetDeviceRegistryRequest;
+                    })();
+    
+                    v1.DeleteDeviceRegistryRequest = (function() {
+    
+                        /**
+                         * Properties of a DeleteDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IDeleteDeviceRegistryRequest
+                         * @property {string|null} [name] DeleteDeviceRegistryRequest name
+                         */
+    
+                        /**
+                         * Constructs a new DeleteDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a DeleteDeviceRegistryRequest.
+                         * @implements IDeleteDeviceRegistryRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRegistryRequest=} [properties] Properties to set
+                         */
+                        function DeleteDeviceRegistryRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * DeleteDeviceRegistryRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @instance
+                         */
+                        DeleteDeviceRegistryRequest.prototype.name = "";
+    
+                        /**
+                         * Creates a new DeleteDeviceRegistryRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRegistryRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRegistryRequest} DeleteDeviceRegistryRequest instance
+                         */
+                        DeleteDeviceRegistryRequest.create = function create(properties) {
+                            return new DeleteDeviceRegistryRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified DeleteDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRegistryRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRegistryRequest} message DeleteDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeleteDeviceRegistryRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified DeleteDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRegistryRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRegistryRequest} message DeleteDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeleteDeviceRegistryRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a DeleteDeviceRegistryRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRegistryRequest} DeleteDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeleteDeviceRegistryRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.DeleteDeviceRegistryRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a DeleteDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRegistryRequest} DeleteDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeleteDeviceRegistryRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a DeleteDeviceRegistryRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        DeleteDeviceRegistryRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a DeleteDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRegistryRequest} DeleteDeviceRegistryRequest
+                         */
+                        DeleteDeviceRegistryRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.DeleteDeviceRegistryRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.DeleteDeviceRegistryRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a DeleteDeviceRegistryRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.DeleteDeviceRegistryRequest} message DeleteDeviceRegistryRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        DeleteDeviceRegistryRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults)
+                                object.name = "";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this DeleteDeviceRegistryRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRegistryRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        DeleteDeviceRegistryRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return DeleteDeviceRegistryRequest;
+                    })();
+    
+                    v1.UpdateDeviceRegistryRequest = (function() {
+    
+                        /**
+                         * Properties of an UpdateDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IUpdateDeviceRegistryRequest
+                         * @property {google.cloud.iot.v1.IDeviceRegistry|null} [deviceRegistry] UpdateDeviceRegistryRequest deviceRegistry
+                         * @property {google.protobuf.IFieldMask|null} [updateMask] UpdateDeviceRegistryRequest updateMask
+                         */
+    
+                        /**
+                         * Constructs a new UpdateDeviceRegistryRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents an UpdateDeviceRegistryRequest.
+                         * @implements IUpdateDeviceRegistryRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRegistryRequest=} [properties] Properties to set
+                         */
+                        function UpdateDeviceRegistryRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * UpdateDeviceRegistryRequest deviceRegistry.
+                         * @member {google.cloud.iot.v1.IDeviceRegistry|null|undefined} deviceRegistry
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @instance
+                         */
+                        UpdateDeviceRegistryRequest.prototype.deviceRegistry = null;
+    
+                        /**
+                         * UpdateDeviceRegistryRequest updateMask.
+                         * @member {google.protobuf.IFieldMask|null|undefined} updateMask
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @instance
+                         */
+                        UpdateDeviceRegistryRequest.prototype.updateMask = null;
+    
+                        /**
+                         * Creates a new UpdateDeviceRegistryRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRegistryRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRegistryRequest} UpdateDeviceRegistryRequest instance
+                         */
+                        UpdateDeviceRegistryRequest.create = function create(properties) {
+                            return new UpdateDeviceRegistryRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified UpdateDeviceRegistryRequest message. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRegistryRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRegistryRequest} message UpdateDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UpdateDeviceRegistryRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.deviceRegistry != null && Object.hasOwnProperty.call(message, "deviceRegistry"))
+                                $root.google.cloud.iot.v1.DeviceRegistry.encode(message.deviceRegistry, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                            if (message.updateMask != null && Object.hasOwnProperty.call(message, "updateMask"))
+                                $root.google.protobuf.FieldMask.encode(message.updateMask, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified UpdateDeviceRegistryRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRegistryRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRegistryRequest} message UpdateDeviceRegistryRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UpdateDeviceRegistryRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes an UpdateDeviceRegistryRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRegistryRequest} UpdateDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UpdateDeviceRegistryRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.UpdateDeviceRegistryRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.deviceRegistry = $root.google.cloud.iot.v1.DeviceRegistry.decode(reader, reader.uint32());
+                                    break;
+                                case 2:
+                                    message.updateMask = $root.google.protobuf.FieldMask.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes an UpdateDeviceRegistryRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRegistryRequest} UpdateDeviceRegistryRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UpdateDeviceRegistryRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies an UpdateDeviceRegistryRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        UpdateDeviceRegistryRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.deviceRegistry != null && message.hasOwnProperty("deviceRegistry")) {
+                                var error = $root.google.cloud.iot.v1.DeviceRegistry.verify(message.deviceRegistry);
+                                if (error)
+                                    return "deviceRegistry." + error;
+                            }
+                            if (message.updateMask != null && message.hasOwnProperty("updateMask")) {
+                                var error = $root.google.protobuf.FieldMask.verify(message.updateMask);
+                                if (error)
+                                    return "updateMask." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates an UpdateDeviceRegistryRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRegistryRequest} UpdateDeviceRegistryRequest
+                         */
+                        UpdateDeviceRegistryRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.UpdateDeviceRegistryRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.UpdateDeviceRegistryRequest();
+                            if (object.deviceRegistry != null) {
+                                if (typeof object.deviceRegistry !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.UpdateDeviceRegistryRequest.deviceRegistry: object expected");
+                                message.deviceRegistry = $root.google.cloud.iot.v1.DeviceRegistry.fromObject(object.deviceRegistry);
+                            }
+                            if (object.updateMask != null) {
+                                if (typeof object.updateMask !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.UpdateDeviceRegistryRequest.updateMask: object expected");
+                                message.updateMask = $root.google.protobuf.FieldMask.fromObject(object.updateMask);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from an UpdateDeviceRegistryRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.UpdateDeviceRegistryRequest} message UpdateDeviceRegistryRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        UpdateDeviceRegistryRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.deviceRegistry = null;
+                                object.updateMask = null;
+                            }
+                            if (message.deviceRegistry != null && message.hasOwnProperty("deviceRegistry"))
+                                object.deviceRegistry = $root.google.cloud.iot.v1.DeviceRegistry.toObject(message.deviceRegistry, options);
+                            if (message.updateMask != null && message.hasOwnProperty("updateMask"))
+                                object.updateMask = $root.google.protobuf.FieldMask.toObject(message.updateMask, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this UpdateDeviceRegistryRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRegistryRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        UpdateDeviceRegistryRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return UpdateDeviceRegistryRequest;
+                    })();
+    
+                    v1.ListDeviceRegistriesRequest = (function() {
+    
+                        /**
+                         * Properties of a ListDeviceRegistriesRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDeviceRegistriesRequest
+                         * @property {string|null} [parent] ListDeviceRegistriesRequest parent
+                         * @property {number|null} [pageSize] ListDeviceRegistriesRequest pageSize
+                         * @property {string|null} [pageToken] ListDeviceRegistriesRequest pageToken
+                         */
+    
+                        /**
+                         * Constructs a new ListDeviceRegistriesRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDeviceRegistriesRequest.
+                         * @implements IListDeviceRegistriesRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesRequest=} [properties] Properties to set
+                         */
+                        function ListDeviceRegistriesRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDeviceRegistriesRequest parent.
+                         * @member {string} parent
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @instance
+                         */
+                        ListDeviceRegistriesRequest.prototype.parent = "";
+    
+                        /**
+                         * ListDeviceRegistriesRequest pageSize.
+                         * @member {number} pageSize
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @instance
+                         */
+                        ListDeviceRegistriesRequest.prototype.pageSize = 0;
+    
+                        /**
+                         * ListDeviceRegistriesRequest pageToken.
+                         * @member {string} pageToken
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @instance
+                         */
+                        ListDeviceRegistriesRequest.prototype.pageToken = "";
+    
+                        /**
+                         * Creates a new ListDeviceRegistriesRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesRequest} ListDeviceRegistriesRequest instance
+                         */
+                        ListDeviceRegistriesRequest.create = function create(properties) {
+                            return new ListDeviceRegistriesRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceRegistriesRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesRequest} message ListDeviceRegistriesRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceRegistriesRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.parent != null && Object.hasOwnProperty.call(message, "parent"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.parent);
+                            if (message.pageSize != null && Object.hasOwnProperty.call(message, "pageSize"))
+                                writer.uint32(/* id 2, wireType 0 =*/16).int32(message.pageSize);
+                            if (message.pageToken != null && Object.hasOwnProperty.call(message, "pageToken"))
+                                writer.uint32(/* id 3, wireType 2 =*/26).string(message.pageToken);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceRegistriesRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesRequest} message ListDeviceRegistriesRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceRegistriesRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceRegistriesRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesRequest} ListDeviceRegistriesRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceRegistriesRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDeviceRegistriesRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.parent = reader.string();
+                                    break;
+                                case 2:
+                                    message.pageSize = reader.int32();
+                                    break;
+                                case 3:
+                                    message.pageToken = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceRegistriesRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesRequest} ListDeviceRegistriesRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceRegistriesRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDeviceRegistriesRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDeviceRegistriesRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                if (!$util.isString(message.parent))
+                                    return "parent: string expected";
+                            if (message.pageSize != null && message.hasOwnProperty("pageSize"))
+                                if (!$util.isInteger(message.pageSize))
+                                    return "pageSize: integer expected";
+                            if (message.pageToken != null && message.hasOwnProperty("pageToken"))
+                                if (!$util.isString(message.pageToken))
+                                    return "pageToken: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDeviceRegistriesRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesRequest} ListDeviceRegistriesRequest
+                         */
+                        ListDeviceRegistriesRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDeviceRegistriesRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDeviceRegistriesRequest();
+                            if (object.parent != null)
+                                message.parent = String(object.parent);
+                            if (object.pageSize != null)
+                                message.pageSize = object.pageSize | 0;
+                            if (object.pageToken != null)
+                                message.pageToken = String(object.pageToken);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDeviceRegistriesRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDeviceRegistriesRequest} message ListDeviceRegistriesRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDeviceRegistriesRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.parent = "";
+                                object.pageSize = 0;
+                                object.pageToken = "";
+                            }
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                object.parent = message.parent;
+                            if (message.pageSize != null && message.hasOwnProperty("pageSize"))
+                                object.pageSize = message.pageSize;
+                            if (message.pageToken != null && message.hasOwnProperty("pageToken"))
+                                object.pageToken = message.pageToken;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDeviceRegistriesRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDeviceRegistriesRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDeviceRegistriesRequest;
+                    })();
+    
+                    v1.ListDeviceRegistriesResponse = (function() {
+    
+                        /**
+                         * Properties of a ListDeviceRegistriesResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDeviceRegistriesResponse
+                         * @property {Array.<google.cloud.iot.v1.IDeviceRegistry>|null} [deviceRegistries] ListDeviceRegistriesResponse deviceRegistries
+                         * @property {string|null} [nextPageToken] ListDeviceRegistriesResponse nextPageToken
+                         */
+    
+                        /**
+                         * Constructs a new ListDeviceRegistriesResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDeviceRegistriesResponse.
+                         * @implements IListDeviceRegistriesResponse
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesResponse=} [properties] Properties to set
+                         */
+                        function ListDeviceRegistriesResponse(properties) {
+                            this.deviceRegistries = [];
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDeviceRegistriesResponse deviceRegistries.
+                         * @member {Array.<google.cloud.iot.v1.IDeviceRegistry>} deviceRegistries
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @instance
+                         */
+                        ListDeviceRegistriesResponse.prototype.deviceRegistries = $util.emptyArray;
+    
+                        /**
+                         * ListDeviceRegistriesResponse nextPageToken.
+                         * @member {string} nextPageToken
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @instance
+                         */
+                        ListDeviceRegistriesResponse.prototype.nextPageToken = "";
+    
+                        /**
+                         * Creates a new ListDeviceRegistriesResponse instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesResponse=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesResponse} ListDeviceRegistriesResponse instance
+                         */
+                        ListDeviceRegistriesResponse.create = function create(properties) {
+                            return new ListDeviceRegistriesResponse(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceRegistriesResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesResponse.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesResponse} message ListDeviceRegistriesResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceRegistriesResponse.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.deviceRegistries != null && message.deviceRegistries.length)
+                                for (var i = 0; i < message.deviceRegistries.length; ++i)
+                                    $root.google.cloud.iot.v1.DeviceRegistry.encode(message.deviceRegistries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                            if (message.nextPageToken != null && Object.hasOwnProperty.call(message, "nextPageToken"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.nextPageToken);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceRegistriesResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceRegistriesResponse.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceRegistriesResponse} message ListDeviceRegistriesResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceRegistriesResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceRegistriesResponse message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesResponse} ListDeviceRegistriesResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceRegistriesResponse.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDeviceRegistriesResponse();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    if (!(message.deviceRegistries && message.deviceRegistries.length))
+                                        message.deviceRegistries = [];
+                                    message.deviceRegistries.push($root.google.cloud.iot.v1.DeviceRegistry.decode(reader, reader.uint32()));
+                                    break;
+                                case 2:
+                                    message.nextPageToken = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceRegistriesResponse message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesResponse} ListDeviceRegistriesResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceRegistriesResponse.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDeviceRegistriesResponse message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDeviceRegistriesResponse.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.deviceRegistries != null && message.hasOwnProperty("deviceRegistries")) {
+                                if (!Array.isArray(message.deviceRegistries))
+                                    return "deviceRegistries: array expected";
+                                for (var i = 0; i < message.deviceRegistries.length; ++i) {
+                                    var error = $root.google.cloud.iot.v1.DeviceRegistry.verify(message.deviceRegistries[i]);
+                                    if (error)
+                                        return "deviceRegistries." + error;
+                                }
+                            }
+                            if (message.nextPageToken != null && message.hasOwnProperty("nextPageToken"))
+                                if (!$util.isString(message.nextPageToken))
+                                    return "nextPageToken: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDeviceRegistriesResponse message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDeviceRegistriesResponse} ListDeviceRegistriesResponse
+                         */
+                        ListDeviceRegistriesResponse.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDeviceRegistriesResponse)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDeviceRegistriesResponse();
+                            if (object.deviceRegistries) {
+                                if (!Array.isArray(object.deviceRegistries))
+                                    throw TypeError(".google.cloud.iot.v1.ListDeviceRegistriesResponse.deviceRegistries: array expected");
+                                message.deviceRegistries = [];
+                                for (var i = 0; i < object.deviceRegistries.length; ++i) {
+                                    if (typeof object.deviceRegistries[i] !== "object")
+                                        throw TypeError(".google.cloud.iot.v1.ListDeviceRegistriesResponse.deviceRegistries: object expected");
+                                    message.deviceRegistries[i] = $root.google.cloud.iot.v1.DeviceRegistry.fromObject(object.deviceRegistries[i]);
+                                }
+                            }
+                            if (object.nextPageToken != null)
+                                message.nextPageToken = String(object.nextPageToken);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDeviceRegistriesResponse message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDeviceRegistriesResponse} message ListDeviceRegistriesResponse
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDeviceRegistriesResponse.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.arrays || options.defaults)
+                                object.deviceRegistries = [];
+                            if (options.defaults)
+                                object.nextPageToken = "";
+                            if (message.deviceRegistries && message.deviceRegistries.length) {
+                                object.deviceRegistries = [];
+                                for (var j = 0; j < message.deviceRegistries.length; ++j)
+                                    object.deviceRegistries[j] = $root.google.cloud.iot.v1.DeviceRegistry.toObject(message.deviceRegistries[j], options);
+                            }
+                            if (message.nextPageToken != null && message.hasOwnProperty("nextPageToken"))
+                                object.nextPageToken = message.nextPageToken;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDeviceRegistriesResponse to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDeviceRegistriesResponse
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDeviceRegistriesResponse.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDeviceRegistriesResponse;
+                    })();
+    
+                    v1.CreateDeviceRequest = (function() {
+    
+                        /**
+                         * Properties of a CreateDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface ICreateDeviceRequest
+                         * @property {string|null} [parent] CreateDeviceRequest parent
+                         * @property {google.cloud.iot.v1.IDevice|null} [device] CreateDeviceRequest device
+                         */
+    
+                        /**
+                         * Constructs a new CreateDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a CreateDeviceRequest.
+                         * @implements ICreateDeviceRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.ICreateDeviceRequest=} [properties] Properties to set
+                         */
+                        function CreateDeviceRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * CreateDeviceRequest parent.
+                         * @member {string} parent
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @instance
+                         */
+                        CreateDeviceRequest.prototype.parent = "";
+    
+                        /**
+                         * CreateDeviceRequest device.
+                         * @member {google.cloud.iot.v1.IDevice|null|undefined} device
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @instance
+                         */
+                        CreateDeviceRequest.prototype.device = null;
+    
+                        /**
+                         * Creates a new CreateDeviceRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ICreateDeviceRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.CreateDeviceRequest} CreateDeviceRequest instance
+                         */
+                        CreateDeviceRequest.create = function create(properties) {
+                            return new CreateDeviceRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified CreateDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ICreateDeviceRequest} message CreateDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        CreateDeviceRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.parent != null && Object.hasOwnProperty.call(message, "parent"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.parent);
+                            if (message.device != null && Object.hasOwnProperty.call(message, "device"))
+                                $root.google.cloud.iot.v1.Device.encode(message.device, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified CreateDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.CreateDeviceRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ICreateDeviceRequest} message CreateDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        CreateDeviceRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a CreateDeviceRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.CreateDeviceRequest} CreateDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        CreateDeviceRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.CreateDeviceRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.parent = reader.string();
+                                    break;
+                                case 2:
+                                    message.device = $root.google.cloud.iot.v1.Device.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a CreateDeviceRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.CreateDeviceRequest} CreateDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        CreateDeviceRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a CreateDeviceRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        CreateDeviceRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                if (!$util.isString(message.parent))
+                                    return "parent: string expected";
+                            if (message.device != null && message.hasOwnProperty("device")) {
+                                var error = $root.google.cloud.iot.v1.Device.verify(message.device);
+                                if (error)
+                                    return "device." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a CreateDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.CreateDeviceRequest} CreateDeviceRequest
+                         */
+                        CreateDeviceRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.CreateDeviceRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.CreateDeviceRequest();
+                            if (object.parent != null)
+                                message.parent = String(object.parent);
+                            if (object.device != null) {
+                                if (typeof object.device !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.CreateDeviceRequest.device: object expected");
+                                message.device = $root.google.cloud.iot.v1.Device.fromObject(object.device);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a CreateDeviceRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.CreateDeviceRequest} message CreateDeviceRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        CreateDeviceRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.parent = "";
+                                object.device = null;
+                            }
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                object.parent = message.parent;
+                            if (message.device != null && message.hasOwnProperty("device"))
+                                object.device = $root.google.cloud.iot.v1.Device.toObject(message.device, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this CreateDeviceRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.CreateDeviceRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        CreateDeviceRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return CreateDeviceRequest;
+                    })();
+    
+                    v1.GetDeviceRequest = (function() {
+    
+                        /**
+                         * Properties of a GetDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IGetDeviceRequest
+                         * @property {string|null} [name] GetDeviceRequest name
+                         * @property {google.protobuf.IFieldMask|null} [fieldMask] GetDeviceRequest fieldMask
+                         */
+    
+                        /**
+                         * Constructs a new GetDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a GetDeviceRequest.
+                         * @implements IGetDeviceRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IGetDeviceRequest=} [properties] Properties to set
+                         */
+                        function GetDeviceRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * GetDeviceRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @instance
+                         */
+                        GetDeviceRequest.prototype.name = "";
+    
+                        /**
+                         * GetDeviceRequest fieldMask.
+                         * @member {google.protobuf.IFieldMask|null|undefined} fieldMask
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @instance
+                         */
+                        GetDeviceRequest.prototype.fieldMask = null;
+    
+                        /**
+                         * Creates a new GetDeviceRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IGetDeviceRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.GetDeviceRequest} GetDeviceRequest instance
+                         */
+                        GetDeviceRequest.create = function create(properties) {
+                            return new GetDeviceRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified GetDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IGetDeviceRequest} message GetDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GetDeviceRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            if (message.fieldMask != null && Object.hasOwnProperty.call(message, "fieldMask"))
+                                $root.google.protobuf.FieldMask.encode(message.fieldMask, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified GetDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GetDeviceRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IGetDeviceRequest} message GetDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GetDeviceRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a GetDeviceRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.GetDeviceRequest} GetDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GetDeviceRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.GetDeviceRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                case 2:
+                                    message.fieldMask = $root.google.protobuf.FieldMask.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a GetDeviceRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.GetDeviceRequest} GetDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GetDeviceRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a GetDeviceRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        GetDeviceRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            if (message.fieldMask != null && message.hasOwnProperty("fieldMask")) {
+                                var error = $root.google.protobuf.FieldMask.verify(message.fieldMask);
+                                if (error)
+                                    return "fieldMask." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a GetDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.GetDeviceRequest} GetDeviceRequest
+                         */
+                        GetDeviceRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.GetDeviceRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.GetDeviceRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            if (object.fieldMask != null) {
+                                if (typeof object.fieldMask !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.GetDeviceRequest.fieldMask: object expected");
+                                message.fieldMask = $root.google.protobuf.FieldMask.fromObject(object.fieldMask);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a GetDeviceRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.GetDeviceRequest} message GetDeviceRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        GetDeviceRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.name = "";
+                                object.fieldMask = null;
+                            }
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            if (message.fieldMask != null && message.hasOwnProperty("fieldMask"))
+                                object.fieldMask = $root.google.protobuf.FieldMask.toObject(message.fieldMask, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this GetDeviceRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.GetDeviceRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        GetDeviceRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return GetDeviceRequest;
+                    })();
+    
+                    v1.UpdateDeviceRequest = (function() {
+    
+                        /**
+                         * Properties of an UpdateDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IUpdateDeviceRequest
+                         * @property {google.cloud.iot.v1.IDevice|null} [device] UpdateDeviceRequest device
+                         * @property {google.protobuf.IFieldMask|null} [updateMask] UpdateDeviceRequest updateMask
+                         */
+    
+                        /**
+                         * Constructs a new UpdateDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents an UpdateDeviceRequest.
+                         * @implements IUpdateDeviceRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRequest=} [properties] Properties to set
+                         */
+                        function UpdateDeviceRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * UpdateDeviceRequest device.
+                         * @member {google.cloud.iot.v1.IDevice|null|undefined} device
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @instance
+                         */
+                        UpdateDeviceRequest.prototype.device = null;
+    
+                        /**
+                         * UpdateDeviceRequest updateMask.
+                         * @member {google.protobuf.IFieldMask|null|undefined} updateMask
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @instance
+                         */
+                        UpdateDeviceRequest.prototype.updateMask = null;
+    
+                        /**
+                         * Creates a new UpdateDeviceRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRequest} UpdateDeviceRequest instance
+                         */
+                        UpdateDeviceRequest.create = function create(properties) {
+                            return new UpdateDeviceRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified UpdateDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRequest} message UpdateDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UpdateDeviceRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.device != null && Object.hasOwnProperty.call(message, "device"))
+                                $root.google.cloud.iot.v1.Device.encode(message.device, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                            if (message.updateMask != null && Object.hasOwnProperty.call(message, "updateMask"))
+                                $root.google.protobuf.FieldMask.encode(message.updateMask, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified UpdateDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UpdateDeviceRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUpdateDeviceRequest} message UpdateDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UpdateDeviceRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes an UpdateDeviceRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRequest} UpdateDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UpdateDeviceRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.UpdateDeviceRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 2:
+                                    message.device = $root.google.cloud.iot.v1.Device.decode(reader, reader.uint32());
+                                    break;
+                                case 3:
+                                    message.updateMask = $root.google.protobuf.FieldMask.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes an UpdateDeviceRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRequest} UpdateDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UpdateDeviceRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies an UpdateDeviceRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        UpdateDeviceRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.device != null && message.hasOwnProperty("device")) {
+                                var error = $root.google.cloud.iot.v1.Device.verify(message.device);
+                                if (error)
+                                    return "device." + error;
+                            }
+                            if (message.updateMask != null && message.hasOwnProperty("updateMask")) {
+                                var error = $root.google.protobuf.FieldMask.verify(message.updateMask);
+                                if (error)
+                                    return "updateMask." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates an UpdateDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.UpdateDeviceRequest} UpdateDeviceRequest
+                         */
+                        UpdateDeviceRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.UpdateDeviceRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.UpdateDeviceRequest();
+                            if (object.device != null) {
+                                if (typeof object.device !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.UpdateDeviceRequest.device: object expected");
+                                message.device = $root.google.cloud.iot.v1.Device.fromObject(object.device);
+                            }
+                            if (object.updateMask != null) {
+                                if (typeof object.updateMask !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.UpdateDeviceRequest.updateMask: object expected");
+                                message.updateMask = $root.google.protobuf.FieldMask.fromObject(object.updateMask);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from an UpdateDeviceRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.UpdateDeviceRequest} message UpdateDeviceRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        UpdateDeviceRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.device = null;
+                                object.updateMask = null;
+                            }
+                            if (message.device != null && message.hasOwnProperty("device"))
+                                object.device = $root.google.cloud.iot.v1.Device.toObject(message.device, options);
+                            if (message.updateMask != null && message.hasOwnProperty("updateMask"))
+                                object.updateMask = $root.google.protobuf.FieldMask.toObject(message.updateMask, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this UpdateDeviceRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.UpdateDeviceRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        UpdateDeviceRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return UpdateDeviceRequest;
+                    })();
+    
+                    v1.DeleteDeviceRequest = (function() {
+    
+                        /**
+                         * Properties of a DeleteDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IDeleteDeviceRequest
+                         * @property {string|null} [name] DeleteDeviceRequest name
+                         */
+    
+                        /**
+                         * Constructs a new DeleteDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a DeleteDeviceRequest.
+                         * @implements IDeleteDeviceRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRequest=} [properties] Properties to set
+                         */
+                        function DeleteDeviceRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * DeleteDeviceRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @instance
+                         */
+                        DeleteDeviceRequest.prototype.name = "";
+    
+                        /**
+                         * Creates a new DeleteDeviceRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRequest} DeleteDeviceRequest instance
+                         */
+                        DeleteDeviceRequest.create = function create(properties) {
+                            return new DeleteDeviceRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified DeleteDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRequest} message DeleteDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeleteDeviceRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified DeleteDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeleteDeviceRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeleteDeviceRequest} message DeleteDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeleteDeviceRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a DeleteDeviceRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRequest} DeleteDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeleteDeviceRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.DeleteDeviceRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a DeleteDeviceRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRequest} DeleteDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeleteDeviceRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a DeleteDeviceRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        DeleteDeviceRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a DeleteDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.DeleteDeviceRequest} DeleteDeviceRequest
+                         */
+                        DeleteDeviceRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.DeleteDeviceRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.DeleteDeviceRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a DeleteDeviceRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.DeleteDeviceRequest} message DeleteDeviceRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        DeleteDeviceRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults)
+                                object.name = "";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this DeleteDeviceRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.DeleteDeviceRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        DeleteDeviceRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return DeleteDeviceRequest;
+                    })();
+    
+                    v1.ListDevicesRequest = (function() {
+    
+                        /**
+                         * Properties of a ListDevicesRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDevicesRequest
+                         * @property {string|null} [parent] ListDevicesRequest parent
+                         * @property {Array.<number|Long>|null} [deviceNumIds] ListDevicesRequest deviceNumIds
+                         * @property {Array.<string>|null} [deviceIds] ListDevicesRequest deviceIds
+                         * @property {google.protobuf.IFieldMask|null} [fieldMask] ListDevicesRequest fieldMask
+                         * @property {google.cloud.iot.v1.IGatewayListOptions|null} [gatewayListOptions] ListDevicesRequest gatewayListOptions
+                         * @property {number|null} [pageSize] ListDevicesRequest pageSize
+                         * @property {string|null} [pageToken] ListDevicesRequest pageToken
+                         */
+    
+                        /**
+                         * Constructs a new ListDevicesRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDevicesRequest.
+                         * @implements IListDevicesRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDevicesRequest=} [properties] Properties to set
+                         */
+                        function ListDevicesRequest(properties) {
+                            this.deviceNumIds = [];
+                            this.deviceIds = [];
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDevicesRequest parent.
+                         * @member {string} parent
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         */
+                        ListDevicesRequest.prototype.parent = "";
+    
+                        /**
+                         * ListDevicesRequest deviceNumIds.
+                         * @member {Array.<number|Long>} deviceNumIds
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         */
+                        ListDevicesRequest.prototype.deviceNumIds = $util.emptyArray;
+    
+                        /**
+                         * ListDevicesRequest deviceIds.
+                         * @member {Array.<string>} deviceIds
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         */
+                        ListDevicesRequest.prototype.deviceIds = $util.emptyArray;
+    
+                        /**
+                         * ListDevicesRequest fieldMask.
+                         * @member {google.protobuf.IFieldMask|null|undefined} fieldMask
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         */
+                        ListDevicesRequest.prototype.fieldMask = null;
+    
+                        /**
+                         * ListDevicesRequest gatewayListOptions.
+                         * @member {google.cloud.iot.v1.IGatewayListOptions|null|undefined} gatewayListOptions
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         */
+                        ListDevicesRequest.prototype.gatewayListOptions = null;
+    
+                        /**
+                         * ListDevicesRequest pageSize.
+                         * @member {number} pageSize
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         */
+                        ListDevicesRequest.prototype.pageSize = 0;
+    
+                        /**
+                         * ListDevicesRequest pageToken.
+                         * @member {string} pageToken
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         */
+                        ListDevicesRequest.prototype.pageToken = "";
+    
+                        /**
+                         * Creates a new ListDevicesRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDevicesRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDevicesRequest} ListDevicesRequest instance
+                         */
+                        ListDevicesRequest.create = function create(properties) {
+                            return new ListDevicesRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDevicesRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDevicesRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDevicesRequest} message ListDevicesRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDevicesRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.parent != null && Object.hasOwnProperty.call(message, "parent"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.parent);
+                            if (message.deviceNumIds != null && message.deviceNumIds.length) {
+                                writer.uint32(/* id 2, wireType 2 =*/18).fork();
+                                for (var i = 0; i < message.deviceNumIds.length; ++i)
+                                    writer.uint64(message.deviceNumIds[i]);
+                                writer.ldelim();
+                            }
+                            if (message.deviceIds != null && message.deviceIds.length)
+                                for (var i = 0; i < message.deviceIds.length; ++i)
+                                    writer.uint32(/* id 3, wireType 2 =*/26).string(message.deviceIds[i]);
+                            if (message.fieldMask != null && Object.hasOwnProperty.call(message, "fieldMask"))
+                                $root.google.protobuf.FieldMask.encode(message.fieldMask, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                            if (message.gatewayListOptions != null && Object.hasOwnProperty.call(message, "gatewayListOptions"))
+                                $root.google.cloud.iot.v1.GatewayListOptions.encode(message.gatewayListOptions, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
+                            if (message.pageSize != null && Object.hasOwnProperty.call(message, "pageSize"))
+                                writer.uint32(/* id 100, wireType 0 =*/800).int32(message.pageSize);
+                            if (message.pageToken != null && Object.hasOwnProperty.call(message, "pageToken"))
+                                writer.uint32(/* id 101, wireType 2 =*/810).string(message.pageToken);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDevicesRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDevicesRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDevicesRequest} message ListDevicesRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDevicesRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDevicesRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDevicesRequest} ListDevicesRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDevicesRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDevicesRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.parent = reader.string();
+                                    break;
+                                case 2:
+                                    if (!(message.deviceNumIds && message.deviceNumIds.length))
+                                        message.deviceNumIds = [];
+                                    if ((tag & 7) === 2) {
+                                        var end2 = reader.uint32() + reader.pos;
+                                        while (reader.pos < end2)
+                                            message.deviceNumIds.push(reader.uint64());
+                                    } else
+                                        message.deviceNumIds.push(reader.uint64());
+                                    break;
+                                case 3:
+                                    if (!(message.deviceIds && message.deviceIds.length))
+                                        message.deviceIds = [];
+                                    message.deviceIds.push(reader.string());
+                                    break;
+                                case 4:
+                                    message.fieldMask = $root.google.protobuf.FieldMask.decode(reader, reader.uint32());
+                                    break;
+                                case 6:
+                                    message.gatewayListOptions = $root.google.cloud.iot.v1.GatewayListOptions.decode(reader, reader.uint32());
+                                    break;
+                                case 100:
+                                    message.pageSize = reader.int32();
+                                    break;
+                                case 101:
+                                    message.pageToken = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDevicesRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDevicesRequest} ListDevicesRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDevicesRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDevicesRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDevicesRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                if (!$util.isString(message.parent))
+                                    return "parent: string expected";
+                            if (message.deviceNumIds != null && message.hasOwnProperty("deviceNumIds")) {
+                                if (!Array.isArray(message.deviceNumIds))
+                                    return "deviceNumIds: array expected";
+                                for (var i = 0; i < message.deviceNumIds.length; ++i)
+                                    if (!$util.isInteger(message.deviceNumIds[i]) && !(message.deviceNumIds[i] && $util.isInteger(message.deviceNumIds[i].low) && $util.isInteger(message.deviceNumIds[i].high)))
+                                        return "deviceNumIds: integer|Long[] expected";
+                            }
+                            if (message.deviceIds != null && message.hasOwnProperty("deviceIds")) {
+                                if (!Array.isArray(message.deviceIds))
+                                    return "deviceIds: array expected";
+                                for (var i = 0; i < message.deviceIds.length; ++i)
+                                    if (!$util.isString(message.deviceIds[i]))
+                                        return "deviceIds: string[] expected";
+                            }
+                            if (message.fieldMask != null && message.hasOwnProperty("fieldMask")) {
+                                var error = $root.google.protobuf.FieldMask.verify(message.fieldMask);
+                                if (error)
+                                    return "fieldMask." + error;
+                            }
+                            if (message.gatewayListOptions != null && message.hasOwnProperty("gatewayListOptions")) {
+                                var error = $root.google.cloud.iot.v1.GatewayListOptions.verify(message.gatewayListOptions);
+                                if (error)
+                                    return "gatewayListOptions." + error;
+                            }
+                            if (message.pageSize != null && message.hasOwnProperty("pageSize"))
+                                if (!$util.isInteger(message.pageSize))
+                                    return "pageSize: integer expected";
+                            if (message.pageToken != null && message.hasOwnProperty("pageToken"))
+                                if (!$util.isString(message.pageToken))
+                                    return "pageToken: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDevicesRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDevicesRequest} ListDevicesRequest
+                         */
+                        ListDevicesRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDevicesRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDevicesRequest();
+                            if (object.parent != null)
+                                message.parent = String(object.parent);
+                            if (object.deviceNumIds) {
+                                if (!Array.isArray(object.deviceNumIds))
+                                    throw TypeError(".google.cloud.iot.v1.ListDevicesRequest.deviceNumIds: array expected");
+                                message.deviceNumIds = [];
+                                for (var i = 0; i < object.deviceNumIds.length; ++i)
+                                    if ($util.Long)
+                                        (message.deviceNumIds[i] = $util.Long.fromValue(object.deviceNumIds[i])).unsigned = true;
+                                    else if (typeof object.deviceNumIds[i] === "string")
+                                        message.deviceNumIds[i] = parseInt(object.deviceNumIds[i], 10);
+                                    else if (typeof object.deviceNumIds[i] === "number")
+                                        message.deviceNumIds[i] = object.deviceNumIds[i];
+                                    else if (typeof object.deviceNumIds[i] === "object")
+                                        message.deviceNumIds[i] = new $util.LongBits(object.deviceNumIds[i].low >>> 0, object.deviceNumIds[i].high >>> 0).toNumber(true);
+                            }
+                            if (object.deviceIds) {
+                                if (!Array.isArray(object.deviceIds))
+                                    throw TypeError(".google.cloud.iot.v1.ListDevicesRequest.deviceIds: array expected");
+                                message.deviceIds = [];
+                                for (var i = 0; i < object.deviceIds.length; ++i)
+                                    message.deviceIds[i] = String(object.deviceIds[i]);
+                            }
+                            if (object.fieldMask != null) {
+                                if (typeof object.fieldMask !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.ListDevicesRequest.fieldMask: object expected");
+                                message.fieldMask = $root.google.protobuf.FieldMask.fromObject(object.fieldMask);
+                            }
+                            if (object.gatewayListOptions != null) {
+                                if (typeof object.gatewayListOptions !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.ListDevicesRequest.gatewayListOptions: object expected");
+                                message.gatewayListOptions = $root.google.cloud.iot.v1.GatewayListOptions.fromObject(object.gatewayListOptions);
+                            }
+                            if (object.pageSize != null)
+                                message.pageSize = object.pageSize | 0;
+                            if (object.pageToken != null)
+                                message.pageToken = String(object.pageToken);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDevicesRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDevicesRequest} message ListDevicesRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDevicesRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.arrays || options.defaults) {
+                                object.deviceNumIds = [];
+                                object.deviceIds = [];
+                            }
+                            if (options.defaults) {
+                                object.parent = "";
+                                object.fieldMask = null;
+                                object.gatewayListOptions = null;
+                                object.pageSize = 0;
+                                object.pageToken = "";
+                            }
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                object.parent = message.parent;
+                            if (message.deviceNumIds && message.deviceNumIds.length) {
+                                object.deviceNumIds = [];
+                                for (var j = 0; j < message.deviceNumIds.length; ++j)
+                                    if (typeof message.deviceNumIds[j] === "number")
+                                        object.deviceNumIds[j] = options.longs === String ? String(message.deviceNumIds[j]) : message.deviceNumIds[j];
+                                    else
+                                        object.deviceNumIds[j] = options.longs === String ? $util.Long.prototype.toString.call(message.deviceNumIds[j]) : options.longs === Number ? new $util.LongBits(message.deviceNumIds[j].low >>> 0, message.deviceNumIds[j].high >>> 0).toNumber(true) : message.deviceNumIds[j];
+                            }
+                            if (message.deviceIds && message.deviceIds.length) {
+                                object.deviceIds = [];
+                                for (var j = 0; j < message.deviceIds.length; ++j)
+                                    object.deviceIds[j] = message.deviceIds[j];
+                            }
+                            if (message.fieldMask != null && message.hasOwnProperty("fieldMask"))
+                                object.fieldMask = $root.google.protobuf.FieldMask.toObject(message.fieldMask, options);
+                            if (message.gatewayListOptions != null && message.hasOwnProperty("gatewayListOptions"))
+                                object.gatewayListOptions = $root.google.cloud.iot.v1.GatewayListOptions.toObject(message.gatewayListOptions, options);
+                            if (message.pageSize != null && message.hasOwnProperty("pageSize"))
+                                object.pageSize = message.pageSize;
+                            if (message.pageToken != null && message.hasOwnProperty("pageToken"))
+                                object.pageToken = message.pageToken;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDevicesRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDevicesRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDevicesRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDevicesRequest;
+                    })();
+    
+                    v1.GatewayListOptions = (function() {
+    
+                        /**
+                         * Properties of a GatewayListOptions.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IGatewayListOptions
+                         * @property {google.cloud.iot.v1.GatewayType|null} [gatewayType] GatewayListOptions gatewayType
+                         * @property {string|null} [associationsGatewayId] GatewayListOptions associationsGatewayId
+                         * @property {string|null} [associationsDeviceId] GatewayListOptions associationsDeviceId
+                         */
+    
+                        /**
+                         * Constructs a new GatewayListOptions.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a GatewayListOptions.
+                         * @implements IGatewayListOptions
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IGatewayListOptions=} [properties] Properties to set
+                         */
+                        function GatewayListOptions(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * GatewayListOptions gatewayType.
+                         * @member {google.cloud.iot.v1.GatewayType|null|undefined} gatewayType
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @instance
+                         */
+                        GatewayListOptions.prototype.gatewayType = null;
+    
+                        /**
+                         * GatewayListOptions associationsGatewayId.
+                         * @member {string|null|undefined} associationsGatewayId
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @instance
+                         */
+                        GatewayListOptions.prototype.associationsGatewayId = null;
+    
+                        /**
+                         * GatewayListOptions associationsDeviceId.
+                         * @member {string|null|undefined} associationsDeviceId
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @instance
+                         */
+                        GatewayListOptions.prototype.associationsDeviceId = null;
+    
+                        // OneOf field names bound to virtual getters and setters
+                        var $oneOfFields;
+    
+                        /**
+                         * GatewayListOptions filter.
+                         * @member {"gatewayType"|"associationsGatewayId"|"associationsDeviceId"|undefined} filter
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @instance
+                         */
+                        Object.defineProperty(GatewayListOptions.prototype, "filter", {
+                            get: $util.oneOfGetter($oneOfFields = ["gatewayType", "associationsGatewayId", "associationsDeviceId"]),
+                            set: $util.oneOfSetter($oneOfFields)
+                        });
+    
+                        /**
+                         * Creates a new GatewayListOptions instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {google.cloud.iot.v1.IGatewayListOptions=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.GatewayListOptions} GatewayListOptions instance
+                         */
+                        GatewayListOptions.create = function create(properties) {
+                            return new GatewayListOptions(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified GatewayListOptions message. Does not implicitly {@link google.cloud.iot.v1.GatewayListOptions.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {google.cloud.iot.v1.IGatewayListOptions} message GatewayListOptions message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GatewayListOptions.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.gatewayType != null && Object.hasOwnProperty.call(message, "gatewayType"))
+                                writer.uint32(/* id 1, wireType 0 =*/8).int32(message.gatewayType);
+                            if (message.associationsGatewayId != null && Object.hasOwnProperty.call(message, "associationsGatewayId"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.associationsGatewayId);
+                            if (message.associationsDeviceId != null && Object.hasOwnProperty.call(message, "associationsDeviceId"))
+                                writer.uint32(/* id 3, wireType 2 =*/26).string(message.associationsDeviceId);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified GatewayListOptions message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GatewayListOptions.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {google.cloud.iot.v1.IGatewayListOptions} message GatewayListOptions message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GatewayListOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a GatewayListOptions message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.GatewayListOptions} GatewayListOptions
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GatewayListOptions.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.GatewayListOptions();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.gatewayType = reader.int32();
+                                    break;
+                                case 2:
+                                    message.associationsGatewayId = reader.string();
+                                    break;
+                                case 3:
+                                    message.associationsDeviceId = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a GatewayListOptions message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.GatewayListOptions} GatewayListOptions
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GatewayListOptions.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a GatewayListOptions message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        GatewayListOptions.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            var properties = {};
+                            if (message.gatewayType != null && message.hasOwnProperty("gatewayType")) {
+                                properties.filter = 1;
+                                switch (message.gatewayType) {
+                                default:
+                                    return "gatewayType: enum value expected";
+                                case 0:
+                                case 1:
+                                case 2:
+                                    break;
+                                }
+                            }
+                            if (message.associationsGatewayId != null && message.hasOwnProperty("associationsGatewayId")) {
+                                if (properties.filter === 1)
+                                    return "filter: multiple values";
+                                properties.filter = 1;
+                                if (!$util.isString(message.associationsGatewayId))
+                                    return "associationsGatewayId: string expected";
+                            }
+                            if (message.associationsDeviceId != null && message.hasOwnProperty("associationsDeviceId")) {
+                                if (properties.filter === 1)
+                                    return "filter: multiple values";
+                                properties.filter = 1;
+                                if (!$util.isString(message.associationsDeviceId))
+                                    return "associationsDeviceId: string expected";
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a GatewayListOptions message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.GatewayListOptions} GatewayListOptions
+                         */
+                        GatewayListOptions.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.GatewayListOptions)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.GatewayListOptions();
+                            switch (object.gatewayType) {
+                            case "GATEWAY_TYPE_UNSPECIFIED":
+                            case 0:
+                                message.gatewayType = 0;
+                                break;
+                            case "GATEWAY":
+                            case 1:
+                                message.gatewayType = 1;
+                                break;
+                            case "NON_GATEWAY":
+                            case 2:
+                                message.gatewayType = 2;
+                                break;
+                            }
+                            if (object.associationsGatewayId != null)
+                                message.associationsGatewayId = String(object.associationsGatewayId);
+                            if (object.associationsDeviceId != null)
+                                message.associationsDeviceId = String(object.associationsDeviceId);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a GatewayListOptions message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @static
+                         * @param {google.cloud.iot.v1.GatewayListOptions} message GatewayListOptions
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        GatewayListOptions.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (message.gatewayType != null && message.hasOwnProperty("gatewayType")) {
+                                object.gatewayType = options.enums === String ? $root.google.cloud.iot.v1.GatewayType[message.gatewayType] : message.gatewayType;
+                                if (options.oneofs)
+                                    object.filter = "gatewayType";
+                            }
+                            if (message.associationsGatewayId != null && message.hasOwnProperty("associationsGatewayId")) {
+                                object.associationsGatewayId = message.associationsGatewayId;
+                                if (options.oneofs)
+                                    object.filter = "associationsGatewayId";
+                            }
+                            if (message.associationsDeviceId != null && message.hasOwnProperty("associationsDeviceId")) {
+                                object.associationsDeviceId = message.associationsDeviceId;
+                                if (options.oneofs)
+                                    object.filter = "associationsDeviceId";
+                            }
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this GatewayListOptions to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.GatewayListOptions
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        GatewayListOptions.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return GatewayListOptions;
+                    })();
+    
+                    v1.ListDevicesResponse = (function() {
+    
+                        /**
+                         * Properties of a ListDevicesResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDevicesResponse
+                         * @property {Array.<google.cloud.iot.v1.IDevice>|null} [devices] ListDevicesResponse devices
+                         * @property {string|null} [nextPageToken] ListDevicesResponse nextPageToken
+                         */
+    
+                        /**
+                         * Constructs a new ListDevicesResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDevicesResponse.
+                         * @implements IListDevicesResponse
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDevicesResponse=} [properties] Properties to set
+                         */
+                        function ListDevicesResponse(properties) {
+                            this.devices = [];
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDevicesResponse devices.
+                         * @member {Array.<google.cloud.iot.v1.IDevice>} devices
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @instance
+                         */
+                        ListDevicesResponse.prototype.devices = $util.emptyArray;
+    
+                        /**
+                         * ListDevicesResponse nextPageToken.
+                         * @member {string} nextPageToken
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @instance
+                         */
+                        ListDevicesResponse.prototype.nextPageToken = "";
+    
+                        /**
+                         * Creates a new ListDevicesResponse instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDevicesResponse=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDevicesResponse} ListDevicesResponse instance
+                         */
+                        ListDevicesResponse.create = function create(properties) {
+                            return new ListDevicesResponse(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDevicesResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDevicesResponse.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDevicesResponse} message ListDevicesResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDevicesResponse.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.devices != null && message.devices.length)
+                                for (var i = 0; i < message.devices.length; ++i)
+                                    $root.google.cloud.iot.v1.Device.encode(message.devices[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                            if (message.nextPageToken != null && Object.hasOwnProperty.call(message, "nextPageToken"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.nextPageToken);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDevicesResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDevicesResponse.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDevicesResponse} message ListDevicesResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDevicesResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDevicesResponse message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDevicesResponse} ListDevicesResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDevicesResponse.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDevicesResponse();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    if (!(message.devices && message.devices.length))
+                                        message.devices = [];
+                                    message.devices.push($root.google.cloud.iot.v1.Device.decode(reader, reader.uint32()));
+                                    break;
+                                case 2:
+                                    message.nextPageToken = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDevicesResponse message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDevicesResponse} ListDevicesResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDevicesResponse.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDevicesResponse message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDevicesResponse.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.devices != null && message.hasOwnProperty("devices")) {
+                                if (!Array.isArray(message.devices))
+                                    return "devices: array expected";
+                                for (var i = 0; i < message.devices.length; ++i) {
+                                    var error = $root.google.cloud.iot.v1.Device.verify(message.devices[i]);
+                                    if (error)
+                                        return "devices." + error;
+                                }
+                            }
+                            if (message.nextPageToken != null && message.hasOwnProperty("nextPageToken"))
+                                if (!$util.isString(message.nextPageToken))
+                                    return "nextPageToken: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDevicesResponse message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDevicesResponse} ListDevicesResponse
+                         */
+                        ListDevicesResponse.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDevicesResponse)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDevicesResponse();
+                            if (object.devices) {
+                                if (!Array.isArray(object.devices))
+                                    throw TypeError(".google.cloud.iot.v1.ListDevicesResponse.devices: array expected");
+                                message.devices = [];
+                                for (var i = 0; i < object.devices.length; ++i) {
+                                    if (typeof object.devices[i] !== "object")
+                                        throw TypeError(".google.cloud.iot.v1.ListDevicesResponse.devices: object expected");
+                                    message.devices[i] = $root.google.cloud.iot.v1.Device.fromObject(object.devices[i]);
+                                }
+                            }
+                            if (object.nextPageToken != null)
+                                message.nextPageToken = String(object.nextPageToken);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDevicesResponse message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDevicesResponse} message ListDevicesResponse
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDevicesResponse.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.arrays || options.defaults)
+                                object.devices = [];
+                            if (options.defaults)
+                                object.nextPageToken = "";
+                            if (message.devices && message.devices.length) {
+                                object.devices = [];
+                                for (var j = 0; j < message.devices.length; ++j)
+                                    object.devices[j] = $root.google.cloud.iot.v1.Device.toObject(message.devices[j], options);
+                            }
+                            if (message.nextPageToken != null && message.hasOwnProperty("nextPageToken"))
+                                object.nextPageToken = message.nextPageToken;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDevicesResponse to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDevicesResponse
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDevicesResponse.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDevicesResponse;
+                    })();
+    
+                    v1.ModifyCloudToDeviceConfigRequest = (function() {
+    
+                        /**
+                         * Properties of a ModifyCloudToDeviceConfigRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IModifyCloudToDeviceConfigRequest
+                         * @property {string|null} [name] ModifyCloudToDeviceConfigRequest name
+                         * @property {number|Long|null} [versionToUpdate] ModifyCloudToDeviceConfigRequest versionToUpdate
+                         * @property {Uint8Array|null} [binaryData] ModifyCloudToDeviceConfigRequest binaryData
+                         */
+    
+                        /**
+                         * Constructs a new ModifyCloudToDeviceConfigRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ModifyCloudToDeviceConfigRequest.
+                         * @implements IModifyCloudToDeviceConfigRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest=} [properties] Properties to set
+                         */
+                        function ModifyCloudToDeviceConfigRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ModifyCloudToDeviceConfigRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @instance
+                         */
+                        ModifyCloudToDeviceConfigRequest.prototype.name = "";
+    
+                        /**
+                         * ModifyCloudToDeviceConfigRequest versionToUpdate.
+                         * @member {number|Long} versionToUpdate
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @instance
+                         */
+                        ModifyCloudToDeviceConfigRequest.prototype.versionToUpdate = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
+    
+                        /**
+                         * ModifyCloudToDeviceConfigRequest binaryData.
+                         * @member {Uint8Array} binaryData
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @instance
+                         */
+                        ModifyCloudToDeviceConfigRequest.prototype.binaryData = $util.newBuffer([]);
+    
+                        /**
+                         * Creates a new ModifyCloudToDeviceConfigRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest} ModifyCloudToDeviceConfigRequest instance
+                         */
+                        ModifyCloudToDeviceConfigRequest.create = function create(properties) {
+                            return new ModifyCloudToDeviceConfigRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ModifyCloudToDeviceConfigRequest message. Does not implicitly {@link google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest} message ModifyCloudToDeviceConfigRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ModifyCloudToDeviceConfigRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            if (message.versionToUpdate != null && Object.hasOwnProperty.call(message, "versionToUpdate"))
+                                writer.uint32(/* id 2, wireType 0 =*/16).int64(message.versionToUpdate);
+                            if (message.binaryData != null && Object.hasOwnProperty.call(message, "binaryData"))
+                                writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.binaryData);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ModifyCloudToDeviceConfigRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest} message ModifyCloudToDeviceConfigRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ModifyCloudToDeviceConfigRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ModifyCloudToDeviceConfigRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest} ModifyCloudToDeviceConfigRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ModifyCloudToDeviceConfigRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                case 2:
+                                    message.versionToUpdate = reader.int64();
+                                    break;
+                                case 3:
+                                    message.binaryData = reader.bytes();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ModifyCloudToDeviceConfigRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest} ModifyCloudToDeviceConfigRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ModifyCloudToDeviceConfigRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ModifyCloudToDeviceConfigRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ModifyCloudToDeviceConfigRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            if (message.versionToUpdate != null && message.hasOwnProperty("versionToUpdate"))
+                                if (!$util.isInteger(message.versionToUpdate) && !(message.versionToUpdate && $util.isInteger(message.versionToUpdate.low) && $util.isInteger(message.versionToUpdate.high)))
+                                    return "versionToUpdate: integer|Long expected";
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                if (!(message.binaryData && typeof message.binaryData.length === "number" || $util.isString(message.binaryData)))
+                                    return "binaryData: buffer expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ModifyCloudToDeviceConfigRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest} ModifyCloudToDeviceConfigRequest
+                         */
+                        ModifyCloudToDeviceConfigRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            if (object.versionToUpdate != null)
+                                if ($util.Long)
+                                    (message.versionToUpdate = $util.Long.fromValue(object.versionToUpdate)).unsigned = false;
+                                else if (typeof object.versionToUpdate === "string")
+                                    message.versionToUpdate = parseInt(object.versionToUpdate, 10);
+                                else if (typeof object.versionToUpdate === "number")
+                                    message.versionToUpdate = object.versionToUpdate;
+                                else if (typeof object.versionToUpdate === "object")
+                                    message.versionToUpdate = new $util.LongBits(object.versionToUpdate.low >>> 0, object.versionToUpdate.high >>> 0).toNumber();
+                            if (object.binaryData != null)
+                                if (typeof object.binaryData === "string")
+                                    $util.base64.decode(object.binaryData, message.binaryData = $util.newBuffer($util.base64.length(object.binaryData)), 0);
+                                else if (object.binaryData.length)
+                                    message.binaryData = object.binaryData;
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ModifyCloudToDeviceConfigRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest} message ModifyCloudToDeviceConfigRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ModifyCloudToDeviceConfigRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.name = "";
+                                if ($util.Long) {
+                                    var long = new $util.Long(0, 0, false);
+                                    object.versionToUpdate = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+                                } else
+                                    object.versionToUpdate = options.longs === String ? "0" : 0;
+                                if (options.bytes === String)
+                                    object.binaryData = "";
+                                else {
+                                    object.binaryData = [];
+                                    if (options.bytes !== Array)
+                                        object.binaryData = $util.newBuffer(object.binaryData);
+                                }
+                            }
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            if (message.versionToUpdate != null && message.hasOwnProperty("versionToUpdate"))
+                                if (typeof message.versionToUpdate === "number")
+                                    object.versionToUpdate = options.longs === String ? String(message.versionToUpdate) : message.versionToUpdate;
+                                else
+                                    object.versionToUpdate = options.longs === String ? $util.Long.prototype.toString.call(message.versionToUpdate) : options.longs === Number ? new $util.LongBits(message.versionToUpdate.low >>> 0, message.versionToUpdate.high >>> 0).toNumber() : message.versionToUpdate;
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                object.binaryData = options.bytes === String ? $util.base64.encode(message.binaryData, 0, message.binaryData.length) : options.bytes === Array ? Array.prototype.slice.call(message.binaryData) : message.binaryData;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ModifyCloudToDeviceConfigRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ModifyCloudToDeviceConfigRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ModifyCloudToDeviceConfigRequest;
+                    })();
+    
+                    v1.ListDeviceConfigVersionsRequest = (function() {
+    
+                        /**
+                         * Properties of a ListDeviceConfigVersionsRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDeviceConfigVersionsRequest
+                         * @property {string|null} [name] ListDeviceConfigVersionsRequest name
+                         * @property {number|null} [numVersions] ListDeviceConfigVersionsRequest numVersions
+                         */
+    
+                        /**
+                         * Constructs a new ListDeviceConfigVersionsRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDeviceConfigVersionsRequest.
+                         * @implements IListDeviceConfigVersionsRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsRequest=} [properties] Properties to set
+                         */
+                        function ListDeviceConfigVersionsRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDeviceConfigVersionsRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @instance
+                         */
+                        ListDeviceConfigVersionsRequest.prototype.name = "";
+    
+                        /**
+                         * ListDeviceConfigVersionsRequest numVersions.
+                         * @member {number} numVersions
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @instance
+                         */
+                        ListDeviceConfigVersionsRequest.prototype.numVersions = 0;
+    
+                        /**
+                         * Creates a new ListDeviceConfigVersionsRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsRequest} ListDeviceConfigVersionsRequest instance
+                         */
+                        ListDeviceConfigVersionsRequest.create = function create(properties) {
+                            return new ListDeviceConfigVersionsRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceConfigVersionsRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsRequest} message ListDeviceConfigVersionsRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceConfigVersionsRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            if (message.numVersions != null && Object.hasOwnProperty.call(message, "numVersions"))
+                                writer.uint32(/* id 2, wireType 0 =*/16).int32(message.numVersions);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceConfigVersionsRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsRequest} message ListDeviceConfigVersionsRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceConfigVersionsRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceConfigVersionsRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsRequest} ListDeviceConfigVersionsRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceConfigVersionsRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDeviceConfigVersionsRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                case 2:
+                                    message.numVersions = reader.int32();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceConfigVersionsRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsRequest} ListDeviceConfigVersionsRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceConfigVersionsRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDeviceConfigVersionsRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDeviceConfigVersionsRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            if (message.numVersions != null && message.hasOwnProperty("numVersions"))
+                                if (!$util.isInteger(message.numVersions))
+                                    return "numVersions: integer expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDeviceConfigVersionsRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsRequest} ListDeviceConfigVersionsRequest
+                         */
+                        ListDeviceConfigVersionsRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDeviceConfigVersionsRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDeviceConfigVersionsRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            if (object.numVersions != null)
+                                message.numVersions = object.numVersions | 0;
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDeviceConfigVersionsRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDeviceConfigVersionsRequest} message ListDeviceConfigVersionsRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDeviceConfigVersionsRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.name = "";
+                                object.numVersions = 0;
+                            }
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            if (message.numVersions != null && message.hasOwnProperty("numVersions"))
+                                object.numVersions = message.numVersions;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDeviceConfigVersionsRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDeviceConfigVersionsRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDeviceConfigVersionsRequest;
+                    })();
+    
+                    v1.ListDeviceConfigVersionsResponse = (function() {
+    
+                        /**
+                         * Properties of a ListDeviceConfigVersionsResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDeviceConfigVersionsResponse
+                         * @property {Array.<google.cloud.iot.v1.IDeviceConfig>|null} [deviceConfigs] ListDeviceConfigVersionsResponse deviceConfigs
+                         */
+    
+                        /**
+                         * Constructs a new ListDeviceConfigVersionsResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDeviceConfigVersionsResponse.
+                         * @implements IListDeviceConfigVersionsResponse
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsResponse=} [properties] Properties to set
+                         */
+                        function ListDeviceConfigVersionsResponse(properties) {
+                            this.deviceConfigs = [];
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDeviceConfigVersionsResponse deviceConfigs.
+                         * @member {Array.<google.cloud.iot.v1.IDeviceConfig>} deviceConfigs
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @instance
+                         */
+                        ListDeviceConfigVersionsResponse.prototype.deviceConfigs = $util.emptyArray;
+    
+                        /**
+                         * Creates a new ListDeviceConfigVersionsResponse instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsResponse=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsResponse} ListDeviceConfigVersionsResponse instance
+                         */
+                        ListDeviceConfigVersionsResponse.create = function create(properties) {
+                            return new ListDeviceConfigVersionsResponse(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceConfigVersionsResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsResponse.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsResponse} message ListDeviceConfigVersionsResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceConfigVersionsResponse.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.deviceConfigs != null && message.deviceConfigs.length)
+                                for (var i = 0; i < message.deviceConfigs.length; ++i)
+                                    $root.google.cloud.iot.v1.DeviceConfig.encode(message.deviceConfigs[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceConfigVersionsResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceConfigVersionsResponse.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceConfigVersionsResponse} message ListDeviceConfigVersionsResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceConfigVersionsResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceConfigVersionsResponse message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsResponse} ListDeviceConfigVersionsResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceConfigVersionsResponse.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDeviceConfigVersionsResponse();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    if (!(message.deviceConfigs && message.deviceConfigs.length))
+                                        message.deviceConfigs = [];
+                                    message.deviceConfigs.push($root.google.cloud.iot.v1.DeviceConfig.decode(reader, reader.uint32()));
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceConfigVersionsResponse message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsResponse} ListDeviceConfigVersionsResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceConfigVersionsResponse.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDeviceConfigVersionsResponse message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDeviceConfigVersionsResponse.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.deviceConfigs != null && message.hasOwnProperty("deviceConfigs")) {
+                                if (!Array.isArray(message.deviceConfigs))
+                                    return "deviceConfigs: array expected";
+                                for (var i = 0; i < message.deviceConfigs.length; ++i) {
+                                    var error = $root.google.cloud.iot.v1.DeviceConfig.verify(message.deviceConfigs[i]);
+                                    if (error)
+                                        return "deviceConfigs." + error;
+                                }
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDeviceConfigVersionsResponse message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDeviceConfigVersionsResponse} ListDeviceConfigVersionsResponse
+                         */
+                        ListDeviceConfigVersionsResponse.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDeviceConfigVersionsResponse)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDeviceConfigVersionsResponse();
+                            if (object.deviceConfigs) {
+                                if (!Array.isArray(object.deviceConfigs))
+                                    throw TypeError(".google.cloud.iot.v1.ListDeviceConfigVersionsResponse.deviceConfigs: array expected");
+                                message.deviceConfigs = [];
+                                for (var i = 0; i < object.deviceConfigs.length; ++i) {
+                                    if (typeof object.deviceConfigs[i] !== "object")
+                                        throw TypeError(".google.cloud.iot.v1.ListDeviceConfigVersionsResponse.deviceConfigs: object expected");
+                                    message.deviceConfigs[i] = $root.google.cloud.iot.v1.DeviceConfig.fromObject(object.deviceConfigs[i]);
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDeviceConfigVersionsResponse message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDeviceConfigVersionsResponse} message ListDeviceConfigVersionsResponse
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDeviceConfigVersionsResponse.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.arrays || options.defaults)
+                                object.deviceConfigs = [];
+                            if (message.deviceConfigs && message.deviceConfigs.length) {
+                                object.deviceConfigs = [];
+                                for (var j = 0; j < message.deviceConfigs.length; ++j)
+                                    object.deviceConfigs[j] = $root.google.cloud.iot.v1.DeviceConfig.toObject(message.deviceConfigs[j], options);
+                            }
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDeviceConfigVersionsResponse to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDeviceConfigVersionsResponse
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDeviceConfigVersionsResponse.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDeviceConfigVersionsResponse;
+                    })();
+    
+                    v1.ListDeviceStatesRequest = (function() {
+    
+                        /**
+                         * Properties of a ListDeviceStatesRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDeviceStatesRequest
+                         * @property {string|null} [name] ListDeviceStatesRequest name
+                         * @property {number|null} [numStates] ListDeviceStatesRequest numStates
+                         */
+    
+                        /**
+                         * Constructs a new ListDeviceStatesRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDeviceStatesRequest.
+                         * @implements IListDeviceStatesRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDeviceStatesRequest=} [properties] Properties to set
+                         */
+                        function ListDeviceStatesRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDeviceStatesRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @instance
+                         */
+                        ListDeviceStatesRequest.prototype.name = "";
+    
+                        /**
+                         * ListDeviceStatesRequest numStates.
+                         * @member {number} numStates
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @instance
+                         */
+                        ListDeviceStatesRequest.prototype.numStates = 0;
+    
+                        /**
+                         * Creates a new ListDeviceStatesRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceStatesRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesRequest} ListDeviceStatesRequest instance
+                         */
+                        ListDeviceStatesRequest.create = function create(properties) {
+                            return new ListDeviceStatesRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceStatesRequest message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceStatesRequest} message ListDeviceStatesRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceStatesRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            if (message.numStates != null && Object.hasOwnProperty.call(message, "numStates"))
+                                writer.uint32(/* id 2, wireType 0 =*/16).int32(message.numStates);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceStatesRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceStatesRequest} message ListDeviceStatesRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceStatesRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceStatesRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesRequest} ListDeviceStatesRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceStatesRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDeviceStatesRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                case 2:
+                                    message.numStates = reader.int32();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceStatesRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesRequest} ListDeviceStatesRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceStatesRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDeviceStatesRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDeviceStatesRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            if (message.numStates != null && message.hasOwnProperty("numStates"))
+                                if (!$util.isInteger(message.numStates))
+                                    return "numStates: integer expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDeviceStatesRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesRequest} ListDeviceStatesRequest
+                         */
+                        ListDeviceStatesRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDeviceStatesRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDeviceStatesRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            if (object.numStates != null)
+                                message.numStates = object.numStates | 0;
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDeviceStatesRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDeviceStatesRequest} message ListDeviceStatesRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDeviceStatesRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.name = "";
+                                object.numStates = 0;
+                            }
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            if (message.numStates != null && message.hasOwnProperty("numStates"))
+                                object.numStates = message.numStates;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDeviceStatesRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDeviceStatesRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDeviceStatesRequest;
+                    })();
+    
+                    v1.ListDeviceStatesResponse = (function() {
+    
+                        /**
+                         * Properties of a ListDeviceStatesResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IListDeviceStatesResponse
+                         * @property {Array.<google.cloud.iot.v1.IDeviceState>|null} [deviceStates] ListDeviceStatesResponse deviceStates
+                         */
+    
+                        /**
+                         * Constructs a new ListDeviceStatesResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a ListDeviceStatesResponse.
+                         * @implements IListDeviceStatesResponse
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IListDeviceStatesResponse=} [properties] Properties to set
+                         */
+                        function ListDeviceStatesResponse(properties) {
+                            this.deviceStates = [];
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * ListDeviceStatesResponse deviceStates.
+                         * @member {Array.<google.cloud.iot.v1.IDeviceState>} deviceStates
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @instance
+                         */
+                        ListDeviceStatesResponse.prototype.deviceStates = $util.emptyArray;
+    
+                        /**
+                         * Creates a new ListDeviceStatesResponse instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceStatesResponse=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesResponse} ListDeviceStatesResponse instance
+                         */
+                        ListDeviceStatesResponse.create = function create(properties) {
+                            return new ListDeviceStatesResponse(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceStatesResponse message. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesResponse.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceStatesResponse} message ListDeviceStatesResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceStatesResponse.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.deviceStates != null && message.deviceStates.length)
+                                for (var i = 0; i < message.deviceStates.length; ++i)
+                                    $root.google.cloud.iot.v1.DeviceState.encode(message.deviceStates[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified ListDeviceStatesResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.ListDeviceStatesResponse.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IListDeviceStatesResponse} message ListDeviceStatesResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        ListDeviceStatesResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceStatesResponse message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesResponse} ListDeviceStatesResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceStatesResponse.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.ListDeviceStatesResponse();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    if (!(message.deviceStates && message.deviceStates.length))
+                                        message.deviceStates = [];
+                                    message.deviceStates.push($root.google.cloud.iot.v1.DeviceState.decode(reader, reader.uint32()));
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a ListDeviceStatesResponse message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesResponse} ListDeviceStatesResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        ListDeviceStatesResponse.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a ListDeviceStatesResponse message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        ListDeviceStatesResponse.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.deviceStates != null && message.hasOwnProperty("deviceStates")) {
+                                if (!Array.isArray(message.deviceStates))
+                                    return "deviceStates: array expected";
+                                for (var i = 0; i < message.deviceStates.length; ++i) {
+                                    var error = $root.google.cloud.iot.v1.DeviceState.verify(message.deviceStates[i]);
+                                    if (error)
+                                        return "deviceStates." + error;
+                                }
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a ListDeviceStatesResponse message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.ListDeviceStatesResponse} ListDeviceStatesResponse
+                         */
+                        ListDeviceStatesResponse.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.ListDeviceStatesResponse)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.ListDeviceStatesResponse();
+                            if (object.deviceStates) {
+                                if (!Array.isArray(object.deviceStates))
+                                    throw TypeError(".google.cloud.iot.v1.ListDeviceStatesResponse.deviceStates: array expected");
+                                message.deviceStates = [];
+                                for (var i = 0; i < object.deviceStates.length; ++i) {
+                                    if (typeof object.deviceStates[i] !== "object")
+                                        throw TypeError(".google.cloud.iot.v1.ListDeviceStatesResponse.deviceStates: object expected");
+                                    message.deviceStates[i] = $root.google.cloud.iot.v1.DeviceState.fromObject(object.deviceStates[i]);
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a ListDeviceStatesResponse message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.ListDeviceStatesResponse} message ListDeviceStatesResponse
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        ListDeviceStatesResponse.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.arrays || options.defaults)
+                                object.deviceStates = [];
+                            if (message.deviceStates && message.deviceStates.length) {
+                                object.deviceStates = [];
+                                for (var j = 0; j < message.deviceStates.length; ++j)
+                                    object.deviceStates[j] = $root.google.cloud.iot.v1.DeviceState.toObject(message.deviceStates[j], options);
+                            }
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this ListDeviceStatesResponse to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.ListDeviceStatesResponse
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        ListDeviceStatesResponse.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return ListDeviceStatesResponse;
+                    })();
+    
+                    v1.SendCommandToDeviceRequest = (function() {
+    
+                        /**
+                         * Properties of a SendCommandToDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface ISendCommandToDeviceRequest
+                         * @property {string|null} [name] SendCommandToDeviceRequest name
+                         * @property {Uint8Array|null} [binaryData] SendCommandToDeviceRequest binaryData
+                         * @property {string|null} [subfolder] SendCommandToDeviceRequest subfolder
+                         */
+    
+                        /**
+                         * Constructs a new SendCommandToDeviceRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a SendCommandToDeviceRequest.
+                         * @implements ISendCommandToDeviceRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceRequest=} [properties] Properties to set
+                         */
+                        function SendCommandToDeviceRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * SendCommandToDeviceRequest name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @instance
+                         */
+                        SendCommandToDeviceRequest.prototype.name = "";
+    
+                        /**
+                         * SendCommandToDeviceRequest binaryData.
+                         * @member {Uint8Array} binaryData
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @instance
+                         */
+                        SendCommandToDeviceRequest.prototype.binaryData = $util.newBuffer([]);
+    
+                        /**
+                         * SendCommandToDeviceRequest subfolder.
+                         * @member {string} subfolder
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @instance
+                         */
+                        SendCommandToDeviceRequest.prototype.subfolder = "";
+    
+                        /**
+                         * Creates a new SendCommandToDeviceRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceRequest} SendCommandToDeviceRequest instance
+                         */
+                        SendCommandToDeviceRequest.create = function create(properties) {
+                            return new SendCommandToDeviceRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified SendCommandToDeviceRequest message. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceRequest} message SendCommandToDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        SendCommandToDeviceRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                            if (message.binaryData != null && Object.hasOwnProperty.call(message, "binaryData"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.binaryData);
+                            if (message.subfolder != null && Object.hasOwnProperty.call(message, "subfolder"))
+                                writer.uint32(/* id 3, wireType 2 =*/26).string(message.subfolder);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified SendCommandToDeviceRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceRequest} message SendCommandToDeviceRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        SendCommandToDeviceRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a SendCommandToDeviceRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceRequest} SendCommandToDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        SendCommandToDeviceRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.SendCommandToDeviceRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.name = reader.string();
+                                    break;
+                                case 2:
+                                    message.binaryData = reader.bytes();
+                                    break;
+                                case 3:
+                                    message.subfolder = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a SendCommandToDeviceRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceRequest} SendCommandToDeviceRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        SendCommandToDeviceRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a SendCommandToDeviceRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        SendCommandToDeviceRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                if (!(message.binaryData && typeof message.binaryData.length === "number" || $util.isString(message.binaryData)))
+                                    return "binaryData: buffer expected";
+                            if (message.subfolder != null && message.hasOwnProperty("subfolder"))
+                                if (!$util.isString(message.subfolder))
+                                    return "subfolder: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a SendCommandToDeviceRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceRequest} SendCommandToDeviceRequest
+                         */
+                        SendCommandToDeviceRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.SendCommandToDeviceRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.SendCommandToDeviceRequest();
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            if (object.binaryData != null)
+                                if (typeof object.binaryData === "string")
+                                    $util.base64.decode(object.binaryData, message.binaryData = $util.newBuffer($util.base64.length(object.binaryData)), 0);
+                                else if (object.binaryData.length)
+                                    message.binaryData = object.binaryData;
+                            if (object.subfolder != null)
+                                message.subfolder = String(object.subfolder);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a SendCommandToDeviceRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.SendCommandToDeviceRequest} message SendCommandToDeviceRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        SendCommandToDeviceRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.name = "";
+                                if (options.bytes === String)
+                                    object.binaryData = "";
+                                else {
+                                    object.binaryData = [];
+                                    if (options.bytes !== Array)
+                                        object.binaryData = $util.newBuffer(object.binaryData);
+                                }
+                                object.subfolder = "";
+                            }
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                object.binaryData = options.bytes === String ? $util.base64.encode(message.binaryData, 0, message.binaryData.length) : options.bytes === Array ? Array.prototype.slice.call(message.binaryData) : message.binaryData;
+                            if (message.subfolder != null && message.hasOwnProperty("subfolder"))
+                                object.subfolder = message.subfolder;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this SendCommandToDeviceRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        SendCommandToDeviceRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return SendCommandToDeviceRequest;
+                    })();
+    
+                    v1.SendCommandToDeviceResponse = (function() {
+    
+                        /**
+                         * Properties of a SendCommandToDeviceResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @interface ISendCommandToDeviceResponse
+                         */
+    
+                        /**
+                         * Constructs a new SendCommandToDeviceResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a SendCommandToDeviceResponse.
+                         * @implements ISendCommandToDeviceResponse
+                         * @constructor
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceResponse=} [properties] Properties to set
+                         */
+                        function SendCommandToDeviceResponse(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * Creates a new SendCommandToDeviceResponse instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceResponse=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceResponse} SendCommandToDeviceResponse instance
+                         */
+                        SendCommandToDeviceResponse.create = function create(properties) {
+                            return new SendCommandToDeviceResponse(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified SendCommandToDeviceResponse message. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceResponse.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceResponse} message SendCommandToDeviceResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        SendCommandToDeviceResponse.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified SendCommandToDeviceResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.SendCommandToDeviceResponse.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.ISendCommandToDeviceResponse} message SendCommandToDeviceResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        SendCommandToDeviceResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a SendCommandToDeviceResponse message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceResponse} SendCommandToDeviceResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        SendCommandToDeviceResponse.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.SendCommandToDeviceResponse();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a SendCommandToDeviceResponse message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceResponse} SendCommandToDeviceResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        SendCommandToDeviceResponse.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a SendCommandToDeviceResponse message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        SendCommandToDeviceResponse.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a SendCommandToDeviceResponse message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.SendCommandToDeviceResponse} SendCommandToDeviceResponse
+                         */
+                        SendCommandToDeviceResponse.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.SendCommandToDeviceResponse)
+                                return object;
+                            return new $root.google.cloud.iot.v1.SendCommandToDeviceResponse();
+                        };
+    
+                        /**
+                         * Creates a plain object from a SendCommandToDeviceResponse message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.SendCommandToDeviceResponse} message SendCommandToDeviceResponse
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        SendCommandToDeviceResponse.toObject = function toObject() {
+                            return {};
+                        };
+    
+                        /**
+                         * Converts this SendCommandToDeviceResponse to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.SendCommandToDeviceResponse
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        SendCommandToDeviceResponse.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return SendCommandToDeviceResponse;
+                    })();
+    
+                    v1.BindDeviceToGatewayRequest = (function() {
+    
+                        /**
+                         * Properties of a BindDeviceToGatewayRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IBindDeviceToGatewayRequest
+                         * @property {string|null} [parent] BindDeviceToGatewayRequest parent
+                         * @property {string|null} [gatewayId] BindDeviceToGatewayRequest gatewayId
+                         * @property {string|null} [deviceId] BindDeviceToGatewayRequest deviceId
+                         */
+    
+                        /**
+                         * Constructs a new BindDeviceToGatewayRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a BindDeviceToGatewayRequest.
+                         * @implements IBindDeviceToGatewayRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayRequest=} [properties] Properties to set
+                         */
+                        function BindDeviceToGatewayRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * BindDeviceToGatewayRequest parent.
+                         * @member {string} parent
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @instance
+                         */
+                        BindDeviceToGatewayRequest.prototype.parent = "";
+    
+                        /**
+                         * BindDeviceToGatewayRequest gatewayId.
+                         * @member {string} gatewayId
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @instance
+                         */
+                        BindDeviceToGatewayRequest.prototype.gatewayId = "";
+    
+                        /**
+                         * BindDeviceToGatewayRequest deviceId.
+                         * @member {string} deviceId
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @instance
+                         */
+                        BindDeviceToGatewayRequest.prototype.deviceId = "";
+    
+                        /**
+                         * Creates a new BindDeviceToGatewayRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayRequest} BindDeviceToGatewayRequest instance
+                         */
+                        BindDeviceToGatewayRequest.create = function create(properties) {
+                            return new BindDeviceToGatewayRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified BindDeviceToGatewayRequest message. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayRequest} message BindDeviceToGatewayRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        BindDeviceToGatewayRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.parent != null && Object.hasOwnProperty.call(message, "parent"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.parent);
+                            if (message.gatewayId != null && Object.hasOwnProperty.call(message, "gatewayId"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.gatewayId);
+                            if (message.deviceId != null && Object.hasOwnProperty.call(message, "deviceId"))
+                                writer.uint32(/* id 3, wireType 2 =*/26).string(message.deviceId);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified BindDeviceToGatewayRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayRequest} message BindDeviceToGatewayRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        BindDeviceToGatewayRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a BindDeviceToGatewayRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayRequest} BindDeviceToGatewayRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        BindDeviceToGatewayRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.BindDeviceToGatewayRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.parent = reader.string();
+                                    break;
+                                case 2:
+                                    message.gatewayId = reader.string();
+                                    break;
+                                case 3:
+                                    message.deviceId = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a BindDeviceToGatewayRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayRequest} BindDeviceToGatewayRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        BindDeviceToGatewayRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a BindDeviceToGatewayRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        BindDeviceToGatewayRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                if (!$util.isString(message.parent))
+                                    return "parent: string expected";
+                            if (message.gatewayId != null && message.hasOwnProperty("gatewayId"))
+                                if (!$util.isString(message.gatewayId))
+                                    return "gatewayId: string expected";
+                            if (message.deviceId != null && message.hasOwnProperty("deviceId"))
+                                if (!$util.isString(message.deviceId))
+                                    return "deviceId: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a BindDeviceToGatewayRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayRequest} BindDeviceToGatewayRequest
+                         */
+                        BindDeviceToGatewayRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.BindDeviceToGatewayRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.BindDeviceToGatewayRequest();
+                            if (object.parent != null)
+                                message.parent = String(object.parent);
+                            if (object.gatewayId != null)
+                                message.gatewayId = String(object.gatewayId);
+                            if (object.deviceId != null)
+                                message.deviceId = String(object.deviceId);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a BindDeviceToGatewayRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.BindDeviceToGatewayRequest} message BindDeviceToGatewayRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        BindDeviceToGatewayRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.parent = "";
+                                object.gatewayId = "";
+                                object.deviceId = "";
+                            }
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                object.parent = message.parent;
+                            if (message.gatewayId != null && message.hasOwnProperty("gatewayId"))
+                                object.gatewayId = message.gatewayId;
+                            if (message.deviceId != null && message.hasOwnProperty("deviceId"))
+                                object.deviceId = message.deviceId;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this BindDeviceToGatewayRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        BindDeviceToGatewayRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return BindDeviceToGatewayRequest;
+                    })();
+    
+                    v1.BindDeviceToGatewayResponse = (function() {
+    
+                        /**
+                         * Properties of a BindDeviceToGatewayResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IBindDeviceToGatewayResponse
+                         */
+    
+                        /**
+                         * Constructs a new BindDeviceToGatewayResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a BindDeviceToGatewayResponse.
+                         * @implements IBindDeviceToGatewayResponse
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayResponse=} [properties] Properties to set
+                         */
+                        function BindDeviceToGatewayResponse(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * Creates a new BindDeviceToGatewayResponse instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayResponse=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayResponse} BindDeviceToGatewayResponse instance
+                         */
+                        BindDeviceToGatewayResponse.create = function create(properties) {
+                            return new BindDeviceToGatewayResponse(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified BindDeviceToGatewayResponse message. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayResponse.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayResponse} message BindDeviceToGatewayResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        BindDeviceToGatewayResponse.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified BindDeviceToGatewayResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.BindDeviceToGatewayResponse.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IBindDeviceToGatewayResponse} message BindDeviceToGatewayResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        BindDeviceToGatewayResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a BindDeviceToGatewayResponse message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayResponse} BindDeviceToGatewayResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        BindDeviceToGatewayResponse.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.BindDeviceToGatewayResponse();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a BindDeviceToGatewayResponse message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayResponse} BindDeviceToGatewayResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        BindDeviceToGatewayResponse.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a BindDeviceToGatewayResponse message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        BindDeviceToGatewayResponse.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a BindDeviceToGatewayResponse message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.BindDeviceToGatewayResponse} BindDeviceToGatewayResponse
+                         */
+                        BindDeviceToGatewayResponse.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.BindDeviceToGatewayResponse)
+                                return object;
+                            return new $root.google.cloud.iot.v1.BindDeviceToGatewayResponse();
+                        };
+    
+                        /**
+                         * Creates a plain object from a BindDeviceToGatewayResponse message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.BindDeviceToGatewayResponse} message BindDeviceToGatewayResponse
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        BindDeviceToGatewayResponse.toObject = function toObject() {
+                            return {};
+                        };
+    
+                        /**
+                         * Converts this BindDeviceToGatewayResponse to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.BindDeviceToGatewayResponse
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        BindDeviceToGatewayResponse.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return BindDeviceToGatewayResponse;
+                    })();
+    
+                    v1.UnbindDeviceFromGatewayRequest = (function() {
+    
+                        /**
+                         * Properties of an UnbindDeviceFromGatewayRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IUnbindDeviceFromGatewayRequest
+                         * @property {string|null} [parent] UnbindDeviceFromGatewayRequest parent
+                         * @property {string|null} [gatewayId] UnbindDeviceFromGatewayRequest gatewayId
+                         * @property {string|null} [deviceId] UnbindDeviceFromGatewayRequest deviceId
+                         */
+    
+                        /**
+                         * Constructs a new UnbindDeviceFromGatewayRequest.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents an UnbindDeviceFromGatewayRequest.
+                         * @implements IUnbindDeviceFromGatewayRequest
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest=} [properties] Properties to set
+                         */
+                        function UnbindDeviceFromGatewayRequest(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * UnbindDeviceFromGatewayRequest parent.
+                         * @member {string} parent
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @instance
+                         */
+                        UnbindDeviceFromGatewayRequest.prototype.parent = "";
+    
+                        /**
+                         * UnbindDeviceFromGatewayRequest gatewayId.
+                         * @member {string} gatewayId
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @instance
+                         */
+                        UnbindDeviceFromGatewayRequest.prototype.gatewayId = "";
+    
+                        /**
+                         * UnbindDeviceFromGatewayRequest deviceId.
+                         * @member {string} deviceId
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @instance
+                         */
+                        UnbindDeviceFromGatewayRequest.prototype.deviceId = "";
+    
+                        /**
+                         * Creates a new UnbindDeviceFromGatewayRequest instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayRequest} UnbindDeviceFromGatewayRequest instance
+                         */
+                        UnbindDeviceFromGatewayRequest.create = function create(properties) {
+                            return new UnbindDeviceFromGatewayRequest(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified UnbindDeviceFromGatewayRequest message. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayRequest.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest} message UnbindDeviceFromGatewayRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UnbindDeviceFromGatewayRequest.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.parent != null && Object.hasOwnProperty.call(message, "parent"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.parent);
+                            if (message.gatewayId != null && Object.hasOwnProperty.call(message, "gatewayId"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.gatewayId);
+                            if (message.deviceId != null && Object.hasOwnProperty.call(message, "deviceId"))
+                                writer.uint32(/* id 3, wireType 2 =*/26).string(message.deviceId);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified UnbindDeviceFromGatewayRequest message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayRequest.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest} message UnbindDeviceFromGatewayRequest message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UnbindDeviceFromGatewayRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes an UnbindDeviceFromGatewayRequest message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayRequest} UnbindDeviceFromGatewayRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UnbindDeviceFromGatewayRequest.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.parent = reader.string();
+                                    break;
+                                case 2:
+                                    message.gatewayId = reader.string();
+                                    break;
+                                case 3:
+                                    message.deviceId = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes an UnbindDeviceFromGatewayRequest message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayRequest} UnbindDeviceFromGatewayRequest
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UnbindDeviceFromGatewayRequest.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies an UnbindDeviceFromGatewayRequest message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        UnbindDeviceFromGatewayRequest.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                if (!$util.isString(message.parent))
+                                    return "parent: string expected";
+                            if (message.gatewayId != null && message.hasOwnProperty("gatewayId"))
+                                if (!$util.isString(message.gatewayId))
+                                    return "gatewayId: string expected";
+                            if (message.deviceId != null && message.hasOwnProperty("deviceId"))
+                                if (!$util.isString(message.deviceId))
+                                    return "deviceId: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates an UnbindDeviceFromGatewayRequest message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayRequest} UnbindDeviceFromGatewayRequest
+                         */
+                        UnbindDeviceFromGatewayRequest.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest();
+                            if (object.parent != null)
+                                message.parent = String(object.parent);
+                            if (object.gatewayId != null)
+                                message.gatewayId = String(object.gatewayId);
+                            if (object.deviceId != null)
+                                message.deviceId = String(object.deviceId);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from an UnbindDeviceFromGatewayRequest message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @static
+                         * @param {google.cloud.iot.v1.UnbindDeviceFromGatewayRequest} message UnbindDeviceFromGatewayRequest
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        UnbindDeviceFromGatewayRequest.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.parent = "";
+                                object.gatewayId = "";
+                                object.deviceId = "";
+                            }
+                            if (message.parent != null && message.hasOwnProperty("parent"))
+                                object.parent = message.parent;
+                            if (message.gatewayId != null && message.hasOwnProperty("gatewayId"))
+                                object.gatewayId = message.gatewayId;
+                            if (message.deviceId != null && message.hasOwnProperty("deviceId"))
+                                object.deviceId = message.deviceId;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this UnbindDeviceFromGatewayRequest to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayRequest
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        UnbindDeviceFromGatewayRequest.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return UnbindDeviceFromGatewayRequest;
+                    })();
+    
+                    v1.UnbindDeviceFromGatewayResponse = (function() {
+    
+                        /**
+                         * Properties of an UnbindDeviceFromGatewayResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IUnbindDeviceFromGatewayResponse
+                         */
+    
+                        /**
+                         * Constructs a new UnbindDeviceFromGatewayResponse.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents an UnbindDeviceFromGatewayResponse.
+                         * @implements IUnbindDeviceFromGatewayResponse
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse=} [properties] Properties to set
+                         */
+                        function UnbindDeviceFromGatewayResponse(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * Creates a new UnbindDeviceFromGatewayResponse instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayResponse} UnbindDeviceFromGatewayResponse instance
+                         */
+                        UnbindDeviceFromGatewayResponse.create = function create(properties) {
+                            return new UnbindDeviceFromGatewayResponse(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified UnbindDeviceFromGatewayResponse message. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayResponse.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse} message UnbindDeviceFromGatewayResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UnbindDeviceFromGatewayResponse.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified UnbindDeviceFromGatewayResponse message, length delimited. Does not implicitly {@link google.cloud.iot.v1.UnbindDeviceFromGatewayResponse.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse} message UnbindDeviceFromGatewayResponse message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        UnbindDeviceFromGatewayResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes an UnbindDeviceFromGatewayResponse message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayResponse} UnbindDeviceFromGatewayResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UnbindDeviceFromGatewayResponse.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.UnbindDeviceFromGatewayResponse();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes an UnbindDeviceFromGatewayResponse message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayResponse} UnbindDeviceFromGatewayResponse
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        UnbindDeviceFromGatewayResponse.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies an UnbindDeviceFromGatewayResponse message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        UnbindDeviceFromGatewayResponse.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates an UnbindDeviceFromGatewayResponse message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.UnbindDeviceFromGatewayResponse} UnbindDeviceFromGatewayResponse
+                         */
+                        UnbindDeviceFromGatewayResponse.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.UnbindDeviceFromGatewayResponse)
+                                return object;
+                            return new $root.google.cloud.iot.v1.UnbindDeviceFromGatewayResponse();
+                        };
+    
+                        /**
+                         * Creates a plain object from an UnbindDeviceFromGatewayResponse message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @static
+                         * @param {google.cloud.iot.v1.UnbindDeviceFromGatewayResponse} message UnbindDeviceFromGatewayResponse
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        UnbindDeviceFromGatewayResponse.toObject = function toObject() {
+                            return {};
+                        };
+    
+                        /**
+                         * Converts this UnbindDeviceFromGatewayResponse to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.UnbindDeviceFromGatewayResponse
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        UnbindDeviceFromGatewayResponse.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return UnbindDeviceFromGatewayResponse;
+                    })();
+    
+                    v1.Device = (function() {
+    
+                        /**
+                         * Properties of a Device.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IDevice
+                         * @property {string|null} [id] Device id
+                         * @property {string|null} [name] Device name
+                         * @property {number|Long|null} [numId] Device numId
+                         * @property {Array.<google.cloud.iot.v1.IDeviceCredential>|null} [credentials] Device credentials
+                         * @property {google.protobuf.ITimestamp|null} [lastHeartbeatTime] Device lastHeartbeatTime
+                         * @property {google.protobuf.ITimestamp|null} [lastEventTime] Device lastEventTime
+                         * @property {google.protobuf.ITimestamp|null} [lastStateTime] Device lastStateTime
+                         * @property {google.protobuf.ITimestamp|null} [lastConfigAckTime] Device lastConfigAckTime
+                         * @property {google.protobuf.ITimestamp|null} [lastConfigSendTime] Device lastConfigSendTime
+                         * @property {boolean|null} [blocked] Device blocked
+                         * @property {google.protobuf.ITimestamp|null} [lastErrorTime] Device lastErrorTime
+                         * @property {google.rpc.IStatus|null} [lastErrorStatus] Device lastErrorStatus
+                         * @property {google.cloud.iot.v1.IDeviceConfig|null} [config] Device config
+                         * @property {google.cloud.iot.v1.IDeviceState|null} [state] Device state
+                         * @property {google.cloud.iot.v1.LogLevel|null} [logLevel] Device logLevel
+                         * @property {Object.<string,string>|null} [metadata] Device metadata
+                         * @property {google.cloud.iot.v1.IGatewayConfig|null} [gatewayConfig] Device gatewayConfig
+                         */
+    
+                        /**
+                         * Constructs a new Device.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a Device.
+                         * @implements IDevice
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IDevice=} [properties] Properties to set
+                         */
+                        function Device(properties) {
+                            this.credentials = [];
+                            this.metadata = {};
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * Device id.
+                         * @member {string} id
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.id = "";
+    
+                        /**
+                         * Device name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.name = "";
+    
+                        /**
+                         * Device numId.
+                         * @member {number|Long} numId
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.numId = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
+    
+                        /**
+                         * Device credentials.
+                         * @member {Array.<google.cloud.iot.v1.IDeviceCredential>} credentials
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.credentials = $util.emptyArray;
+    
+                        /**
+                         * Device lastHeartbeatTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} lastHeartbeatTime
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.lastHeartbeatTime = null;
+    
+                        /**
+                         * Device lastEventTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} lastEventTime
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.lastEventTime = null;
+    
+                        /**
+                         * Device lastStateTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} lastStateTime
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.lastStateTime = null;
+    
+                        /**
+                         * Device lastConfigAckTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} lastConfigAckTime
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.lastConfigAckTime = null;
+    
+                        /**
+                         * Device lastConfigSendTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} lastConfigSendTime
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.lastConfigSendTime = null;
+    
+                        /**
+                         * Device blocked.
+                         * @member {boolean} blocked
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.blocked = false;
+    
+                        /**
+                         * Device lastErrorTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} lastErrorTime
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.lastErrorTime = null;
+    
+                        /**
+                         * Device lastErrorStatus.
+                         * @member {google.rpc.IStatus|null|undefined} lastErrorStatus
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.lastErrorStatus = null;
+    
+                        /**
+                         * Device config.
+                         * @member {google.cloud.iot.v1.IDeviceConfig|null|undefined} config
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.config = null;
+    
+                        /**
+                         * Device state.
+                         * @member {google.cloud.iot.v1.IDeviceState|null|undefined} state
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.state = null;
+    
+                        /**
+                         * Device logLevel.
+                         * @member {google.cloud.iot.v1.LogLevel} logLevel
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.logLevel = 0;
+    
+                        /**
+                         * Device metadata.
+                         * @member {Object.<string,string>} metadata
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.metadata = $util.emptyObject;
+    
+                        /**
+                         * Device gatewayConfig.
+                         * @member {google.cloud.iot.v1.IGatewayConfig|null|undefined} gatewayConfig
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         */
+                        Device.prototype.gatewayConfig = null;
+    
+                        /**
+                         * Creates a new Device instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {google.cloud.iot.v1.IDevice=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.Device} Device instance
+                         */
+                        Device.create = function create(properties) {
+                            return new Device(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified Device message. Does not implicitly {@link google.cloud.iot.v1.Device.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {google.cloud.iot.v1.IDevice} message Device message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        Device.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.id != null && Object.hasOwnProperty.call(message, "id"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.id);
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.name);
+                            if (message.numId != null && Object.hasOwnProperty.call(message, "numId"))
+                                writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.numId);
+                            if (message.lastHeartbeatTime != null && Object.hasOwnProperty.call(message, "lastHeartbeatTime"))
+                                $root.google.protobuf.Timestamp.encode(message.lastHeartbeatTime, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
+                            if (message.lastEventTime != null && Object.hasOwnProperty.call(message, "lastEventTime"))
+                                $root.google.protobuf.Timestamp.encode(message.lastEventTime, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
+                            if (message.lastErrorTime != null && Object.hasOwnProperty.call(message, "lastErrorTime"))
+                                $root.google.protobuf.Timestamp.encode(message.lastErrorTime, writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim();
+                            if (message.lastErrorStatus != null && Object.hasOwnProperty.call(message, "lastErrorStatus"))
+                                $root.google.rpc.Status.encode(message.lastErrorStatus, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
+                            if (message.credentials != null && message.credentials.length)
+                                for (var i = 0; i < message.credentials.length; ++i)
+                                    $root.google.cloud.iot.v1.DeviceCredential.encode(message.credentials[i], writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim();
+                            if (message.config != null && Object.hasOwnProperty.call(message, "config"))
+                                $root.google.cloud.iot.v1.DeviceConfig.encode(message.config, writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim();
+                            if (message.lastConfigAckTime != null && Object.hasOwnProperty.call(message, "lastConfigAckTime"))
+                                $root.google.protobuf.Timestamp.encode(message.lastConfigAckTime, writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim();
+                            if (message.state != null && Object.hasOwnProperty.call(message, "state"))
+                                $root.google.cloud.iot.v1.DeviceState.encode(message.state, writer.uint32(/* id 16, wireType 2 =*/130).fork()).ldelim();
+                            if (message.metadata != null && Object.hasOwnProperty.call(message, "metadata"))
+                                for (var keys = Object.keys(message.metadata), i = 0; i < keys.length; ++i)
+                                    writer.uint32(/* id 17, wireType 2 =*/138).fork().uint32(/* id 1, wireType 2 =*/10).string(keys[i]).uint32(/* id 2, wireType 2 =*/18).string(message.metadata[keys[i]]).ldelim();
+                            if (message.lastConfigSendTime != null && Object.hasOwnProperty.call(message, "lastConfigSendTime"))
+                                $root.google.protobuf.Timestamp.encode(message.lastConfigSendTime, writer.uint32(/* id 18, wireType 2 =*/146).fork()).ldelim();
+                            if (message.blocked != null && Object.hasOwnProperty.call(message, "blocked"))
+                                writer.uint32(/* id 19, wireType 0 =*/152).bool(message.blocked);
+                            if (message.lastStateTime != null && Object.hasOwnProperty.call(message, "lastStateTime"))
+                                $root.google.protobuf.Timestamp.encode(message.lastStateTime, writer.uint32(/* id 20, wireType 2 =*/162).fork()).ldelim();
+                            if (message.logLevel != null && Object.hasOwnProperty.call(message, "logLevel"))
+                                writer.uint32(/* id 21, wireType 0 =*/168).int32(message.logLevel);
+                            if (message.gatewayConfig != null && Object.hasOwnProperty.call(message, "gatewayConfig"))
+                                $root.google.cloud.iot.v1.GatewayConfig.encode(message.gatewayConfig, writer.uint32(/* id 24, wireType 2 =*/194).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified Device message, length delimited. Does not implicitly {@link google.cloud.iot.v1.Device.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {google.cloud.iot.v1.IDevice} message Device message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        Device.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a Device message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.Device} Device
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        Device.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.Device(), key, value;
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.id = reader.string();
+                                    break;
+                                case 2:
+                                    message.name = reader.string();
+                                    break;
+                                case 3:
+                                    message.numId = reader.uint64();
+                                    break;
+                                case 12:
+                                    if (!(message.credentials && message.credentials.length))
+                                        message.credentials = [];
+                                    message.credentials.push($root.google.cloud.iot.v1.DeviceCredential.decode(reader, reader.uint32()));
+                                    break;
+                                case 7:
+                                    message.lastHeartbeatTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 8:
+                                    message.lastEventTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 20:
+                                    message.lastStateTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 14:
+                                    message.lastConfigAckTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 18:
+                                    message.lastConfigSendTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 19:
+                                    message.blocked = reader.bool();
+                                    break;
+                                case 10:
+                                    message.lastErrorTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 11:
+                                    message.lastErrorStatus = $root.google.rpc.Status.decode(reader, reader.uint32());
+                                    break;
+                                case 13:
+                                    message.config = $root.google.cloud.iot.v1.DeviceConfig.decode(reader, reader.uint32());
+                                    break;
+                                case 16:
+                                    message.state = $root.google.cloud.iot.v1.DeviceState.decode(reader, reader.uint32());
+                                    break;
+                                case 21:
+                                    message.logLevel = reader.int32();
+                                    break;
+                                case 17:
+                                    if (message.metadata === $util.emptyObject)
+                                        message.metadata = {};
+                                    var end2 = reader.uint32() + reader.pos;
+                                    key = "";
+                                    value = "";
+                                    while (reader.pos < end2) {
+                                        var tag2 = reader.uint32();
+                                        switch (tag2 >>> 3) {
+                                        case 1:
+                                            key = reader.string();
+                                            break;
+                                        case 2:
+                                            value = reader.string();
+                                            break;
+                                        default:
+                                            reader.skipType(tag2 & 7);
+                                            break;
+                                        }
+                                    }
+                                    message.metadata[key] = value;
+                                    break;
+                                case 24:
+                                    message.gatewayConfig = $root.google.cloud.iot.v1.GatewayConfig.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a Device message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.Device} Device
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        Device.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a Device message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        Device.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.id != null && message.hasOwnProperty("id"))
+                                if (!$util.isString(message.id))
+                                    return "id: string expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            if (message.numId != null && message.hasOwnProperty("numId"))
+                                if (!$util.isInteger(message.numId) && !(message.numId && $util.isInteger(message.numId.low) && $util.isInteger(message.numId.high)))
+                                    return "numId: integer|Long expected";
+                            if (message.credentials != null && message.hasOwnProperty("credentials")) {
+                                if (!Array.isArray(message.credentials))
+                                    return "credentials: array expected";
+                                for (var i = 0; i < message.credentials.length; ++i) {
+                                    var error = $root.google.cloud.iot.v1.DeviceCredential.verify(message.credentials[i]);
+                                    if (error)
+                                        return "credentials." + error;
+                                }
+                            }
+                            if (message.lastHeartbeatTime != null && message.hasOwnProperty("lastHeartbeatTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.lastHeartbeatTime);
+                                if (error)
+                                    return "lastHeartbeatTime." + error;
+                            }
+                            if (message.lastEventTime != null && message.hasOwnProperty("lastEventTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.lastEventTime);
+                                if (error)
+                                    return "lastEventTime." + error;
+                            }
+                            if (message.lastStateTime != null && message.hasOwnProperty("lastStateTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.lastStateTime);
+                                if (error)
+                                    return "lastStateTime." + error;
+                            }
+                            if (message.lastConfigAckTime != null && message.hasOwnProperty("lastConfigAckTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.lastConfigAckTime);
+                                if (error)
+                                    return "lastConfigAckTime." + error;
+                            }
+                            if (message.lastConfigSendTime != null && message.hasOwnProperty("lastConfigSendTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.lastConfigSendTime);
+                                if (error)
+                                    return "lastConfigSendTime." + error;
+                            }
+                            if (message.blocked != null && message.hasOwnProperty("blocked"))
+                                if (typeof message.blocked !== "boolean")
+                                    return "blocked: boolean expected";
+                            if (message.lastErrorTime != null && message.hasOwnProperty("lastErrorTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.lastErrorTime);
+                                if (error)
+                                    return "lastErrorTime." + error;
+                            }
+                            if (message.lastErrorStatus != null && message.hasOwnProperty("lastErrorStatus")) {
+                                var error = $root.google.rpc.Status.verify(message.lastErrorStatus);
+                                if (error)
+                                    return "lastErrorStatus." + error;
+                            }
+                            if (message.config != null && message.hasOwnProperty("config")) {
+                                var error = $root.google.cloud.iot.v1.DeviceConfig.verify(message.config);
+                                if (error)
+                                    return "config." + error;
+                            }
+                            if (message.state != null && message.hasOwnProperty("state")) {
+                                var error = $root.google.cloud.iot.v1.DeviceState.verify(message.state);
+                                if (error)
+                                    return "state." + error;
+                            }
+                            if (message.logLevel != null && message.hasOwnProperty("logLevel"))
+                                switch (message.logLevel) {
+                                default:
+                                    return "logLevel: enum value expected";
+                                case 0:
+                                case 10:
+                                case 20:
+                                case 30:
+                                case 40:
+                                    break;
+                                }
+                            if (message.metadata != null && message.hasOwnProperty("metadata")) {
+                                if (!$util.isObject(message.metadata))
+                                    return "metadata: object expected";
+                                var key = Object.keys(message.metadata);
+                                for (var i = 0; i < key.length; ++i)
+                                    if (!$util.isString(message.metadata[key[i]]))
+                                        return "metadata: string{k:string} expected";
+                            }
+                            if (message.gatewayConfig != null && message.hasOwnProperty("gatewayConfig")) {
+                                var error = $root.google.cloud.iot.v1.GatewayConfig.verify(message.gatewayConfig);
+                                if (error)
+                                    return "gatewayConfig." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a Device message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.Device} Device
+                         */
+                        Device.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.Device)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.Device();
+                            if (object.id != null)
+                                message.id = String(object.id);
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            if (object.numId != null)
+                                if ($util.Long)
+                                    (message.numId = $util.Long.fromValue(object.numId)).unsigned = true;
+                                else if (typeof object.numId === "string")
+                                    message.numId = parseInt(object.numId, 10);
+                                else if (typeof object.numId === "number")
+                                    message.numId = object.numId;
+                                else if (typeof object.numId === "object")
+                                    message.numId = new $util.LongBits(object.numId.low >>> 0, object.numId.high >>> 0).toNumber(true);
+                            if (object.credentials) {
+                                if (!Array.isArray(object.credentials))
+                                    throw TypeError(".google.cloud.iot.v1.Device.credentials: array expected");
+                                message.credentials = [];
+                                for (var i = 0; i < object.credentials.length; ++i) {
+                                    if (typeof object.credentials[i] !== "object")
+                                        throw TypeError(".google.cloud.iot.v1.Device.credentials: object expected");
+                                    message.credentials[i] = $root.google.cloud.iot.v1.DeviceCredential.fromObject(object.credentials[i]);
+                                }
+                            }
+                            if (object.lastHeartbeatTime != null) {
+                                if (typeof object.lastHeartbeatTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.lastHeartbeatTime: object expected");
+                                message.lastHeartbeatTime = $root.google.protobuf.Timestamp.fromObject(object.lastHeartbeatTime);
+                            }
+                            if (object.lastEventTime != null) {
+                                if (typeof object.lastEventTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.lastEventTime: object expected");
+                                message.lastEventTime = $root.google.protobuf.Timestamp.fromObject(object.lastEventTime);
+                            }
+                            if (object.lastStateTime != null) {
+                                if (typeof object.lastStateTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.lastStateTime: object expected");
+                                message.lastStateTime = $root.google.protobuf.Timestamp.fromObject(object.lastStateTime);
+                            }
+                            if (object.lastConfigAckTime != null) {
+                                if (typeof object.lastConfigAckTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.lastConfigAckTime: object expected");
+                                message.lastConfigAckTime = $root.google.protobuf.Timestamp.fromObject(object.lastConfigAckTime);
+                            }
+                            if (object.lastConfigSendTime != null) {
+                                if (typeof object.lastConfigSendTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.lastConfigSendTime: object expected");
+                                message.lastConfigSendTime = $root.google.protobuf.Timestamp.fromObject(object.lastConfigSendTime);
+                            }
+                            if (object.blocked != null)
+                                message.blocked = Boolean(object.blocked);
+                            if (object.lastErrorTime != null) {
+                                if (typeof object.lastErrorTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.lastErrorTime: object expected");
+                                message.lastErrorTime = $root.google.protobuf.Timestamp.fromObject(object.lastErrorTime);
+                            }
+                            if (object.lastErrorStatus != null) {
+                                if (typeof object.lastErrorStatus !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.lastErrorStatus: object expected");
+                                message.lastErrorStatus = $root.google.rpc.Status.fromObject(object.lastErrorStatus);
+                            }
+                            if (object.config != null) {
+                                if (typeof object.config !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.config: object expected");
+                                message.config = $root.google.cloud.iot.v1.DeviceConfig.fromObject(object.config);
+                            }
+                            if (object.state != null) {
+                                if (typeof object.state !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.state: object expected");
+                                message.state = $root.google.cloud.iot.v1.DeviceState.fromObject(object.state);
+                            }
+                            switch (object.logLevel) {
+                            case "LOG_LEVEL_UNSPECIFIED":
+                            case 0:
+                                message.logLevel = 0;
+                                break;
+                            case "NONE":
+                            case 10:
+                                message.logLevel = 10;
+                                break;
+                            case "ERROR":
+                            case 20:
+                                message.logLevel = 20;
+                                break;
+                            case "INFO":
+                            case 30:
+                                message.logLevel = 30;
+                                break;
+                            case "DEBUG":
+                            case 40:
+                                message.logLevel = 40;
+                                break;
+                            }
+                            if (object.metadata) {
+                                if (typeof object.metadata !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.metadata: object expected");
+                                message.metadata = {};
+                                for (var keys = Object.keys(object.metadata), i = 0; i < keys.length; ++i)
+                                    message.metadata[keys[i]] = String(object.metadata[keys[i]]);
+                            }
+                            if (object.gatewayConfig != null) {
+                                if (typeof object.gatewayConfig !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.Device.gatewayConfig: object expected");
+                                message.gatewayConfig = $root.google.cloud.iot.v1.GatewayConfig.fromObject(object.gatewayConfig);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a Device message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.Device
+                         * @static
+                         * @param {google.cloud.iot.v1.Device} message Device
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        Device.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.arrays || options.defaults)
+                                object.credentials = [];
+                            if (options.objects || options.defaults)
+                                object.metadata = {};
+                            if (options.defaults) {
+                                object.id = "";
+                                object.name = "";
+                                if ($util.Long) {
+                                    var long = new $util.Long(0, 0, true);
+                                    object.numId = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+                                } else
+                                    object.numId = options.longs === String ? "0" : 0;
+                                object.lastHeartbeatTime = null;
+                                object.lastEventTime = null;
+                                object.lastErrorTime = null;
+                                object.lastErrorStatus = null;
+                                object.config = null;
+                                object.lastConfigAckTime = null;
+                                object.state = null;
+                                object.lastConfigSendTime = null;
+                                object.blocked = false;
+                                object.lastStateTime = null;
+                                object.logLevel = options.enums === String ? "LOG_LEVEL_UNSPECIFIED" : 0;
+                                object.gatewayConfig = null;
+                            }
+                            if (message.id != null && message.hasOwnProperty("id"))
+                                object.id = message.id;
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            if (message.numId != null && message.hasOwnProperty("numId"))
+                                if (typeof message.numId === "number")
+                                    object.numId = options.longs === String ? String(message.numId) : message.numId;
+                                else
+                                    object.numId = options.longs === String ? $util.Long.prototype.toString.call(message.numId) : options.longs === Number ? new $util.LongBits(message.numId.low >>> 0, message.numId.high >>> 0).toNumber(true) : message.numId;
+                            if (message.lastHeartbeatTime != null && message.hasOwnProperty("lastHeartbeatTime"))
+                                object.lastHeartbeatTime = $root.google.protobuf.Timestamp.toObject(message.lastHeartbeatTime, options);
+                            if (message.lastEventTime != null && message.hasOwnProperty("lastEventTime"))
+                                object.lastEventTime = $root.google.protobuf.Timestamp.toObject(message.lastEventTime, options);
+                            if (message.lastErrorTime != null && message.hasOwnProperty("lastErrorTime"))
+                                object.lastErrorTime = $root.google.protobuf.Timestamp.toObject(message.lastErrorTime, options);
+                            if (message.lastErrorStatus != null && message.hasOwnProperty("lastErrorStatus"))
+                                object.lastErrorStatus = $root.google.rpc.Status.toObject(message.lastErrorStatus, options);
+                            if (message.credentials && message.credentials.length) {
+                                object.credentials = [];
+                                for (var j = 0; j < message.credentials.length; ++j)
+                                    object.credentials[j] = $root.google.cloud.iot.v1.DeviceCredential.toObject(message.credentials[j], options);
+                            }
+                            if (message.config != null && message.hasOwnProperty("config"))
+                                object.config = $root.google.cloud.iot.v1.DeviceConfig.toObject(message.config, options);
+                            if (message.lastConfigAckTime != null && message.hasOwnProperty("lastConfigAckTime"))
+                                object.lastConfigAckTime = $root.google.protobuf.Timestamp.toObject(message.lastConfigAckTime, options);
+                            if (message.state != null && message.hasOwnProperty("state"))
+                                object.state = $root.google.cloud.iot.v1.DeviceState.toObject(message.state, options);
+                            var keys2;
+                            if (message.metadata && (keys2 = Object.keys(message.metadata)).length) {
+                                object.metadata = {};
+                                for (var j = 0; j < keys2.length; ++j)
+                                    object.metadata[keys2[j]] = message.metadata[keys2[j]];
+                            }
+                            if (message.lastConfigSendTime != null && message.hasOwnProperty("lastConfigSendTime"))
+                                object.lastConfigSendTime = $root.google.protobuf.Timestamp.toObject(message.lastConfigSendTime, options);
+                            if (message.blocked != null && message.hasOwnProperty("blocked"))
+                                object.blocked = message.blocked;
+                            if (message.lastStateTime != null && message.hasOwnProperty("lastStateTime"))
+                                object.lastStateTime = $root.google.protobuf.Timestamp.toObject(message.lastStateTime, options);
+                            if (message.logLevel != null && message.hasOwnProperty("logLevel"))
+                                object.logLevel = options.enums === String ? $root.google.cloud.iot.v1.LogLevel[message.logLevel] : message.logLevel;
+                            if (message.gatewayConfig != null && message.hasOwnProperty("gatewayConfig"))
+                                object.gatewayConfig = $root.google.cloud.iot.v1.GatewayConfig.toObject(message.gatewayConfig, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this Device to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.Device
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        Device.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return Device;
+                    })();
+    
+                    v1.GatewayConfig = (function() {
+    
+                        /**
+                         * Properties of a GatewayConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IGatewayConfig
+                         * @property {google.cloud.iot.v1.GatewayType|null} [gatewayType] GatewayConfig gatewayType
+                         * @property {google.cloud.iot.v1.GatewayAuthMethod|null} [gatewayAuthMethod] GatewayConfig gatewayAuthMethod
+                         * @property {string|null} [lastAccessedGatewayId] GatewayConfig lastAccessedGatewayId
+                         * @property {google.protobuf.ITimestamp|null} [lastAccessedGatewayTime] GatewayConfig lastAccessedGatewayTime
+                         */
+    
+                        /**
+                         * Constructs a new GatewayConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a GatewayConfig.
+                         * @implements IGatewayConfig
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IGatewayConfig=} [properties] Properties to set
+                         */
+                        function GatewayConfig(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * GatewayConfig gatewayType.
+                         * @member {google.cloud.iot.v1.GatewayType} gatewayType
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @instance
+                         */
+                        GatewayConfig.prototype.gatewayType = 0;
+    
+                        /**
+                         * GatewayConfig gatewayAuthMethod.
+                         * @member {google.cloud.iot.v1.GatewayAuthMethod} gatewayAuthMethod
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @instance
+                         */
+                        GatewayConfig.prototype.gatewayAuthMethod = 0;
+    
+                        /**
+                         * GatewayConfig lastAccessedGatewayId.
+                         * @member {string} lastAccessedGatewayId
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @instance
+                         */
+                        GatewayConfig.prototype.lastAccessedGatewayId = "";
+    
+                        /**
+                         * GatewayConfig lastAccessedGatewayTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} lastAccessedGatewayTime
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @instance
+                         */
+                        GatewayConfig.prototype.lastAccessedGatewayTime = null;
+    
+                        /**
+                         * Creates a new GatewayConfig instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IGatewayConfig=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.GatewayConfig} GatewayConfig instance
+                         */
+                        GatewayConfig.create = function create(properties) {
+                            return new GatewayConfig(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified GatewayConfig message. Does not implicitly {@link google.cloud.iot.v1.GatewayConfig.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IGatewayConfig} message GatewayConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GatewayConfig.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.gatewayType != null && Object.hasOwnProperty.call(message, "gatewayType"))
+                                writer.uint32(/* id 1, wireType 0 =*/8).int32(message.gatewayType);
+                            if (message.gatewayAuthMethod != null && Object.hasOwnProperty.call(message, "gatewayAuthMethod"))
+                                writer.uint32(/* id 2, wireType 0 =*/16).int32(message.gatewayAuthMethod);
+                            if (message.lastAccessedGatewayId != null && Object.hasOwnProperty.call(message, "lastAccessedGatewayId"))
+                                writer.uint32(/* id 3, wireType 2 =*/26).string(message.lastAccessedGatewayId);
+                            if (message.lastAccessedGatewayTime != null && Object.hasOwnProperty.call(message, "lastAccessedGatewayTime"))
+                                $root.google.protobuf.Timestamp.encode(message.lastAccessedGatewayTime, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified GatewayConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.GatewayConfig.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IGatewayConfig} message GatewayConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        GatewayConfig.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a GatewayConfig message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.GatewayConfig} GatewayConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GatewayConfig.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.GatewayConfig();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.gatewayType = reader.int32();
+                                    break;
+                                case 2:
+                                    message.gatewayAuthMethod = reader.int32();
+                                    break;
+                                case 3:
+                                    message.lastAccessedGatewayId = reader.string();
+                                    break;
+                                case 4:
+                                    message.lastAccessedGatewayTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a GatewayConfig message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.GatewayConfig} GatewayConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        GatewayConfig.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a GatewayConfig message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        GatewayConfig.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.gatewayType != null && message.hasOwnProperty("gatewayType"))
+                                switch (message.gatewayType) {
+                                default:
+                                    return "gatewayType: enum value expected";
+                                case 0:
+                                case 1:
+                                case 2:
+                                    break;
+                                }
+                            if (message.gatewayAuthMethod != null && message.hasOwnProperty("gatewayAuthMethod"))
+                                switch (message.gatewayAuthMethod) {
+                                default:
+                                    return "gatewayAuthMethod: enum value expected";
+                                case 0:
+                                case 1:
+                                case 2:
+                                case 3:
+                                    break;
+                                }
+                            if (message.lastAccessedGatewayId != null && message.hasOwnProperty("lastAccessedGatewayId"))
+                                if (!$util.isString(message.lastAccessedGatewayId))
+                                    return "lastAccessedGatewayId: string expected";
+                            if (message.lastAccessedGatewayTime != null && message.hasOwnProperty("lastAccessedGatewayTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.lastAccessedGatewayTime);
+                                if (error)
+                                    return "lastAccessedGatewayTime." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a GatewayConfig message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.GatewayConfig} GatewayConfig
+                         */
+                        GatewayConfig.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.GatewayConfig)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.GatewayConfig();
+                            switch (object.gatewayType) {
+                            case "GATEWAY_TYPE_UNSPECIFIED":
+                            case 0:
+                                message.gatewayType = 0;
+                                break;
+                            case "GATEWAY":
+                            case 1:
+                                message.gatewayType = 1;
+                                break;
+                            case "NON_GATEWAY":
+                            case 2:
+                                message.gatewayType = 2;
+                                break;
+                            }
+                            switch (object.gatewayAuthMethod) {
+                            case "GATEWAY_AUTH_METHOD_UNSPECIFIED":
+                            case 0:
+                                message.gatewayAuthMethod = 0;
+                                break;
+                            case "ASSOCIATION_ONLY":
+                            case 1:
+                                message.gatewayAuthMethod = 1;
+                                break;
+                            case "DEVICE_AUTH_TOKEN_ONLY":
+                            case 2:
+                                message.gatewayAuthMethod = 2;
+                                break;
+                            case "ASSOCIATION_AND_DEVICE_AUTH_TOKEN":
+                            case 3:
+                                message.gatewayAuthMethod = 3;
+                                break;
+                            }
+                            if (object.lastAccessedGatewayId != null)
+                                message.lastAccessedGatewayId = String(object.lastAccessedGatewayId);
+                            if (object.lastAccessedGatewayTime != null) {
+                                if (typeof object.lastAccessedGatewayTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.GatewayConfig.lastAccessedGatewayTime: object expected");
+                                message.lastAccessedGatewayTime = $root.google.protobuf.Timestamp.fromObject(object.lastAccessedGatewayTime);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a GatewayConfig message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.GatewayConfig} message GatewayConfig
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        GatewayConfig.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.gatewayType = options.enums === String ? "GATEWAY_TYPE_UNSPECIFIED" : 0;
+                                object.gatewayAuthMethod = options.enums === String ? "GATEWAY_AUTH_METHOD_UNSPECIFIED" : 0;
+                                object.lastAccessedGatewayId = "";
+                                object.lastAccessedGatewayTime = null;
+                            }
+                            if (message.gatewayType != null && message.hasOwnProperty("gatewayType"))
+                                object.gatewayType = options.enums === String ? $root.google.cloud.iot.v1.GatewayType[message.gatewayType] : message.gatewayType;
+                            if (message.gatewayAuthMethod != null && message.hasOwnProperty("gatewayAuthMethod"))
+                                object.gatewayAuthMethod = options.enums === String ? $root.google.cloud.iot.v1.GatewayAuthMethod[message.gatewayAuthMethod] : message.gatewayAuthMethod;
+                            if (message.lastAccessedGatewayId != null && message.hasOwnProperty("lastAccessedGatewayId"))
+                                object.lastAccessedGatewayId = message.lastAccessedGatewayId;
+                            if (message.lastAccessedGatewayTime != null && message.hasOwnProperty("lastAccessedGatewayTime"))
+                                object.lastAccessedGatewayTime = $root.google.protobuf.Timestamp.toObject(message.lastAccessedGatewayTime, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this GatewayConfig to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.GatewayConfig
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        GatewayConfig.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return GatewayConfig;
+                    })();
+    
+                    v1.DeviceRegistry = (function() {
+    
+                        /**
+                         * Properties of a DeviceRegistry.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IDeviceRegistry
+                         * @property {string|null} [id] DeviceRegistry id
+                         * @property {string|null} [name] DeviceRegistry name
+                         * @property {Array.<google.cloud.iot.v1.IEventNotificationConfig>|null} [eventNotificationConfigs] DeviceRegistry eventNotificationConfigs
+                         * @property {google.cloud.iot.v1.IStateNotificationConfig|null} [stateNotificationConfig] DeviceRegistry stateNotificationConfig
+                         * @property {google.cloud.iot.v1.IMqttConfig|null} [mqttConfig] DeviceRegistry mqttConfig
+                         * @property {google.cloud.iot.v1.IHttpConfig|null} [httpConfig] DeviceRegistry httpConfig
+                         * @property {google.cloud.iot.v1.LogLevel|null} [logLevel] DeviceRegistry logLevel
+                         * @property {Array.<google.cloud.iot.v1.IRegistryCredential>|null} [credentials] DeviceRegistry credentials
+                         */
+    
+                        /**
+                         * Constructs a new DeviceRegistry.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a DeviceRegistry.
+                         * @implements IDeviceRegistry
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IDeviceRegistry=} [properties] Properties to set
+                         */
+                        function DeviceRegistry(properties) {
+                            this.eventNotificationConfigs = [];
+                            this.credentials = [];
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * DeviceRegistry id.
+                         * @member {string} id
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.id = "";
+    
+                        /**
+                         * DeviceRegistry name.
+                         * @member {string} name
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.name = "";
+    
+                        /**
+                         * DeviceRegistry eventNotificationConfigs.
+                         * @member {Array.<google.cloud.iot.v1.IEventNotificationConfig>} eventNotificationConfigs
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.eventNotificationConfigs = $util.emptyArray;
+    
+                        /**
+                         * DeviceRegistry stateNotificationConfig.
+                         * @member {google.cloud.iot.v1.IStateNotificationConfig|null|undefined} stateNotificationConfig
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.stateNotificationConfig = null;
+    
+                        /**
+                         * DeviceRegistry mqttConfig.
+                         * @member {google.cloud.iot.v1.IMqttConfig|null|undefined} mqttConfig
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.mqttConfig = null;
+    
+                        /**
+                         * DeviceRegistry httpConfig.
+                         * @member {google.cloud.iot.v1.IHttpConfig|null|undefined} httpConfig
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.httpConfig = null;
+    
+                        /**
+                         * DeviceRegistry logLevel.
+                         * @member {google.cloud.iot.v1.LogLevel} logLevel
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.logLevel = 0;
+    
+                        /**
+                         * DeviceRegistry credentials.
+                         * @member {Array.<google.cloud.iot.v1.IRegistryCredential>} credentials
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         */
+                        DeviceRegistry.prototype.credentials = $util.emptyArray;
+    
+                        /**
+                         * Creates a new DeviceRegistry instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceRegistry=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.DeviceRegistry} DeviceRegistry instance
+                         */
+                        DeviceRegistry.create = function create(properties) {
+                            return new DeviceRegistry(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceRegistry message. Does not implicitly {@link google.cloud.iot.v1.DeviceRegistry.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceRegistry} message DeviceRegistry message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceRegistry.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.id != null && Object.hasOwnProperty.call(message, "id"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.id);
+                            if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.name);
+                            if (message.mqttConfig != null && Object.hasOwnProperty.call(message, "mqttConfig"))
+                                $root.google.cloud.iot.v1.MqttConfig.encode(message.mqttConfig, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                            if (message.stateNotificationConfig != null && Object.hasOwnProperty.call(message, "stateNotificationConfig"))
+                                $root.google.cloud.iot.v1.StateNotificationConfig.encode(message.stateNotificationConfig, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
+                            if (message.credentials != null && message.credentials.length)
+                                for (var i = 0; i < message.credentials.length; ++i)
+                                    $root.google.cloud.iot.v1.RegistryCredential.encode(message.credentials[i], writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
+                            if (message.httpConfig != null && Object.hasOwnProperty.call(message, "httpConfig"))
+                                $root.google.cloud.iot.v1.HttpConfig.encode(message.httpConfig, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim();
+                            if (message.eventNotificationConfigs != null && message.eventNotificationConfigs.length)
+                                for (var i = 0; i < message.eventNotificationConfigs.length; ++i)
+                                    $root.google.cloud.iot.v1.EventNotificationConfig.encode(message.eventNotificationConfigs[i], writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim();
+                            if (message.logLevel != null && Object.hasOwnProperty.call(message, "logLevel"))
+                                writer.uint32(/* id 11, wireType 0 =*/88).int32(message.logLevel);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceRegistry message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceRegistry.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceRegistry} message DeviceRegistry message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceRegistry.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a DeviceRegistry message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.DeviceRegistry} DeviceRegistry
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceRegistry.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.DeviceRegistry();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.id = reader.string();
+                                    break;
+                                case 2:
+                                    message.name = reader.string();
+                                    break;
+                                case 10:
+                                    if (!(message.eventNotificationConfigs && message.eventNotificationConfigs.length))
+                                        message.eventNotificationConfigs = [];
+                                    message.eventNotificationConfigs.push($root.google.cloud.iot.v1.EventNotificationConfig.decode(reader, reader.uint32()));
+                                    break;
+                                case 7:
+                                    message.stateNotificationConfig = $root.google.cloud.iot.v1.StateNotificationConfig.decode(reader, reader.uint32());
+                                    break;
+                                case 4:
+                                    message.mqttConfig = $root.google.cloud.iot.v1.MqttConfig.decode(reader, reader.uint32());
+                                    break;
+                                case 9:
+                                    message.httpConfig = $root.google.cloud.iot.v1.HttpConfig.decode(reader, reader.uint32());
+                                    break;
+                                case 11:
+                                    message.logLevel = reader.int32();
+                                    break;
+                                case 8:
+                                    if (!(message.credentials && message.credentials.length))
+                                        message.credentials = [];
+                                    message.credentials.push($root.google.cloud.iot.v1.RegistryCredential.decode(reader, reader.uint32()));
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a DeviceRegistry message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.DeviceRegistry} DeviceRegistry
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceRegistry.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a DeviceRegistry message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        DeviceRegistry.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.id != null && message.hasOwnProperty("id"))
+                                if (!$util.isString(message.id))
+                                    return "id: string expected";
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                if (!$util.isString(message.name))
+                                    return "name: string expected";
+                            if (message.eventNotificationConfigs != null && message.hasOwnProperty("eventNotificationConfigs")) {
+                                if (!Array.isArray(message.eventNotificationConfigs))
+                                    return "eventNotificationConfigs: array expected";
+                                for (var i = 0; i < message.eventNotificationConfigs.length; ++i) {
+                                    var error = $root.google.cloud.iot.v1.EventNotificationConfig.verify(message.eventNotificationConfigs[i]);
+                                    if (error)
+                                        return "eventNotificationConfigs." + error;
+                                }
+                            }
+                            if (message.stateNotificationConfig != null && message.hasOwnProperty("stateNotificationConfig")) {
+                                var error = $root.google.cloud.iot.v1.StateNotificationConfig.verify(message.stateNotificationConfig);
+                                if (error)
+                                    return "stateNotificationConfig." + error;
+                            }
+                            if (message.mqttConfig != null && message.hasOwnProperty("mqttConfig")) {
+                                var error = $root.google.cloud.iot.v1.MqttConfig.verify(message.mqttConfig);
+                                if (error)
+                                    return "mqttConfig." + error;
+                            }
+                            if (message.httpConfig != null && message.hasOwnProperty("httpConfig")) {
+                                var error = $root.google.cloud.iot.v1.HttpConfig.verify(message.httpConfig);
+                                if (error)
+                                    return "httpConfig." + error;
+                            }
+                            if (message.logLevel != null && message.hasOwnProperty("logLevel"))
+                                switch (message.logLevel) {
+                                default:
+                                    return "logLevel: enum value expected";
+                                case 0:
+                                case 10:
+                                case 20:
+                                case 30:
+                                case 40:
+                                    break;
+                                }
+                            if (message.credentials != null && message.hasOwnProperty("credentials")) {
+                                if (!Array.isArray(message.credentials))
+                                    return "credentials: array expected";
+                                for (var i = 0; i < message.credentials.length; ++i) {
+                                    var error = $root.google.cloud.iot.v1.RegistryCredential.verify(message.credentials[i]);
+                                    if (error)
+                                        return "credentials." + error;
+                                }
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a DeviceRegistry message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.DeviceRegistry} DeviceRegistry
+                         */
+                        DeviceRegistry.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.DeviceRegistry)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.DeviceRegistry();
+                            if (object.id != null)
+                                message.id = String(object.id);
+                            if (object.name != null)
+                                message.name = String(object.name);
+                            if (object.eventNotificationConfigs) {
+                                if (!Array.isArray(object.eventNotificationConfigs))
+                                    throw TypeError(".google.cloud.iot.v1.DeviceRegistry.eventNotificationConfigs: array expected");
+                                message.eventNotificationConfigs = [];
+                                for (var i = 0; i < object.eventNotificationConfigs.length; ++i) {
+                                    if (typeof object.eventNotificationConfigs[i] !== "object")
+                                        throw TypeError(".google.cloud.iot.v1.DeviceRegistry.eventNotificationConfigs: object expected");
+                                    message.eventNotificationConfigs[i] = $root.google.cloud.iot.v1.EventNotificationConfig.fromObject(object.eventNotificationConfigs[i]);
+                                }
+                            }
+                            if (object.stateNotificationConfig != null) {
+                                if (typeof object.stateNotificationConfig !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceRegistry.stateNotificationConfig: object expected");
+                                message.stateNotificationConfig = $root.google.cloud.iot.v1.StateNotificationConfig.fromObject(object.stateNotificationConfig);
+                            }
+                            if (object.mqttConfig != null) {
+                                if (typeof object.mqttConfig !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceRegistry.mqttConfig: object expected");
+                                message.mqttConfig = $root.google.cloud.iot.v1.MqttConfig.fromObject(object.mqttConfig);
+                            }
+                            if (object.httpConfig != null) {
+                                if (typeof object.httpConfig !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceRegistry.httpConfig: object expected");
+                                message.httpConfig = $root.google.cloud.iot.v1.HttpConfig.fromObject(object.httpConfig);
+                            }
+                            switch (object.logLevel) {
+                            case "LOG_LEVEL_UNSPECIFIED":
+                            case 0:
+                                message.logLevel = 0;
+                                break;
+                            case "NONE":
+                            case 10:
+                                message.logLevel = 10;
+                                break;
+                            case "ERROR":
+                            case 20:
+                                message.logLevel = 20;
+                                break;
+                            case "INFO":
+                            case 30:
+                                message.logLevel = 30;
+                                break;
+                            case "DEBUG":
+                            case 40:
+                                message.logLevel = 40;
+                                break;
+                            }
+                            if (object.credentials) {
+                                if (!Array.isArray(object.credentials))
+                                    throw TypeError(".google.cloud.iot.v1.DeviceRegistry.credentials: array expected");
+                                message.credentials = [];
+                                for (var i = 0; i < object.credentials.length; ++i) {
+                                    if (typeof object.credentials[i] !== "object")
+                                        throw TypeError(".google.cloud.iot.v1.DeviceRegistry.credentials: object expected");
+                                    message.credentials[i] = $root.google.cloud.iot.v1.RegistryCredential.fromObject(object.credentials[i]);
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a DeviceRegistry message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @static
+                         * @param {google.cloud.iot.v1.DeviceRegistry} message DeviceRegistry
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        DeviceRegistry.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.arrays || options.defaults) {
+                                object.credentials = [];
+                                object.eventNotificationConfigs = [];
+                            }
+                            if (options.defaults) {
+                                object.id = "";
+                                object.name = "";
+                                object.mqttConfig = null;
+                                object.stateNotificationConfig = null;
+                                object.httpConfig = null;
+                                object.logLevel = options.enums === String ? "LOG_LEVEL_UNSPECIFIED" : 0;
+                            }
+                            if (message.id != null && message.hasOwnProperty("id"))
+                                object.id = message.id;
+                            if (message.name != null && message.hasOwnProperty("name"))
+                                object.name = message.name;
+                            if (message.mqttConfig != null && message.hasOwnProperty("mqttConfig"))
+                                object.mqttConfig = $root.google.cloud.iot.v1.MqttConfig.toObject(message.mqttConfig, options);
+                            if (message.stateNotificationConfig != null && message.hasOwnProperty("stateNotificationConfig"))
+                                object.stateNotificationConfig = $root.google.cloud.iot.v1.StateNotificationConfig.toObject(message.stateNotificationConfig, options);
+                            if (message.credentials && message.credentials.length) {
+                                object.credentials = [];
+                                for (var j = 0; j < message.credentials.length; ++j)
+                                    object.credentials[j] = $root.google.cloud.iot.v1.RegistryCredential.toObject(message.credentials[j], options);
+                            }
+                            if (message.httpConfig != null && message.hasOwnProperty("httpConfig"))
+                                object.httpConfig = $root.google.cloud.iot.v1.HttpConfig.toObject(message.httpConfig, options);
+                            if (message.eventNotificationConfigs && message.eventNotificationConfigs.length) {
+                                object.eventNotificationConfigs = [];
+                                for (var j = 0; j < message.eventNotificationConfigs.length; ++j)
+                                    object.eventNotificationConfigs[j] = $root.google.cloud.iot.v1.EventNotificationConfig.toObject(message.eventNotificationConfigs[j], options);
+                            }
+                            if (message.logLevel != null && message.hasOwnProperty("logLevel"))
+                                object.logLevel = options.enums === String ? $root.google.cloud.iot.v1.LogLevel[message.logLevel] : message.logLevel;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this DeviceRegistry to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.DeviceRegistry
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        DeviceRegistry.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return DeviceRegistry;
+                    })();
+    
+                    v1.MqttConfig = (function() {
+    
+                        /**
+                         * Properties of a MqttConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IMqttConfig
+                         * @property {google.cloud.iot.v1.MqttState|null} [mqttEnabledState] MqttConfig mqttEnabledState
+                         */
+    
+                        /**
+                         * Constructs a new MqttConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a MqttConfig.
+                         * @implements IMqttConfig
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IMqttConfig=} [properties] Properties to set
+                         */
+                        function MqttConfig(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * MqttConfig mqttEnabledState.
+                         * @member {google.cloud.iot.v1.MqttState} mqttEnabledState
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @instance
+                         */
+                        MqttConfig.prototype.mqttEnabledState = 0;
+    
+                        /**
+                         * Creates a new MqttConfig instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IMqttConfig=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.MqttConfig} MqttConfig instance
+                         */
+                        MqttConfig.create = function create(properties) {
+                            return new MqttConfig(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified MqttConfig message. Does not implicitly {@link google.cloud.iot.v1.MqttConfig.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IMqttConfig} message MqttConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        MqttConfig.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.mqttEnabledState != null && Object.hasOwnProperty.call(message, "mqttEnabledState"))
+                                writer.uint32(/* id 1, wireType 0 =*/8).int32(message.mqttEnabledState);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified MqttConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.MqttConfig.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IMqttConfig} message MqttConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        MqttConfig.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a MqttConfig message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.MqttConfig} MqttConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        MqttConfig.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.MqttConfig();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.mqttEnabledState = reader.int32();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a MqttConfig message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.MqttConfig} MqttConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        MqttConfig.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a MqttConfig message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        MqttConfig.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.mqttEnabledState != null && message.hasOwnProperty("mqttEnabledState"))
+                                switch (message.mqttEnabledState) {
+                                default:
+                                    return "mqttEnabledState: enum value expected";
+                                case 0:
+                                case 1:
+                                case 2:
+                                    break;
+                                }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a MqttConfig message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.MqttConfig} MqttConfig
+                         */
+                        MqttConfig.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.MqttConfig)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.MqttConfig();
+                            switch (object.mqttEnabledState) {
+                            case "MQTT_STATE_UNSPECIFIED":
+                            case 0:
+                                message.mqttEnabledState = 0;
+                                break;
+                            case "MQTT_ENABLED":
+                            case 1:
+                                message.mqttEnabledState = 1;
+                                break;
+                            case "MQTT_DISABLED":
+                            case 2:
+                                message.mqttEnabledState = 2;
+                                break;
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a MqttConfig message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.MqttConfig} message MqttConfig
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        MqttConfig.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults)
+                                object.mqttEnabledState = options.enums === String ? "MQTT_STATE_UNSPECIFIED" : 0;
+                            if (message.mqttEnabledState != null && message.hasOwnProperty("mqttEnabledState"))
+                                object.mqttEnabledState = options.enums === String ? $root.google.cloud.iot.v1.MqttState[message.mqttEnabledState] : message.mqttEnabledState;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this MqttConfig to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.MqttConfig
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        MqttConfig.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return MqttConfig;
+                    })();
+    
+                    /**
+                     * MqttState enum.
+                     * @name google.cloud.iot.v1.MqttState
+                     * @enum {number}
+                     * @property {number} MQTT_STATE_UNSPECIFIED=0 MQTT_STATE_UNSPECIFIED value
+                     * @property {number} MQTT_ENABLED=1 MQTT_ENABLED value
+                     * @property {number} MQTT_DISABLED=2 MQTT_DISABLED value
+                     */
+                    v1.MqttState = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "MQTT_STATE_UNSPECIFIED"] = 0;
+                        values[valuesById[1] = "MQTT_ENABLED"] = 1;
+                        values[valuesById[2] = "MQTT_DISABLED"] = 2;
+                        return values;
+                    })();
+    
+                    v1.HttpConfig = (function() {
+    
+                        /**
+                         * Properties of a HttpConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IHttpConfig
+                         * @property {google.cloud.iot.v1.HttpState|null} [httpEnabledState] HttpConfig httpEnabledState
+                         */
+    
+                        /**
+                         * Constructs a new HttpConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a HttpConfig.
+                         * @implements IHttpConfig
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IHttpConfig=} [properties] Properties to set
+                         */
+                        function HttpConfig(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * HttpConfig httpEnabledState.
+                         * @member {google.cloud.iot.v1.HttpState} httpEnabledState
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @instance
+                         */
+                        HttpConfig.prototype.httpEnabledState = 0;
+    
+                        /**
+                         * Creates a new HttpConfig instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IHttpConfig=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.HttpConfig} HttpConfig instance
+                         */
+                        HttpConfig.create = function create(properties) {
+                            return new HttpConfig(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified HttpConfig message. Does not implicitly {@link google.cloud.iot.v1.HttpConfig.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IHttpConfig} message HttpConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        HttpConfig.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.httpEnabledState != null && Object.hasOwnProperty.call(message, "httpEnabledState"))
+                                writer.uint32(/* id 1, wireType 0 =*/8).int32(message.httpEnabledState);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified HttpConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.HttpConfig.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IHttpConfig} message HttpConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        HttpConfig.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a HttpConfig message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.HttpConfig} HttpConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        HttpConfig.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.HttpConfig();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.httpEnabledState = reader.int32();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a HttpConfig message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.HttpConfig} HttpConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        HttpConfig.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a HttpConfig message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        HttpConfig.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.httpEnabledState != null && message.hasOwnProperty("httpEnabledState"))
+                                switch (message.httpEnabledState) {
+                                default:
+                                    return "httpEnabledState: enum value expected";
+                                case 0:
+                                case 1:
+                                case 2:
+                                    break;
+                                }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a HttpConfig message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.HttpConfig} HttpConfig
+                         */
+                        HttpConfig.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.HttpConfig)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.HttpConfig();
+                            switch (object.httpEnabledState) {
+                            case "HTTP_STATE_UNSPECIFIED":
+                            case 0:
+                                message.httpEnabledState = 0;
+                                break;
+                            case "HTTP_ENABLED":
+                            case 1:
+                                message.httpEnabledState = 1;
+                                break;
+                            case "HTTP_DISABLED":
+                            case 2:
+                                message.httpEnabledState = 2;
+                                break;
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a HttpConfig message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.HttpConfig} message HttpConfig
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        HttpConfig.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults)
+                                object.httpEnabledState = options.enums === String ? "HTTP_STATE_UNSPECIFIED" : 0;
+                            if (message.httpEnabledState != null && message.hasOwnProperty("httpEnabledState"))
+                                object.httpEnabledState = options.enums === String ? $root.google.cloud.iot.v1.HttpState[message.httpEnabledState] : message.httpEnabledState;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this HttpConfig to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.HttpConfig
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        HttpConfig.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return HttpConfig;
+                    })();
+    
+                    /**
+                     * HttpState enum.
+                     * @name google.cloud.iot.v1.HttpState
+                     * @enum {number}
+                     * @property {number} HTTP_STATE_UNSPECIFIED=0 HTTP_STATE_UNSPECIFIED value
+                     * @property {number} HTTP_ENABLED=1 HTTP_ENABLED value
+                     * @property {number} HTTP_DISABLED=2 HTTP_DISABLED value
+                     */
+                    v1.HttpState = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "HTTP_STATE_UNSPECIFIED"] = 0;
+                        values[valuesById[1] = "HTTP_ENABLED"] = 1;
+                        values[valuesById[2] = "HTTP_DISABLED"] = 2;
+                        return values;
+                    })();
+    
+                    /**
+                     * LogLevel enum.
+                     * @name google.cloud.iot.v1.LogLevel
+                     * @enum {number}
+                     * @property {number} LOG_LEVEL_UNSPECIFIED=0 LOG_LEVEL_UNSPECIFIED value
+                     * @property {number} NONE=10 NONE value
+                     * @property {number} ERROR=20 ERROR value
+                     * @property {number} INFO=30 INFO value
+                     * @property {number} DEBUG=40 DEBUG value
+                     */
+                    v1.LogLevel = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "LOG_LEVEL_UNSPECIFIED"] = 0;
+                        values[valuesById[10] = "NONE"] = 10;
+                        values[valuesById[20] = "ERROR"] = 20;
+                        values[valuesById[30] = "INFO"] = 30;
+                        values[valuesById[40] = "DEBUG"] = 40;
+                        return values;
+                    })();
+    
+                    /**
+                     * GatewayType enum.
+                     * @name google.cloud.iot.v1.GatewayType
+                     * @enum {number}
+                     * @property {number} GATEWAY_TYPE_UNSPECIFIED=0 GATEWAY_TYPE_UNSPECIFIED value
+                     * @property {number} GATEWAY=1 GATEWAY value
+                     * @property {number} NON_GATEWAY=2 NON_GATEWAY value
+                     */
+                    v1.GatewayType = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "GATEWAY_TYPE_UNSPECIFIED"] = 0;
+                        values[valuesById[1] = "GATEWAY"] = 1;
+                        values[valuesById[2] = "NON_GATEWAY"] = 2;
+                        return values;
+                    })();
+    
+                    /**
+                     * GatewayAuthMethod enum.
+                     * @name google.cloud.iot.v1.GatewayAuthMethod
+                     * @enum {number}
+                     * @property {number} GATEWAY_AUTH_METHOD_UNSPECIFIED=0 GATEWAY_AUTH_METHOD_UNSPECIFIED value
+                     * @property {number} ASSOCIATION_ONLY=1 ASSOCIATION_ONLY value
+                     * @property {number} DEVICE_AUTH_TOKEN_ONLY=2 DEVICE_AUTH_TOKEN_ONLY value
+                     * @property {number} ASSOCIATION_AND_DEVICE_AUTH_TOKEN=3 ASSOCIATION_AND_DEVICE_AUTH_TOKEN value
+                     */
+                    v1.GatewayAuthMethod = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "GATEWAY_AUTH_METHOD_UNSPECIFIED"] = 0;
+                        values[valuesById[1] = "ASSOCIATION_ONLY"] = 1;
+                        values[valuesById[2] = "DEVICE_AUTH_TOKEN_ONLY"] = 2;
+                        values[valuesById[3] = "ASSOCIATION_AND_DEVICE_AUTH_TOKEN"] = 3;
+                        return values;
+                    })();
+    
+                    v1.EventNotificationConfig = (function() {
+    
+                        /**
+                         * Properties of an EventNotificationConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IEventNotificationConfig
+                         * @property {string|null} [subfolderMatches] EventNotificationConfig subfolderMatches
+                         * @property {string|null} [pubsubTopicName] EventNotificationConfig pubsubTopicName
+                         */
+    
+                        /**
+                         * Constructs a new EventNotificationConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents an EventNotificationConfig.
+                         * @implements IEventNotificationConfig
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IEventNotificationConfig=} [properties] Properties to set
+                         */
+                        function EventNotificationConfig(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * EventNotificationConfig subfolderMatches.
+                         * @member {string} subfolderMatches
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @instance
+                         */
+                        EventNotificationConfig.prototype.subfolderMatches = "";
+    
+                        /**
+                         * EventNotificationConfig pubsubTopicName.
+                         * @member {string} pubsubTopicName
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @instance
+                         */
+                        EventNotificationConfig.prototype.pubsubTopicName = "";
+    
+                        /**
+                         * Creates a new EventNotificationConfig instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IEventNotificationConfig=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.EventNotificationConfig} EventNotificationConfig instance
+                         */
+                        EventNotificationConfig.create = function create(properties) {
+                            return new EventNotificationConfig(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified EventNotificationConfig message. Does not implicitly {@link google.cloud.iot.v1.EventNotificationConfig.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IEventNotificationConfig} message EventNotificationConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        EventNotificationConfig.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.pubsubTopicName != null && Object.hasOwnProperty.call(message, "pubsubTopicName"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.pubsubTopicName);
+                            if (message.subfolderMatches != null && Object.hasOwnProperty.call(message, "subfolderMatches"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.subfolderMatches);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified EventNotificationConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.EventNotificationConfig.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IEventNotificationConfig} message EventNotificationConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        EventNotificationConfig.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes an EventNotificationConfig message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.EventNotificationConfig} EventNotificationConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        EventNotificationConfig.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.EventNotificationConfig();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 2:
+                                    message.subfolderMatches = reader.string();
+                                    break;
+                                case 1:
+                                    message.pubsubTopicName = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes an EventNotificationConfig message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.EventNotificationConfig} EventNotificationConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        EventNotificationConfig.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies an EventNotificationConfig message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        EventNotificationConfig.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.subfolderMatches != null && message.hasOwnProperty("subfolderMatches"))
+                                if (!$util.isString(message.subfolderMatches))
+                                    return "subfolderMatches: string expected";
+                            if (message.pubsubTopicName != null && message.hasOwnProperty("pubsubTopicName"))
+                                if (!$util.isString(message.pubsubTopicName))
+                                    return "pubsubTopicName: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates an EventNotificationConfig message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.EventNotificationConfig} EventNotificationConfig
+                         */
+                        EventNotificationConfig.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.EventNotificationConfig)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.EventNotificationConfig();
+                            if (object.subfolderMatches != null)
+                                message.subfolderMatches = String(object.subfolderMatches);
+                            if (object.pubsubTopicName != null)
+                                message.pubsubTopicName = String(object.pubsubTopicName);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from an EventNotificationConfig message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.EventNotificationConfig} message EventNotificationConfig
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        EventNotificationConfig.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.pubsubTopicName = "";
+                                object.subfolderMatches = "";
+                            }
+                            if (message.pubsubTopicName != null && message.hasOwnProperty("pubsubTopicName"))
+                                object.pubsubTopicName = message.pubsubTopicName;
+                            if (message.subfolderMatches != null && message.hasOwnProperty("subfolderMatches"))
+                                object.subfolderMatches = message.subfolderMatches;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this EventNotificationConfig to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.EventNotificationConfig
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        EventNotificationConfig.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return EventNotificationConfig;
+                    })();
+    
+                    v1.StateNotificationConfig = (function() {
+    
+                        /**
+                         * Properties of a StateNotificationConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IStateNotificationConfig
+                         * @property {string|null} [pubsubTopicName] StateNotificationConfig pubsubTopicName
+                         */
+    
+                        /**
+                         * Constructs a new StateNotificationConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a StateNotificationConfig.
+                         * @implements IStateNotificationConfig
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IStateNotificationConfig=} [properties] Properties to set
+                         */
+                        function StateNotificationConfig(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * StateNotificationConfig pubsubTopicName.
+                         * @member {string} pubsubTopicName
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @instance
+                         */
+                        StateNotificationConfig.prototype.pubsubTopicName = "";
+    
+                        /**
+                         * Creates a new StateNotificationConfig instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IStateNotificationConfig=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.StateNotificationConfig} StateNotificationConfig instance
+                         */
+                        StateNotificationConfig.create = function create(properties) {
+                            return new StateNotificationConfig(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified StateNotificationConfig message. Does not implicitly {@link google.cloud.iot.v1.StateNotificationConfig.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IStateNotificationConfig} message StateNotificationConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        StateNotificationConfig.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.pubsubTopicName != null && Object.hasOwnProperty.call(message, "pubsubTopicName"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.pubsubTopicName);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified StateNotificationConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.StateNotificationConfig.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IStateNotificationConfig} message StateNotificationConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        StateNotificationConfig.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a StateNotificationConfig message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.StateNotificationConfig} StateNotificationConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        StateNotificationConfig.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.StateNotificationConfig();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.pubsubTopicName = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a StateNotificationConfig message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.StateNotificationConfig} StateNotificationConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        StateNotificationConfig.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a StateNotificationConfig message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        StateNotificationConfig.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.pubsubTopicName != null && message.hasOwnProperty("pubsubTopicName"))
+                                if (!$util.isString(message.pubsubTopicName))
+                                    return "pubsubTopicName: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a StateNotificationConfig message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.StateNotificationConfig} StateNotificationConfig
+                         */
+                        StateNotificationConfig.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.StateNotificationConfig)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.StateNotificationConfig();
+                            if (object.pubsubTopicName != null)
+                                message.pubsubTopicName = String(object.pubsubTopicName);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a StateNotificationConfig message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.StateNotificationConfig} message StateNotificationConfig
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        StateNotificationConfig.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults)
+                                object.pubsubTopicName = "";
+                            if (message.pubsubTopicName != null && message.hasOwnProperty("pubsubTopicName"))
+                                object.pubsubTopicName = message.pubsubTopicName;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this StateNotificationConfig to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.StateNotificationConfig
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        StateNotificationConfig.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return StateNotificationConfig;
+                    })();
+    
+                    v1.RegistryCredential = (function() {
+    
+                        /**
+                         * Properties of a RegistryCredential.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IRegistryCredential
+                         * @property {google.cloud.iot.v1.IPublicKeyCertificate|null} [publicKeyCertificate] RegistryCredential publicKeyCertificate
+                         */
+    
+                        /**
+                         * Constructs a new RegistryCredential.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a RegistryCredential.
+                         * @implements IRegistryCredential
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IRegistryCredential=} [properties] Properties to set
+                         */
+                        function RegistryCredential(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * RegistryCredential publicKeyCertificate.
+                         * @member {google.cloud.iot.v1.IPublicKeyCertificate|null|undefined} publicKeyCertificate
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @instance
+                         */
+                        RegistryCredential.prototype.publicKeyCertificate = null;
+    
+                        // OneOf field names bound to virtual getters and setters
+                        var $oneOfFields;
+    
+                        /**
+                         * RegistryCredential credential.
+                         * @member {"publicKeyCertificate"|undefined} credential
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @instance
+                         */
+                        Object.defineProperty(RegistryCredential.prototype, "credential", {
+                            get: $util.oneOfGetter($oneOfFields = ["publicKeyCertificate"]),
+                            set: $util.oneOfSetter($oneOfFields)
+                        });
+    
+                        /**
+                         * Creates a new RegistryCredential instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IRegistryCredential=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.RegistryCredential} RegistryCredential instance
+                         */
+                        RegistryCredential.create = function create(properties) {
+                            return new RegistryCredential(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified RegistryCredential message. Does not implicitly {@link google.cloud.iot.v1.RegistryCredential.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IRegistryCredential} message RegistryCredential message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        RegistryCredential.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.publicKeyCertificate != null && Object.hasOwnProperty.call(message, "publicKeyCertificate"))
+                                $root.google.cloud.iot.v1.PublicKeyCertificate.encode(message.publicKeyCertificate, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified RegistryCredential message, length delimited. Does not implicitly {@link google.cloud.iot.v1.RegistryCredential.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IRegistryCredential} message RegistryCredential message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        RegistryCredential.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a RegistryCredential message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.RegistryCredential} RegistryCredential
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        RegistryCredential.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.RegistryCredential();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.publicKeyCertificate = $root.google.cloud.iot.v1.PublicKeyCertificate.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a RegistryCredential message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.RegistryCredential} RegistryCredential
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        RegistryCredential.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a RegistryCredential message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        RegistryCredential.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            var properties = {};
+                            if (message.publicKeyCertificate != null && message.hasOwnProperty("publicKeyCertificate")) {
+                                properties.credential = 1;
+                                {
+                                    var error = $root.google.cloud.iot.v1.PublicKeyCertificate.verify(message.publicKeyCertificate);
+                                    if (error)
+                                        return "publicKeyCertificate." + error;
+                                }
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a RegistryCredential message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.RegistryCredential} RegistryCredential
+                         */
+                        RegistryCredential.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.RegistryCredential)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.RegistryCredential();
+                            if (object.publicKeyCertificate != null) {
+                                if (typeof object.publicKeyCertificate !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.RegistryCredential.publicKeyCertificate: object expected");
+                                message.publicKeyCertificate = $root.google.cloud.iot.v1.PublicKeyCertificate.fromObject(object.publicKeyCertificate);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a RegistryCredential message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.RegistryCredential} message RegistryCredential
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        RegistryCredential.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (message.publicKeyCertificate != null && message.hasOwnProperty("publicKeyCertificate")) {
+                                object.publicKeyCertificate = $root.google.cloud.iot.v1.PublicKeyCertificate.toObject(message.publicKeyCertificate, options);
+                                if (options.oneofs)
+                                    object.credential = "publicKeyCertificate";
+                            }
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this RegistryCredential to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.RegistryCredential
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        RegistryCredential.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return RegistryCredential;
+                    })();
+    
+                    v1.X509CertificateDetails = (function() {
+    
+                        /**
+                         * Properties of a X509CertificateDetails.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IX509CertificateDetails
+                         * @property {string|null} [issuer] X509CertificateDetails issuer
+                         * @property {string|null} [subject] X509CertificateDetails subject
+                         * @property {google.protobuf.ITimestamp|null} [startTime] X509CertificateDetails startTime
+                         * @property {google.protobuf.ITimestamp|null} [expiryTime] X509CertificateDetails expiryTime
+                         * @property {string|null} [signatureAlgorithm] X509CertificateDetails signatureAlgorithm
+                         * @property {string|null} [publicKeyType] X509CertificateDetails publicKeyType
+                         */
+    
+                        /**
+                         * Constructs a new X509CertificateDetails.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a X509CertificateDetails.
+                         * @implements IX509CertificateDetails
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IX509CertificateDetails=} [properties] Properties to set
+                         */
+                        function X509CertificateDetails(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * X509CertificateDetails issuer.
+                         * @member {string} issuer
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @instance
+                         */
+                        X509CertificateDetails.prototype.issuer = "";
+    
+                        /**
+                         * X509CertificateDetails subject.
+                         * @member {string} subject
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @instance
+                         */
+                        X509CertificateDetails.prototype.subject = "";
+    
+                        /**
+                         * X509CertificateDetails startTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} startTime
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @instance
+                         */
+                        X509CertificateDetails.prototype.startTime = null;
+    
+                        /**
+                         * X509CertificateDetails expiryTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} expiryTime
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @instance
+                         */
+                        X509CertificateDetails.prototype.expiryTime = null;
+    
+                        /**
+                         * X509CertificateDetails signatureAlgorithm.
+                         * @member {string} signatureAlgorithm
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @instance
+                         */
+                        X509CertificateDetails.prototype.signatureAlgorithm = "";
+    
+                        /**
+                         * X509CertificateDetails publicKeyType.
+                         * @member {string} publicKeyType
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @instance
+                         */
+                        X509CertificateDetails.prototype.publicKeyType = "";
+    
+                        /**
+                         * Creates a new X509CertificateDetails instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {google.cloud.iot.v1.IX509CertificateDetails=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.X509CertificateDetails} X509CertificateDetails instance
+                         */
+                        X509CertificateDetails.create = function create(properties) {
+                            return new X509CertificateDetails(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified X509CertificateDetails message. Does not implicitly {@link google.cloud.iot.v1.X509CertificateDetails.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {google.cloud.iot.v1.IX509CertificateDetails} message X509CertificateDetails message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        X509CertificateDetails.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.issuer != null && Object.hasOwnProperty.call(message, "issuer"))
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.issuer);
+                            if (message.subject != null && Object.hasOwnProperty.call(message, "subject"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.subject);
+                            if (message.startTime != null && Object.hasOwnProperty.call(message, "startTime"))
+                                $root.google.protobuf.Timestamp.encode(message.startTime, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                            if (message.expiryTime != null && Object.hasOwnProperty.call(message, "expiryTime"))
+                                $root.google.protobuf.Timestamp.encode(message.expiryTime, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                            if (message.signatureAlgorithm != null && Object.hasOwnProperty.call(message, "signatureAlgorithm"))
+                                writer.uint32(/* id 5, wireType 2 =*/42).string(message.signatureAlgorithm);
+                            if (message.publicKeyType != null && Object.hasOwnProperty.call(message, "publicKeyType"))
+                                writer.uint32(/* id 6, wireType 2 =*/50).string(message.publicKeyType);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified X509CertificateDetails message, length delimited. Does not implicitly {@link google.cloud.iot.v1.X509CertificateDetails.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {google.cloud.iot.v1.IX509CertificateDetails} message X509CertificateDetails message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        X509CertificateDetails.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a X509CertificateDetails message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.X509CertificateDetails} X509CertificateDetails
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        X509CertificateDetails.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.X509CertificateDetails();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.issuer = reader.string();
+                                    break;
+                                case 2:
+                                    message.subject = reader.string();
+                                    break;
+                                case 3:
+                                    message.startTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 4:
+                                    message.expiryTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 5:
+                                    message.signatureAlgorithm = reader.string();
+                                    break;
+                                case 6:
+                                    message.publicKeyType = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a X509CertificateDetails message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.X509CertificateDetails} X509CertificateDetails
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        X509CertificateDetails.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a X509CertificateDetails message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        X509CertificateDetails.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.issuer != null && message.hasOwnProperty("issuer"))
+                                if (!$util.isString(message.issuer))
+                                    return "issuer: string expected";
+                            if (message.subject != null && message.hasOwnProperty("subject"))
+                                if (!$util.isString(message.subject))
+                                    return "subject: string expected";
+                            if (message.startTime != null && message.hasOwnProperty("startTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.startTime);
+                                if (error)
+                                    return "startTime." + error;
+                            }
+                            if (message.expiryTime != null && message.hasOwnProperty("expiryTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.expiryTime);
+                                if (error)
+                                    return "expiryTime." + error;
+                            }
+                            if (message.signatureAlgorithm != null && message.hasOwnProperty("signatureAlgorithm"))
+                                if (!$util.isString(message.signatureAlgorithm))
+                                    return "signatureAlgorithm: string expected";
+                            if (message.publicKeyType != null && message.hasOwnProperty("publicKeyType"))
+                                if (!$util.isString(message.publicKeyType))
+                                    return "publicKeyType: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a X509CertificateDetails message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.X509CertificateDetails} X509CertificateDetails
+                         */
+                        X509CertificateDetails.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.X509CertificateDetails)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.X509CertificateDetails();
+                            if (object.issuer != null)
+                                message.issuer = String(object.issuer);
+                            if (object.subject != null)
+                                message.subject = String(object.subject);
+                            if (object.startTime != null) {
+                                if (typeof object.startTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.X509CertificateDetails.startTime: object expected");
+                                message.startTime = $root.google.protobuf.Timestamp.fromObject(object.startTime);
+                            }
+                            if (object.expiryTime != null) {
+                                if (typeof object.expiryTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.X509CertificateDetails.expiryTime: object expected");
+                                message.expiryTime = $root.google.protobuf.Timestamp.fromObject(object.expiryTime);
+                            }
+                            if (object.signatureAlgorithm != null)
+                                message.signatureAlgorithm = String(object.signatureAlgorithm);
+                            if (object.publicKeyType != null)
+                                message.publicKeyType = String(object.publicKeyType);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a X509CertificateDetails message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @static
+                         * @param {google.cloud.iot.v1.X509CertificateDetails} message X509CertificateDetails
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        X509CertificateDetails.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.issuer = "";
+                                object.subject = "";
+                                object.startTime = null;
+                                object.expiryTime = null;
+                                object.signatureAlgorithm = "";
+                                object.publicKeyType = "";
+                            }
+                            if (message.issuer != null && message.hasOwnProperty("issuer"))
+                                object.issuer = message.issuer;
+                            if (message.subject != null && message.hasOwnProperty("subject"))
+                                object.subject = message.subject;
+                            if (message.startTime != null && message.hasOwnProperty("startTime"))
+                                object.startTime = $root.google.protobuf.Timestamp.toObject(message.startTime, options);
+                            if (message.expiryTime != null && message.hasOwnProperty("expiryTime"))
+                                object.expiryTime = $root.google.protobuf.Timestamp.toObject(message.expiryTime, options);
+                            if (message.signatureAlgorithm != null && message.hasOwnProperty("signatureAlgorithm"))
+                                object.signatureAlgorithm = message.signatureAlgorithm;
+                            if (message.publicKeyType != null && message.hasOwnProperty("publicKeyType"))
+                                object.publicKeyType = message.publicKeyType;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this X509CertificateDetails to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.X509CertificateDetails
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        X509CertificateDetails.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return X509CertificateDetails;
+                    })();
+    
+                    v1.PublicKeyCertificate = (function() {
+    
+                        /**
+                         * Properties of a PublicKeyCertificate.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IPublicKeyCertificate
+                         * @property {google.cloud.iot.v1.PublicKeyCertificateFormat|null} [format] PublicKeyCertificate format
+                         * @property {string|null} [certificate] PublicKeyCertificate certificate
+                         * @property {google.cloud.iot.v1.IX509CertificateDetails|null} [x509Details] PublicKeyCertificate x509Details
+                         */
+    
+                        /**
+                         * Constructs a new PublicKeyCertificate.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a PublicKeyCertificate.
+                         * @implements IPublicKeyCertificate
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IPublicKeyCertificate=} [properties] Properties to set
+                         */
+                        function PublicKeyCertificate(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * PublicKeyCertificate format.
+                         * @member {google.cloud.iot.v1.PublicKeyCertificateFormat} format
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @instance
+                         */
+                        PublicKeyCertificate.prototype.format = 0;
+    
+                        /**
+                         * PublicKeyCertificate certificate.
+                         * @member {string} certificate
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @instance
+                         */
+                        PublicKeyCertificate.prototype.certificate = "";
+    
+                        /**
+                         * PublicKeyCertificate x509Details.
+                         * @member {google.cloud.iot.v1.IX509CertificateDetails|null|undefined} x509Details
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @instance
+                         */
+                        PublicKeyCertificate.prototype.x509Details = null;
+    
+                        /**
+                         * Creates a new PublicKeyCertificate instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {google.cloud.iot.v1.IPublicKeyCertificate=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.PublicKeyCertificate} PublicKeyCertificate instance
+                         */
+                        PublicKeyCertificate.create = function create(properties) {
+                            return new PublicKeyCertificate(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified PublicKeyCertificate message. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCertificate.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {google.cloud.iot.v1.IPublicKeyCertificate} message PublicKeyCertificate message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        PublicKeyCertificate.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.format != null && Object.hasOwnProperty.call(message, "format"))
+                                writer.uint32(/* id 1, wireType 0 =*/8).int32(message.format);
+                            if (message.certificate != null && Object.hasOwnProperty.call(message, "certificate"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.certificate);
+                            if (message.x509Details != null && Object.hasOwnProperty.call(message, "x509Details"))
+                                $root.google.cloud.iot.v1.X509CertificateDetails.encode(message.x509Details, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified PublicKeyCertificate message, length delimited. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCertificate.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {google.cloud.iot.v1.IPublicKeyCertificate} message PublicKeyCertificate message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        PublicKeyCertificate.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a PublicKeyCertificate message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.PublicKeyCertificate} PublicKeyCertificate
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        PublicKeyCertificate.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.PublicKeyCertificate();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.format = reader.int32();
+                                    break;
+                                case 2:
+                                    message.certificate = reader.string();
+                                    break;
+                                case 3:
+                                    message.x509Details = $root.google.cloud.iot.v1.X509CertificateDetails.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a PublicKeyCertificate message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.PublicKeyCertificate} PublicKeyCertificate
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        PublicKeyCertificate.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a PublicKeyCertificate message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        PublicKeyCertificate.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.format != null && message.hasOwnProperty("format"))
+                                switch (message.format) {
+                                default:
+                                    return "format: enum value expected";
+                                case 0:
+                                case 1:
+                                    break;
+                                }
+                            if (message.certificate != null && message.hasOwnProperty("certificate"))
+                                if (!$util.isString(message.certificate))
+                                    return "certificate: string expected";
+                            if (message.x509Details != null && message.hasOwnProperty("x509Details")) {
+                                var error = $root.google.cloud.iot.v1.X509CertificateDetails.verify(message.x509Details);
+                                if (error)
+                                    return "x509Details." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a PublicKeyCertificate message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.PublicKeyCertificate} PublicKeyCertificate
+                         */
+                        PublicKeyCertificate.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.PublicKeyCertificate)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.PublicKeyCertificate();
+                            switch (object.format) {
+                            case "UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT":
+                            case 0:
+                                message.format = 0;
+                                break;
+                            case "X509_CERTIFICATE_PEM":
+                            case 1:
+                                message.format = 1;
+                                break;
+                            }
+                            if (object.certificate != null)
+                                message.certificate = String(object.certificate);
+                            if (object.x509Details != null) {
+                                if (typeof object.x509Details !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.PublicKeyCertificate.x509Details: object expected");
+                                message.x509Details = $root.google.cloud.iot.v1.X509CertificateDetails.fromObject(object.x509Details);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a PublicKeyCertificate message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @static
+                         * @param {google.cloud.iot.v1.PublicKeyCertificate} message PublicKeyCertificate
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        PublicKeyCertificate.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.format = options.enums === String ? "UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT" : 0;
+                                object.certificate = "";
+                                object.x509Details = null;
+                            }
+                            if (message.format != null && message.hasOwnProperty("format"))
+                                object.format = options.enums === String ? $root.google.cloud.iot.v1.PublicKeyCertificateFormat[message.format] : message.format;
+                            if (message.certificate != null && message.hasOwnProperty("certificate"))
+                                object.certificate = message.certificate;
+                            if (message.x509Details != null && message.hasOwnProperty("x509Details"))
+                                object.x509Details = $root.google.cloud.iot.v1.X509CertificateDetails.toObject(message.x509Details, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this PublicKeyCertificate to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.PublicKeyCertificate
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        PublicKeyCertificate.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return PublicKeyCertificate;
+                    })();
+    
+                    /**
+                     * PublicKeyCertificateFormat enum.
+                     * @name google.cloud.iot.v1.PublicKeyCertificateFormat
+                     * @enum {number}
+                     * @property {number} UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT=0 UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT value
+                     * @property {number} X509_CERTIFICATE_PEM=1 X509_CERTIFICATE_PEM value
+                     */
+                    v1.PublicKeyCertificateFormat = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT"] = 0;
+                        values[valuesById[1] = "X509_CERTIFICATE_PEM"] = 1;
+                        return values;
+                    })();
+    
+                    v1.DeviceCredential = (function() {
+    
+                        /**
+                         * Properties of a DeviceCredential.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IDeviceCredential
+                         * @property {google.cloud.iot.v1.IPublicKeyCredential|null} [publicKey] DeviceCredential publicKey
+                         * @property {google.protobuf.ITimestamp|null} [expirationTime] DeviceCredential expirationTime
+                         */
+    
+                        /**
+                         * Constructs a new DeviceCredential.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a DeviceCredential.
+                         * @implements IDeviceCredential
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IDeviceCredential=} [properties] Properties to set
+                         */
+                        function DeviceCredential(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * DeviceCredential publicKey.
+                         * @member {google.cloud.iot.v1.IPublicKeyCredential|null|undefined} publicKey
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @instance
+                         */
+                        DeviceCredential.prototype.publicKey = null;
+    
+                        /**
+                         * DeviceCredential expirationTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} expirationTime
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @instance
+                         */
+                        DeviceCredential.prototype.expirationTime = null;
+    
+                        // OneOf field names bound to virtual getters and setters
+                        var $oneOfFields;
+    
+                        /**
+                         * DeviceCredential credential.
+                         * @member {"publicKey"|undefined} credential
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @instance
+                         */
+                        Object.defineProperty(DeviceCredential.prototype, "credential", {
+                            get: $util.oneOfGetter($oneOfFields = ["publicKey"]),
+                            set: $util.oneOfSetter($oneOfFields)
+                        });
+    
+                        /**
+                         * Creates a new DeviceCredential instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceCredential=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.DeviceCredential} DeviceCredential instance
+                         */
+                        DeviceCredential.create = function create(properties) {
+                            return new DeviceCredential(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceCredential message. Does not implicitly {@link google.cloud.iot.v1.DeviceCredential.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceCredential} message DeviceCredential message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceCredential.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.publicKey != null && Object.hasOwnProperty.call(message, "publicKey"))
+                                $root.google.cloud.iot.v1.PublicKeyCredential.encode(message.publicKey, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                            if (message.expirationTime != null && Object.hasOwnProperty.call(message, "expirationTime"))
+                                $root.google.protobuf.Timestamp.encode(message.expirationTime, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceCredential message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceCredential.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceCredential} message DeviceCredential message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceCredential.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a DeviceCredential message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.DeviceCredential} DeviceCredential
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceCredential.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.DeviceCredential();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 2:
+                                    message.publicKey = $root.google.cloud.iot.v1.PublicKeyCredential.decode(reader, reader.uint32());
+                                    break;
+                                case 6:
+                                    message.expirationTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a DeviceCredential message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.DeviceCredential} DeviceCredential
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceCredential.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a DeviceCredential message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        DeviceCredential.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            var properties = {};
+                            if (message.publicKey != null && message.hasOwnProperty("publicKey")) {
+                                properties.credential = 1;
+                                {
+                                    var error = $root.google.cloud.iot.v1.PublicKeyCredential.verify(message.publicKey);
+                                    if (error)
+                                        return "publicKey." + error;
+                                }
+                            }
+                            if (message.expirationTime != null && message.hasOwnProperty("expirationTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.expirationTime);
+                                if (error)
+                                    return "expirationTime." + error;
+                            }
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a DeviceCredential message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.DeviceCredential} DeviceCredential
+                         */
+                        DeviceCredential.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.DeviceCredential)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.DeviceCredential();
+                            if (object.publicKey != null) {
+                                if (typeof object.publicKey !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceCredential.publicKey: object expected");
+                                message.publicKey = $root.google.cloud.iot.v1.PublicKeyCredential.fromObject(object.publicKey);
+                            }
+                            if (object.expirationTime != null) {
+                                if (typeof object.expirationTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceCredential.expirationTime: object expected");
+                                message.expirationTime = $root.google.protobuf.Timestamp.fromObject(object.expirationTime);
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a DeviceCredential message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.DeviceCredential} message DeviceCredential
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        DeviceCredential.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults)
+                                object.expirationTime = null;
+                            if (message.publicKey != null && message.hasOwnProperty("publicKey")) {
+                                object.publicKey = $root.google.cloud.iot.v1.PublicKeyCredential.toObject(message.publicKey, options);
+                                if (options.oneofs)
+                                    object.credential = "publicKey";
+                            }
+                            if (message.expirationTime != null && message.hasOwnProperty("expirationTime"))
+                                object.expirationTime = $root.google.protobuf.Timestamp.toObject(message.expirationTime, options);
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this DeviceCredential to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.DeviceCredential
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        DeviceCredential.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return DeviceCredential;
+                    })();
+    
+                    v1.PublicKeyCredential = (function() {
+    
+                        /**
+                         * Properties of a PublicKeyCredential.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IPublicKeyCredential
+                         * @property {google.cloud.iot.v1.PublicKeyFormat|null} [format] PublicKeyCredential format
+                         * @property {string|null} [key] PublicKeyCredential key
+                         */
+    
+                        /**
+                         * Constructs a new PublicKeyCredential.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a PublicKeyCredential.
+                         * @implements IPublicKeyCredential
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IPublicKeyCredential=} [properties] Properties to set
+                         */
+                        function PublicKeyCredential(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * PublicKeyCredential format.
+                         * @member {google.cloud.iot.v1.PublicKeyFormat} format
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @instance
+                         */
+                        PublicKeyCredential.prototype.format = 0;
+    
+                        /**
+                         * PublicKeyCredential key.
+                         * @member {string} key
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @instance
+                         */
+                        PublicKeyCredential.prototype.key = "";
+    
+                        /**
+                         * Creates a new PublicKeyCredential instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IPublicKeyCredential=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.PublicKeyCredential} PublicKeyCredential instance
+                         */
+                        PublicKeyCredential.create = function create(properties) {
+                            return new PublicKeyCredential(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified PublicKeyCredential message. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCredential.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IPublicKeyCredential} message PublicKeyCredential message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        PublicKeyCredential.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.format != null && Object.hasOwnProperty.call(message, "format"))
+                                writer.uint32(/* id 1, wireType 0 =*/8).int32(message.format);
+                            if (message.key != null && Object.hasOwnProperty.call(message, "key"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.key);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified PublicKeyCredential message, length delimited. Does not implicitly {@link google.cloud.iot.v1.PublicKeyCredential.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.IPublicKeyCredential} message PublicKeyCredential message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        PublicKeyCredential.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a PublicKeyCredential message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.PublicKeyCredential} PublicKeyCredential
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        PublicKeyCredential.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.PublicKeyCredential();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.format = reader.int32();
+                                    break;
+                                case 2:
+                                    message.key = reader.string();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a PublicKeyCredential message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.PublicKeyCredential} PublicKeyCredential
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        PublicKeyCredential.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a PublicKeyCredential message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        PublicKeyCredential.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.format != null && message.hasOwnProperty("format"))
+                                switch (message.format) {
+                                default:
+                                    return "format: enum value expected";
+                                case 0:
+                                case 3:
+                                case 1:
+                                case 2:
+                                case 4:
+                                    break;
+                                }
+                            if (message.key != null && message.hasOwnProperty("key"))
+                                if (!$util.isString(message.key))
+                                    return "key: string expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a PublicKeyCredential message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.PublicKeyCredential} PublicKeyCredential
+                         */
+                        PublicKeyCredential.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.PublicKeyCredential)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.PublicKeyCredential();
+                            switch (object.format) {
+                            case "UNSPECIFIED_PUBLIC_KEY_FORMAT":
+                            case 0:
+                                message.format = 0;
+                                break;
+                            case "RSA_PEM":
+                            case 3:
+                                message.format = 3;
+                                break;
+                            case "RSA_X509_PEM":
+                            case 1:
+                                message.format = 1;
+                                break;
+                            case "ES256_PEM":
+                            case 2:
+                                message.format = 2;
+                                break;
+                            case "ES256_X509_PEM":
+                            case 4:
+                                message.format = 4;
+                                break;
+                            }
+                            if (object.key != null)
+                                message.key = String(object.key);
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a PublicKeyCredential message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @static
+                         * @param {google.cloud.iot.v1.PublicKeyCredential} message PublicKeyCredential
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        PublicKeyCredential.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.format = options.enums === String ? "UNSPECIFIED_PUBLIC_KEY_FORMAT" : 0;
+                                object.key = "";
+                            }
+                            if (message.format != null && message.hasOwnProperty("format"))
+                                object.format = options.enums === String ? $root.google.cloud.iot.v1.PublicKeyFormat[message.format] : message.format;
+                            if (message.key != null && message.hasOwnProperty("key"))
+                                object.key = message.key;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this PublicKeyCredential to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.PublicKeyCredential
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        PublicKeyCredential.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return PublicKeyCredential;
+                    })();
+    
+                    /**
+                     * PublicKeyFormat enum.
+                     * @name google.cloud.iot.v1.PublicKeyFormat
+                     * @enum {number}
+                     * @property {number} UNSPECIFIED_PUBLIC_KEY_FORMAT=0 UNSPECIFIED_PUBLIC_KEY_FORMAT value
+                     * @property {number} RSA_PEM=3 RSA_PEM value
+                     * @property {number} RSA_X509_PEM=1 RSA_X509_PEM value
+                     * @property {number} ES256_PEM=2 ES256_PEM value
+                     * @property {number} ES256_X509_PEM=4 ES256_X509_PEM value
+                     */
+                    v1.PublicKeyFormat = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "UNSPECIFIED_PUBLIC_KEY_FORMAT"] = 0;
+                        values[valuesById[3] = "RSA_PEM"] = 3;
+                        values[valuesById[1] = "RSA_X509_PEM"] = 1;
+                        values[valuesById[2] = "ES256_PEM"] = 2;
+                        values[valuesById[4] = "ES256_X509_PEM"] = 4;
+                        return values;
+                    })();
+    
+                    v1.DeviceConfig = (function() {
+    
+                        /**
+                         * Properties of a DeviceConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IDeviceConfig
+                         * @property {number|Long|null} [version] DeviceConfig version
+                         * @property {google.protobuf.ITimestamp|null} [cloudUpdateTime] DeviceConfig cloudUpdateTime
+                         * @property {google.protobuf.ITimestamp|null} [deviceAckTime] DeviceConfig deviceAckTime
+                         * @property {Uint8Array|null} [binaryData] DeviceConfig binaryData
+                         */
+    
+                        /**
+                         * Constructs a new DeviceConfig.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a DeviceConfig.
+                         * @implements IDeviceConfig
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IDeviceConfig=} [properties] Properties to set
+                         */
+                        function DeviceConfig(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * DeviceConfig version.
+                         * @member {number|Long} version
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @instance
+                         */
+                        DeviceConfig.prototype.version = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
+    
+                        /**
+                         * DeviceConfig cloudUpdateTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} cloudUpdateTime
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @instance
+                         */
+                        DeviceConfig.prototype.cloudUpdateTime = null;
+    
+                        /**
+                         * DeviceConfig deviceAckTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} deviceAckTime
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @instance
+                         */
+                        DeviceConfig.prototype.deviceAckTime = null;
+    
+                        /**
+                         * DeviceConfig binaryData.
+                         * @member {Uint8Array} binaryData
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @instance
+                         */
+                        DeviceConfig.prototype.binaryData = $util.newBuffer([]);
+    
+                        /**
+                         * Creates a new DeviceConfig instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceConfig=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.DeviceConfig} DeviceConfig instance
+                         */
+                        DeviceConfig.create = function create(properties) {
+                            return new DeviceConfig(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceConfig message. Does not implicitly {@link google.cloud.iot.v1.DeviceConfig.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceConfig} message DeviceConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceConfig.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.version != null && Object.hasOwnProperty.call(message, "version"))
+                                writer.uint32(/* id 1, wireType 0 =*/8).int64(message.version);
+                            if (message.cloudUpdateTime != null && Object.hasOwnProperty.call(message, "cloudUpdateTime"))
+                                $root.google.protobuf.Timestamp.encode(message.cloudUpdateTime, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                            if (message.deviceAckTime != null && Object.hasOwnProperty.call(message, "deviceAckTime"))
+                                $root.google.protobuf.Timestamp.encode(message.deviceAckTime, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                            if (message.binaryData != null && Object.hasOwnProperty.call(message, "binaryData"))
+                                writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.binaryData);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceConfig message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceConfig.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceConfig} message DeviceConfig message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceConfig.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a DeviceConfig message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.DeviceConfig} DeviceConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceConfig.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.DeviceConfig();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.version = reader.int64();
+                                    break;
+                                case 2:
+                                    message.cloudUpdateTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 3:
+                                    message.deviceAckTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 4:
+                                    message.binaryData = reader.bytes();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a DeviceConfig message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.DeviceConfig} DeviceConfig
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceConfig.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a DeviceConfig message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        DeviceConfig.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.version != null && message.hasOwnProperty("version"))
+                                if (!$util.isInteger(message.version) && !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high)))
+                                    return "version: integer|Long expected";
+                            if (message.cloudUpdateTime != null && message.hasOwnProperty("cloudUpdateTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.cloudUpdateTime);
+                                if (error)
+                                    return "cloudUpdateTime." + error;
+                            }
+                            if (message.deviceAckTime != null && message.hasOwnProperty("deviceAckTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.deviceAckTime);
+                                if (error)
+                                    return "deviceAckTime." + error;
+                            }
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                if (!(message.binaryData && typeof message.binaryData.length === "number" || $util.isString(message.binaryData)))
+                                    return "binaryData: buffer expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a DeviceConfig message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.DeviceConfig} DeviceConfig
+                         */
+                        DeviceConfig.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.DeviceConfig)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.DeviceConfig();
+                            if (object.version != null)
+                                if ($util.Long)
+                                    (message.version = $util.Long.fromValue(object.version)).unsigned = false;
+                                else if (typeof object.version === "string")
+                                    message.version = parseInt(object.version, 10);
+                                else if (typeof object.version === "number")
+                                    message.version = object.version;
+                                else if (typeof object.version === "object")
+                                    message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber();
+                            if (object.cloudUpdateTime != null) {
+                                if (typeof object.cloudUpdateTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceConfig.cloudUpdateTime: object expected");
+                                message.cloudUpdateTime = $root.google.protobuf.Timestamp.fromObject(object.cloudUpdateTime);
+                            }
+                            if (object.deviceAckTime != null) {
+                                if (typeof object.deviceAckTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceConfig.deviceAckTime: object expected");
+                                message.deviceAckTime = $root.google.protobuf.Timestamp.fromObject(object.deviceAckTime);
+                            }
+                            if (object.binaryData != null)
+                                if (typeof object.binaryData === "string")
+                                    $util.base64.decode(object.binaryData, message.binaryData = $util.newBuffer($util.base64.length(object.binaryData)), 0);
+                                else if (object.binaryData.length)
+                                    message.binaryData = object.binaryData;
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a DeviceConfig message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @static
+                         * @param {google.cloud.iot.v1.DeviceConfig} message DeviceConfig
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        DeviceConfig.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                if ($util.Long) {
+                                    var long = new $util.Long(0, 0, false);
+                                    object.version = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+                                } else
+                                    object.version = options.longs === String ? "0" : 0;
+                                object.cloudUpdateTime = null;
+                                object.deviceAckTime = null;
+                                if (options.bytes === String)
+                                    object.binaryData = "";
+                                else {
+                                    object.binaryData = [];
+                                    if (options.bytes !== Array)
+                                        object.binaryData = $util.newBuffer(object.binaryData);
+                                }
+                            }
+                            if (message.version != null && message.hasOwnProperty("version"))
+                                if (typeof message.version === "number")
+                                    object.version = options.longs === String ? String(message.version) : message.version;
+                                else
+                                    object.version = options.longs === String ? $util.Long.prototype.toString.call(message.version) : options.longs === Number ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() : message.version;
+                            if (message.cloudUpdateTime != null && message.hasOwnProperty("cloudUpdateTime"))
+                                object.cloudUpdateTime = $root.google.protobuf.Timestamp.toObject(message.cloudUpdateTime, options);
+                            if (message.deviceAckTime != null && message.hasOwnProperty("deviceAckTime"))
+                                object.deviceAckTime = $root.google.protobuf.Timestamp.toObject(message.deviceAckTime, options);
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                object.binaryData = options.bytes === String ? $util.base64.encode(message.binaryData, 0, message.binaryData.length) : options.bytes === Array ? Array.prototype.slice.call(message.binaryData) : message.binaryData;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this DeviceConfig to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.DeviceConfig
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        DeviceConfig.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return DeviceConfig;
+                    })();
+    
+                    v1.DeviceState = (function() {
+    
+                        /**
+                         * Properties of a DeviceState.
+                         * @memberof google.cloud.iot.v1
+                         * @interface IDeviceState
+                         * @property {google.protobuf.ITimestamp|null} [updateTime] DeviceState updateTime
+                         * @property {Uint8Array|null} [binaryData] DeviceState binaryData
+                         */
+    
+                        /**
+                         * Constructs a new DeviceState.
+                         * @memberof google.cloud.iot.v1
+                         * @classdesc Represents a DeviceState.
+                         * @implements IDeviceState
+                         * @constructor
+                         * @param {google.cloud.iot.v1.IDeviceState=} [properties] Properties to set
+                         */
+                        function DeviceState(properties) {
+                            if (properties)
+                                for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                    if (properties[keys[i]] != null)
+                                        this[keys[i]] = properties[keys[i]];
+                        }
+    
+                        /**
+                         * DeviceState updateTime.
+                         * @member {google.protobuf.ITimestamp|null|undefined} updateTime
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @instance
+                         */
+                        DeviceState.prototype.updateTime = null;
+    
+                        /**
+                         * DeviceState binaryData.
+                         * @member {Uint8Array} binaryData
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @instance
+                         */
+                        DeviceState.prototype.binaryData = $util.newBuffer([]);
+    
+                        /**
+                         * Creates a new DeviceState instance using the specified properties.
+                         * @function create
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceState=} [properties] Properties to set
+                         * @returns {google.cloud.iot.v1.DeviceState} DeviceState instance
+                         */
+                        DeviceState.create = function create(properties) {
+                            return new DeviceState(properties);
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceState message. Does not implicitly {@link google.cloud.iot.v1.DeviceState.verify|verify} messages.
+                         * @function encode
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceState} message DeviceState message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceState.encode = function encode(message, writer) {
+                            if (!writer)
+                                writer = $Writer.create();
+                            if (message.updateTime != null && Object.hasOwnProperty.call(message, "updateTime"))
+                                $root.google.protobuf.Timestamp.encode(message.updateTime, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                            if (message.binaryData != null && Object.hasOwnProperty.call(message, "binaryData"))
+                                writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.binaryData);
+                            return writer;
+                        };
+    
+                        /**
+                         * Encodes the specified DeviceState message, length delimited. Does not implicitly {@link google.cloud.iot.v1.DeviceState.verify|verify} messages.
+                         * @function encodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {google.cloud.iot.v1.IDeviceState} message DeviceState message or plain object to encode
+                         * @param {$protobuf.Writer} [writer] Writer to encode to
+                         * @returns {$protobuf.Writer} Writer
+                         */
+                        DeviceState.encodeDelimited = function encodeDelimited(message, writer) {
+                            return this.encode(message, writer).ldelim();
+                        };
+    
+                        /**
+                         * Decodes a DeviceState message from the specified reader or buffer.
+                         * @function decode
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @param {number} [length] Message length if known beforehand
+                         * @returns {google.cloud.iot.v1.DeviceState} DeviceState
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceState.decode = function decode(reader, length) {
+                            if (!(reader instanceof $Reader))
+                                reader = $Reader.create(reader);
+                            var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.cloud.iot.v1.DeviceState();
+                            while (reader.pos < end) {
+                                var tag = reader.uint32();
+                                switch (tag >>> 3) {
+                                case 1:
+                                    message.updateTime = $root.google.protobuf.Timestamp.decode(reader, reader.uint32());
+                                    break;
+                                case 2:
+                                    message.binaryData = reader.bytes();
+                                    break;
+                                default:
+                                    reader.skipType(tag & 7);
+                                    break;
+                                }
+                            }
+                            return message;
+                        };
+    
+                        /**
+                         * Decodes a DeviceState message from the specified reader or buffer, length delimited.
+                         * @function decodeDelimited
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                         * @returns {google.cloud.iot.v1.DeviceState} DeviceState
+                         * @throws {Error} If the payload is not a reader or valid buffer
+                         * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                         */
+                        DeviceState.decodeDelimited = function decodeDelimited(reader) {
+                            if (!(reader instanceof $Reader))
+                                reader = new $Reader(reader);
+                            return this.decode(reader, reader.uint32());
+                        };
+    
+                        /**
+                         * Verifies a DeviceState message.
+                         * @function verify
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {Object.<string,*>} message Plain object to verify
+                         * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                         */
+                        DeviceState.verify = function verify(message) {
+                            if (typeof message !== "object" || message === null)
+                                return "object expected";
+                            if (message.updateTime != null && message.hasOwnProperty("updateTime")) {
+                                var error = $root.google.protobuf.Timestamp.verify(message.updateTime);
+                                if (error)
+                                    return "updateTime." + error;
+                            }
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                if (!(message.binaryData && typeof message.binaryData.length === "number" || $util.isString(message.binaryData)))
+                                    return "binaryData: buffer expected";
+                            return null;
+                        };
+    
+                        /**
+                         * Creates a DeviceState message from a plain object. Also converts values to their respective internal types.
+                         * @function fromObject
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {Object.<string,*>} object Plain object
+                         * @returns {google.cloud.iot.v1.DeviceState} DeviceState
+                         */
+                        DeviceState.fromObject = function fromObject(object) {
+                            if (object instanceof $root.google.cloud.iot.v1.DeviceState)
+                                return object;
+                            var message = new $root.google.cloud.iot.v1.DeviceState();
+                            if (object.updateTime != null) {
+                                if (typeof object.updateTime !== "object")
+                                    throw TypeError(".google.cloud.iot.v1.DeviceState.updateTime: object expected");
+                                message.updateTime = $root.google.protobuf.Timestamp.fromObject(object.updateTime);
+                            }
+                            if (object.binaryData != null)
+                                if (typeof object.binaryData === "string")
+                                    $util.base64.decode(object.binaryData, message.binaryData = $util.newBuffer($util.base64.length(object.binaryData)), 0);
+                                else if (object.binaryData.length)
+                                    message.binaryData = object.binaryData;
+                            return message;
+                        };
+    
+                        /**
+                         * Creates a plain object from a DeviceState message. Also converts values to other types if specified.
+                         * @function toObject
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @static
+                         * @param {google.cloud.iot.v1.DeviceState} message DeviceState
+                         * @param {$protobuf.IConversionOptions} [options] Conversion options
+                         * @returns {Object.<string,*>} Plain object
+                         */
+                        DeviceState.toObject = function toObject(message, options) {
+                            if (!options)
+                                options = {};
+                            var object = {};
+                            if (options.defaults) {
+                                object.updateTime = null;
+                                if (options.bytes === String)
+                                    object.binaryData = "";
+                                else {
+                                    object.binaryData = [];
+                                    if (options.bytes !== Array)
+                                        object.binaryData = $util.newBuffer(object.binaryData);
+                                }
+                            }
+                            if (message.updateTime != null && message.hasOwnProperty("updateTime"))
+                                object.updateTime = $root.google.protobuf.Timestamp.toObject(message.updateTime, options);
+                            if (message.binaryData != null && message.hasOwnProperty("binaryData"))
+                                object.binaryData = options.bytes === String ? $util.base64.encode(message.binaryData, 0, message.binaryData.length) : options.bytes === Array ? Array.prototype.slice.call(message.binaryData) : message.binaryData;
+                            return object;
+                        };
+    
+                        /**
+                         * Converts this DeviceState to JSON.
+                         * @function toJSON
+                         * @memberof google.cloud.iot.v1.DeviceState
+                         * @instance
+                         * @returns {Object.<string,*>} JSON object
+                         */
+                        DeviceState.prototype.toJSON = function toJSON() {
+                            return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                        };
+    
+                        return DeviceState;
+                    })();
+    
+                    return v1;
+                })();
+    
+                return iot;
+            })();
+    
+            return cloud;
+        })();
+    
+        google.api = (function() {
+    
+            /**
+             * Namespace api.
+             * @memberof google
+             * @namespace
+             */
+            var api = {};
+    
+            api.Http = (function() {
+    
+                /**
+                 * Properties of a Http.
+                 * @memberof google.api
+                 * @interface IHttp
+                 * @property {Array.<google.api.IHttpRule>|null} [rules] Http rules
+                 * @property {boolean|null} [fullyDecodeReservedExpansion] Http fullyDecodeReservedExpansion
+                 */
+    
+                /**
+                 * Constructs a new Http.
+                 * @memberof google.api
+                 * @classdesc Represents a Http.
+                 * @implements IHttp
+                 * @constructor
+                 * @param {google.api.IHttp=} [properties] Properties to set
+                 */
+                function Http(properties) {
+                    this.rules = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * Http rules.
+                 * @member {Array.<google.api.IHttpRule>} rules
+                 * @memberof google.api.Http
+                 * @instance
+                 */
+                Http.prototype.rules = $util.emptyArray;
+    
+                /**
+                 * Http fullyDecodeReservedExpansion.
+                 * @member {boolean} fullyDecodeReservedExpansion
+                 * @memberof google.api.Http
+                 * @instance
+                 */
+                Http.prototype.fullyDecodeReservedExpansion = false;
+    
+                /**
+                 * Creates a new Http instance using the specified properties.
+                 * @function create
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {google.api.IHttp=} [properties] Properties to set
+                 * @returns {google.api.Http} Http instance
+                 */
+                Http.create = function create(properties) {
+                    return new Http(properties);
+                };
+    
+                /**
+                 * Encodes the specified Http message. Does not implicitly {@link google.api.Http.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {google.api.IHttp} message Http message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Http.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.rules != null && message.rules.length)
+                        for (var i = 0; i < message.rules.length; ++i)
+                            $root.google.api.HttpRule.encode(message.rules[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                    if (message.fullyDecodeReservedExpansion != null && Object.hasOwnProperty.call(message, "fullyDecodeReservedExpansion"))
+                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.fullyDecodeReservedExpansion);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified Http message, length delimited. Does not implicitly {@link google.api.Http.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {google.api.IHttp} message Http message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Http.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a Http message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.api.Http} Http
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Http.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.api.Http();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            if (!(message.rules && message.rules.length))
+                                message.rules = [];
+                            message.rules.push($root.google.api.HttpRule.decode(reader, reader.uint32()));
+                            break;
+                        case 2:
+                            message.fullyDecodeReservedExpansion = reader.bool();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a Http message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.api.Http} Http
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Http.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a Http message.
+                 * @function verify
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                Http.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.rules != null && message.hasOwnProperty("rules")) {
+                        if (!Array.isArray(message.rules))
+                            return "rules: array expected";
+                        for (var i = 0; i < message.rules.length; ++i) {
+                            var error = $root.google.api.HttpRule.verify(message.rules[i]);
+                            if (error)
+                                return "rules." + error;
+                        }
+                    }
+                    if (message.fullyDecodeReservedExpansion != null && message.hasOwnProperty("fullyDecodeReservedExpansion"))
+                        if (typeof message.fullyDecodeReservedExpansion !== "boolean")
+                            return "fullyDecodeReservedExpansion: boolean expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a Http message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.api.Http} Http
+                 */
+                Http.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.api.Http)
+                        return object;
+                    var message = new $root.google.api.Http();
+                    if (object.rules) {
+                        if (!Array.isArray(object.rules))
+                            throw TypeError(".google.api.Http.rules: array expected");
+                        message.rules = [];
+                        for (var i = 0; i < object.rules.length; ++i) {
+                            if (typeof object.rules[i] !== "object")
+                                throw TypeError(".google.api.Http.rules: object expected");
+                            message.rules[i] = $root.google.api.HttpRule.fromObject(object.rules[i]);
+                        }
+                    }
+                    if (object.fullyDecodeReservedExpansion != null)
+                        message.fullyDecodeReservedExpansion = Boolean(object.fullyDecodeReservedExpansion);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a Http message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.api.Http
+                 * @static
+                 * @param {google.api.Http} message Http
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                Http.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.rules = [];
+                    if (options.defaults)
+                        object.fullyDecodeReservedExpansion = false;
+                    if (message.rules && message.rules.length) {
+                        object.rules = [];
+                        for (var j = 0; j < message.rules.length; ++j)
+                            object.rules[j] = $root.google.api.HttpRule.toObject(message.rules[j], options);
+                    }
+                    if (message.fullyDecodeReservedExpansion != null && message.hasOwnProperty("fullyDecodeReservedExpansion"))
+                        object.fullyDecodeReservedExpansion = message.fullyDecodeReservedExpansion;
+                    return object;
+                };
+    
+                /**
+                 * Converts this Http to JSON.
+                 * @function toJSON
+                 * @memberof google.api.Http
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                Http.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return Http;
+            })();
+    
+            api.HttpRule = (function() {
+    
+                /**
+                 * Properties of a HttpRule.
+                 * @memberof google.api
+                 * @interface IHttpRule
+                 * @property {string|null} [selector] HttpRule selector
+                 * @property {string|null} [get] HttpRule get
+                 * @property {string|null} [put] HttpRule put
+                 * @property {string|null} [post] HttpRule post
+                 * @property {string|null} ["delete"] HttpRule delete
+                 * @property {string|null} [patch] HttpRule patch
+                 * @property {google.api.ICustomHttpPattern|null} [custom] HttpRule custom
+                 * @property {string|null} [body] HttpRule body
+                 * @property {string|null} [responseBody] HttpRule responseBody
+                 * @property {Array.<google.api.IHttpRule>|null} [additionalBindings] HttpRule additionalBindings
+                 */
+    
+                /**
+                 * Constructs a new HttpRule.
+                 * @memberof google.api
+                 * @classdesc Represents a HttpRule.
+                 * @implements IHttpRule
+                 * @constructor
+                 * @param {google.api.IHttpRule=} [properties] Properties to set
+                 */
+                function HttpRule(properties) {
+                    this.additionalBindings = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * HttpRule selector.
+                 * @member {string} selector
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.selector = "";
+    
+                /**
+                 * HttpRule get.
+                 * @member {string|null|undefined} get
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.get = null;
+    
+                /**
+                 * HttpRule put.
+                 * @member {string|null|undefined} put
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.put = null;
+    
+                /**
+                 * HttpRule post.
+                 * @member {string|null|undefined} post
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.post = null;
+    
+                /**
+                 * HttpRule delete.
+                 * @member {string|null|undefined} delete
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype["delete"] = null;
+    
+                /**
+                 * HttpRule patch.
+                 * @member {string|null|undefined} patch
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.patch = null;
+    
+                /**
+                 * HttpRule custom.
+                 * @member {google.api.ICustomHttpPattern|null|undefined} custom
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.custom = null;
+    
+                /**
+                 * HttpRule body.
+                 * @member {string} body
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.body = "";
+    
+                /**
+                 * HttpRule responseBody.
+                 * @member {string} responseBody
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.responseBody = "";
+    
+                /**
+                 * HttpRule additionalBindings.
+                 * @member {Array.<google.api.IHttpRule>} additionalBindings
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                HttpRule.prototype.additionalBindings = $util.emptyArray;
+    
+                // OneOf field names bound to virtual getters and setters
+                var $oneOfFields;
+    
+                /**
+                 * HttpRule pattern.
+                 * @member {"get"|"put"|"post"|"delete"|"patch"|"custom"|undefined} pattern
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 */
+                Object.defineProperty(HttpRule.prototype, "pattern", {
+                    get: $util.oneOfGetter($oneOfFields = ["get", "put", "post", "delete", "patch", "custom"]),
+                    set: $util.oneOfSetter($oneOfFields)
+                });
+    
+                /**
+                 * Creates a new HttpRule instance using the specified properties.
+                 * @function create
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {google.api.IHttpRule=} [properties] Properties to set
+                 * @returns {google.api.HttpRule} HttpRule instance
+                 */
+                HttpRule.create = function create(properties) {
+                    return new HttpRule(properties);
+                };
+    
+                /**
+                 * Encodes the specified HttpRule message. Does not implicitly {@link google.api.HttpRule.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {google.api.IHttpRule} message HttpRule message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                HttpRule.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.selector != null && Object.hasOwnProperty.call(message, "selector"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.selector);
+                    if (message.get != null && Object.hasOwnProperty.call(message, "get"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.get);
+                    if (message.put != null && Object.hasOwnProperty.call(message, "put"))
+                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.put);
+                    if (message.post != null && Object.hasOwnProperty.call(message, "post"))
+                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.post);
+                    if (message["delete"] != null && Object.hasOwnProperty.call(message, "delete"))
+                        writer.uint32(/* id 5, wireType 2 =*/42).string(message["delete"]);
+                    if (message.patch != null && Object.hasOwnProperty.call(message, "patch"))
+                        writer.uint32(/* id 6, wireType 2 =*/50).string(message.patch);
+                    if (message.body != null && Object.hasOwnProperty.call(message, "body"))
+                        writer.uint32(/* id 7, wireType 2 =*/58).string(message.body);
+                    if (message.custom != null && Object.hasOwnProperty.call(message, "custom"))
+                        $root.google.api.CustomHttpPattern.encode(message.custom, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
+                    if (message.additionalBindings != null && message.additionalBindings.length)
+                        for (var i = 0; i < message.additionalBindings.length; ++i)
+                            $root.google.api.HttpRule.encode(message.additionalBindings[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
+                    if (message.responseBody != null && Object.hasOwnProperty.call(message, "responseBody"))
+                        writer.uint32(/* id 12, wireType 2 =*/98).string(message.responseBody);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified HttpRule message, length delimited. Does not implicitly {@link google.api.HttpRule.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {google.api.IHttpRule} message HttpRule message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                HttpRule.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a HttpRule message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.api.HttpRule} HttpRule
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                HttpRule.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.api.HttpRule();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.selector = reader.string();
+                            break;
+                        case 2:
+                            message.get = reader.string();
+                            break;
+                        case 3:
+                            message.put = reader.string();
+                            break;
+                        case 4:
+                            message.post = reader.string();
+                            break;
+                        case 5:
+                            message["delete"] = reader.string();
+                            break;
+                        case 6:
+                            message.patch = reader.string();
+                            break;
+                        case 8:
+                            message.custom = $root.google.api.CustomHttpPattern.decode(reader, reader.uint32());
+                            break;
+                        case 7:
+                            message.body = reader.string();
+                            break;
+                        case 12:
+                            message.responseBody = reader.string();
+                            break;
+                        case 11:
+                            if (!(message.additionalBindings && message.additionalBindings.length))
+                                message.additionalBindings = [];
+                            message.additionalBindings.push($root.google.api.HttpRule.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a HttpRule message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.api.HttpRule} HttpRule
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                HttpRule.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a HttpRule message.
+                 * @function verify
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                HttpRule.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    var properties = {};
+                    if (message.selector != null && message.hasOwnProperty("selector"))
+                        if (!$util.isString(message.selector))
+                            return "selector: string expected";
+                    if (message.get != null && message.hasOwnProperty("get")) {
+                        properties.pattern = 1;
+                        if (!$util.isString(message.get))
+                            return "get: string expected";
+                    }
+                    if (message.put != null && message.hasOwnProperty("put")) {
+                        if (properties.pattern === 1)
+                            return "pattern: multiple values";
+                        properties.pattern = 1;
+                        if (!$util.isString(message.put))
+                            return "put: string expected";
+                    }
+                    if (message.post != null && message.hasOwnProperty("post")) {
+                        if (properties.pattern === 1)
+                            return "pattern: multiple values";
+                        properties.pattern = 1;
+                        if (!$util.isString(message.post))
+                            return "post: string expected";
+                    }
+                    if (message["delete"] != null && message.hasOwnProperty("delete")) {
+                        if (properties.pattern === 1)
+                            return "pattern: multiple values";
+                        properties.pattern = 1;
+                        if (!$util.isString(message["delete"]))
+                            return "delete: string expected";
+                    }
+                    if (message.patch != null && message.hasOwnProperty("patch")) {
+                        if (properties.pattern === 1)
+                            return "pattern: multiple values";
+                        properties.pattern = 1;
+                        if (!$util.isString(message.patch))
+                            return "patch: string expected";
+                    }
+                    if (message.custom != null && message.hasOwnProperty("custom")) {
+                        if (properties.pattern === 1)
+                            return "pattern: multiple values";
+                        properties.pattern = 1;
+                        {
+                            var error = $root.google.api.CustomHttpPattern.verify(message.custom);
+                            if (error)
+                                return "custom." + error;
+                        }
+                    }
+                    if (message.body != null && message.hasOwnProperty("body"))
+                        if (!$util.isString(message.body))
+                            return "body: string expected";
+                    if (message.responseBody != null && message.hasOwnProperty("responseBody"))
+                        if (!$util.isString(message.responseBody))
+                            return "responseBody: string expected";
+                    if (message.additionalBindings != null && message.hasOwnProperty("additionalBindings")) {
+                        if (!Array.isArray(message.additionalBindings))
+                            return "additionalBindings: array expected";
+                        for (var i = 0; i < message.additionalBindings.length; ++i) {
+                            var error = $root.google.api.HttpRule.verify(message.additionalBindings[i]);
+                            if (error)
+                                return "additionalBindings." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a HttpRule message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.api.HttpRule} HttpRule
+                 */
+                HttpRule.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.api.HttpRule)
+                        return object;
+                    var message = new $root.google.api.HttpRule();
+                    if (object.selector != null)
+                        message.selector = String(object.selector);
+                    if (object.get != null)
+                        message.get = String(object.get);
+                    if (object.put != null)
+                        message.put = String(object.put);
+                    if (object.post != null)
+                        message.post = String(object.post);
+                    if (object["delete"] != null)
+                        message["delete"] = String(object["delete"]);
+                    if (object.patch != null)
+                        message.patch = String(object.patch);
+                    if (object.custom != null) {
+                        if (typeof object.custom !== "object")
+                            throw TypeError(".google.api.HttpRule.custom: object expected");
+                        message.custom = $root.google.api.CustomHttpPattern.fromObject(object.custom);
+                    }
+                    if (object.body != null)
+                        message.body = String(object.body);
+                    if (object.responseBody != null)
+                        message.responseBody = String(object.responseBody);
+                    if (object.additionalBindings) {
+                        if (!Array.isArray(object.additionalBindings))
+                            throw TypeError(".google.api.HttpRule.additionalBindings: array expected");
+                        message.additionalBindings = [];
+                        for (var i = 0; i < object.additionalBindings.length; ++i) {
+                            if (typeof object.additionalBindings[i] !== "object")
+                                throw TypeError(".google.api.HttpRule.additionalBindings: object expected");
+                            message.additionalBindings[i] = $root.google.api.HttpRule.fromObject(object.additionalBindings[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a HttpRule message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.api.HttpRule
+                 * @static
+                 * @param {google.api.HttpRule} message HttpRule
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                HttpRule.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.additionalBindings = [];
+                    if (options.defaults) {
+                        object.selector = "";
+                        object.body = "";
+                        object.responseBody = "";
+                    }
+                    if (message.selector != null && message.hasOwnProperty("selector"))
+                        object.selector = message.selector;
+                    if (message.get != null && message.hasOwnProperty("get")) {
+                        object.get = message.get;
+                        if (options.oneofs)
+                            object.pattern = "get";
+                    }
+                    if (message.put != null && message.hasOwnProperty("put")) {
+                        object.put = message.put;
+                        if (options.oneofs)
+                            object.pattern = "put";
+                    }
+                    if (message.post != null && message.hasOwnProperty("post")) {
+                        object.post = message.post;
+                        if (options.oneofs)
+                            object.pattern = "post";
+                    }
+                    if (message["delete"] != null && message.hasOwnProperty("delete")) {
+                        object["delete"] = message["delete"];
+                        if (options.oneofs)
+                            object.pattern = "delete";
+                    }
+                    if (message.patch != null && message.hasOwnProperty("patch")) {
+                        object.patch = message.patch;
+                        if (options.oneofs)
+                            object.pattern = "patch";
+                    }
+                    if (message.body != null && message.hasOwnProperty("body"))
+                        object.body = message.body;
+                    if (message.custom != null && message.hasOwnProperty("custom")) {
+                        object.custom = $root.google.api.CustomHttpPattern.toObject(message.custom, options);
+                        if (options.oneofs)
+                            object.pattern = "custom";
+                    }
+                    if (message.additionalBindings && message.additionalBindings.length) {
+                        object.additionalBindings = [];
+                        for (var j = 0; j < message.additionalBindings.length; ++j)
+                            object.additionalBindings[j] = $root.google.api.HttpRule.toObject(message.additionalBindings[j], options);
+                    }
+                    if (message.responseBody != null && message.hasOwnProperty("responseBody"))
+                        object.responseBody = message.responseBody;
+                    return object;
+                };
+    
+                /**
+                 * Converts this HttpRule to JSON.
+                 * @function toJSON
+                 * @memberof google.api.HttpRule
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                HttpRule.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return HttpRule;
+            })();
+    
+            api.CustomHttpPattern = (function() {
+    
+                /**
+                 * Properties of a CustomHttpPattern.
+                 * @memberof google.api
+                 * @interface ICustomHttpPattern
+                 * @property {string|null} [kind] CustomHttpPattern kind
+                 * @property {string|null} [path] CustomHttpPattern path
+                 */
+    
+                /**
+                 * Constructs a new CustomHttpPattern.
+                 * @memberof google.api
+                 * @classdesc Represents a CustomHttpPattern.
+                 * @implements ICustomHttpPattern
+                 * @constructor
+                 * @param {google.api.ICustomHttpPattern=} [properties] Properties to set
+                 */
+                function CustomHttpPattern(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * CustomHttpPattern kind.
+                 * @member {string} kind
+                 * @memberof google.api.CustomHttpPattern
+                 * @instance
+                 */
+                CustomHttpPattern.prototype.kind = "";
+    
+                /**
+                 * CustomHttpPattern path.
+                 * @member {string} path
+                 * @memberof google.api.CustomHttpPattern
+                 * @instance
+                 */
+                CustomHttpPattern.prototype.path = "";
+    
+                /**
+                 * Creates a new CustomHttpPattern instance using the specified properties.
+                 * @function create
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {google.api.ICustomHttpPattern=} [properties] Properties to set
+                 * @returns {google.api.CustomHttpPattern} CustomHttpPattern instance
+                 */
+                CustomHttpPattern.create = function create(properties) {
+                    return new CustomHttpPattern(properties);
+                };
+    
+                /**
+                 * Encodes the specified CustomHttpPattern message. Does not implicitly {@link google.api.CustomHttpPattern.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {google.api.ICustomHttpPattern} message CustomHttpPattern message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                CustomHttpPattern.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.kind != null && Object.hasOwnProperty.call(message, "kind"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.kind);
+                    if (message.path != null && Object.hasOwnProperty.call(message, "path"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.path);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified CustomHttpPattern message, length delimited. Does not implicitly {@link google.api.CustomHttpPattern.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {google.api.ICustomHttpPattern} message CustomHttpPattern message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                CustomHttpPattern.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a CustomHttpPattern message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.api.CustomHttpPattern} CustomHttpPattern
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                CustomHttpPattern.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.api.CustomHttpPattern();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.kind = reader.string();
+                            break;
+                        case 2:
+                            message.path = reader.string();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a CustomHttpPattern message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.api.CustomHttpPattern} CustomHttpPattern
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                CustomHttpPattern.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a CustomHttpPattern message.
+                 * @function verify
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                CustomHttpPattern.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.kind != null && message.hasOwnProperty("kind"))
+                        if (!$util.isString(message.kind))
+                            return "kind: string expected";
+                    if (message.path != null && message.hasOwnProperty("path"))
+                        if (!$util.isString(message.path))
+                            return "path: string expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a CustomHttpPattern message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.api.CustomHttpPattern} CustomHttpPattern
+                 */
+                CustomHttpPattern.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.api.CustomHttpPattern)
+                        return object;
+                    var message = new $root.google.api.CustomHttpPattern();
+                    if (object.kind != null)
+                        message.kind = String(object.kind);
+                    if (object.path != null)
+                        message.path = String(object.path);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a CustomHttpPattern message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.api.CustomHttpPattern
+                 * @static
+                 * @param {google.api.CustomHttpPattern} message CustomHttpPattern
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                CustomHttpPattern.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.kind = "";
+                        object.path = "";
+                    }
+                    if (message.kind != null && message.hasOwnProperty("kind"))
+                        object.kind = message.kind;
+                    if (message.path != null && message.hasOwnProperty("path"))
+                        object.path = message.path;
+                    return object;
+                };
+    
+                /**
+                 * Converts this CustomHttpPattern to JSON.
+                 * @function toJSON
+                 * @memberof google.api.CustomHttpPattern
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                CustomHttpPattern.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return CustomHttpPattern;
+            })();
+    
+            /**
+             * FieldBehavior enum.
+             * @name google.api.FieldBehavior
+             * @enum {number}
+             * @property {number} FIELD_BEHAVIOR_UNSPECIFIED=0 FIELD_BEHAVIOR_UNSPECIFIED value
+             * @property {number} OPTIONAL=1 OPTIONAL value
+             * @property {number} REQUIRED=2 REQUIRED value
+             * @property {number} OUTPUT_ONLY=3 OUTPUT_ONLY value
+             * @property {number} INPUT_ONLY=4 INPUT_ONLY value
+             * @property {number} IMMUTABLE=5 IMMUTABLE value
+             * @property {number} UNORDERED_LIST=6 UNORDERED_LIST value
+             * @property {number} NON_EMPTY_DEFAULT=7 NON_EMPTY_DEFAULT value
+             */
+            api.FieldBehavior = (function() {
+                var valuesById = {}, values = Object.create(valuesById);
+                values[valuesById[0] = "FIELD_BEHAVIOR_UNSPECIFIED"] = 0;
+                values[valuesById[1] = "OPTIONAL"] = 1;
+                values[valuesById[2] = "REQUIRED"] = 2;
+                values[valuesById[3] = "OUTPUT_ONLY"] = 3;
+                values[valuesById[4] = "INPUT_ONLY"] = 4;
+                values[valuesById[5] = "IMMUTABLE"] = 5;
+                values[valuesById[6] = "UNORDERED_LIST"] = 6;
+                values[valuesById[7] = "NON_EMPTY_DEFAULT"] = 7;
+                return values;
+            })();
+    
+            api.ResourceDescriptor = (function() {
+    
+                /**
+                 * Properties of a ResourceDescriptor.
+                 * @memberof google.api
+                 * @interface IResourceDescriptor
+                 * @property {string|null} [type] ResourceDescriptor type
+                 * @property {Array.<string>|null} [pattern] ResourceDescriptor pattern
+                 * @property {string|null} [nameField] ResourceDescriptor nameField
+                 * @property {google.api.ResourceDescriptor.History|null} [history] ResourceDescriptor history
+                 * @property {string|null} [plural] ResourceDescriptor plural
+                 * @property {string|null} [singular] ResourceDescriptor singular
+                 * @property {Array.<google.api.ResourceDescriptor.Style>|null} [style] ResourceDescriptor style
+                 */
+    
+                /**
+                 * Constructs a new ResourceDescriptor.
+                 * @memberof google.api
+                 * @classdesc Represents a ResourceDescriptor.
+                 * @implements IResourceDescriptor
+                 * @constructor
+                 * @param {google.api.IResourceDescriptor=} [properties] Properties to set
+                 */
+                function ResourceDescriptor(properties) {
+                    this.pattern = [];
+                    this.style = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * ResourceDescriptor type.
+                 * @member {string} type
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 */
+                ResourceDescriptor.prototype.type = "";
+    
+                /**
+                 * ResourceDescriptor pattern.
+                 * @member {Array.<string>} pattern
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 */
+                ResourceDescriptor.prototype.pattern = $util.emptyArray;
+    
+                /**
+                 * ResourceDescriptor nameField.
+                 * @member {string} nameField
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 */
+                ResourceDescriptor.prototype.nameField = "";
+    
+                /**
+                 * ResourceDescriptor history.
+                 * @member {google.api.ResourceDescriptor.History} history
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 */
+                ResourceDescriptor.prototype.history = 0;
+    
+                /**
+                 * ResourceDescriptor plural.
+                 * @member {string} plural
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 */
+                ResourceDescriptor.prototype.plural = "";
+    
+                /**
+                 * ResourceDescriptor singular.
+                 * @member {string} singular
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 */
+                ResourceDescriptor.prototype.singular = "";
+    
+                /**
+                 * ResourceDescriptor style.
+                 * @member {Array.<google.api.ResourceDescriptor.Style>} style
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 */
+                ResourceDescriptor.prototype.style = $util.emptyArray;
+    
+                /**
+                 * Creates a new ResourceDescriptor instance using the specified properties.
+                 * @function create
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {google.api.IResourceDescriptor=} [properties] Properties to set
+                 * @returns {google.api.ResourceDescriptor} ResourceDescriptor instance
+                 */
+                ResourceDescriptor.create = function create(properties) {
+                    return new ResourceDescriptor(properties);
+                };
+    
+                /**
+                 * Encodes the specified ResourceDescriptor message. Does not implicitly {@link google.api.ResourceDescriptor.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {google.api.IResourceDescriptor} message ResourceDescriptor message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ResourceDescriptor.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.type != null && Object.hasOwnProperty.call(message, "type"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.type);
+                    if (message.pattern != null && message.pattern.length)
+                        for (var i = 0; i < message.pattern.length; ++i)
+                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.pattern[i]);
+                    if (message.nameField != null && Object.hasOwnProperty.call(message, "nameField"))
+                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.nameField);
+                    if (message.history != null && Object.hasOwnProperty.call(message, "history"))
+                        writer.uint32(/* id 4, wireType 0 =*/32).int32(message.history);
+                    if (message.plural != null && Object.hasOwnProperty.call(message, "plural"))
+                        writer.uint32(/* id 5, wireType 2 =*/42).string(message.plural);
+                    if (message.singular != null && Object.hasOwnProperty.call(message, "singular"))
+                        writer.uint32(/* id 6, wireType 2 =*/50).string(message.singular);
+                    if (message.style != null && message.style.length) {
+                        writer.uint32(/* id 10, wireType 2 =*/82).fork();
+                        for (var i = 0; i < message.style.length; ++i)
+                            writer.int32(message.style[i]);
+                        writer.ldelim();
+                    }
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified ResourceDescriptor message, length delimited. Does not implicitly {@link google.api.ResourceDescriptor.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {google.api.IResourceDescriptor} message ResourceDescriptor message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ResourceDescriptor.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a ResourceDescriptor message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.api.ResourceDescriptor} ResourceDescriptor
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ResourceDescriptor.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.api.ResourceDescriptor();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.type = reader.string();
+                            break;
+                        case 2:
+                            if (!(message.pattern && message.pattern.length))
+                                message.pattern = [];
+                            message.pattern.push(reader.string());
+                            break;
+                        case 3:
+                            message.nameField = reader.string();
+                            break;
+                        case 4:
+                            message.history = reader.int32();
+                            break;
+                        case 5:
+                            message.plural = reader.string();
+                            break;
+                        case 6:
+                            message.singular = reader.string();
+                            break;
+                        case 10:
+                            if (!(message.style && message.style.length))
+                                message.style = [];
+                            if ((tag & 7) === 2) {
+                                var end2 = reader.uint32() + reader.pos;
+                                while (reader.pos < end2)
+                                    message.style.push(reader.int32());
+                            } else
+                                message.style.push(reader.int32());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a ResourceDescriptor message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.api.ResourceDescriptor} ResourceDescriptor
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ResourceDescriptor.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a ResourceDescriptor message.
+                 * @function verify
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                ResourceDescriptor.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.type != null && message.hasOwnProperty("type"))
+                        if (!$util.isString(message.type))
+                            return "type: string expected";
+                    if (message.pattern != null && message.hasOwnProperty("pattern")) {
+                        if (!Array.isArray(message.pattern))
+                            return "pattern: array expected";
+                        for (var i = 0; i < message.pattern.length; ++i)
+                            if (!$util.isString(message.pattern[i]))
+                                return "pattern: string[] expected";
+                    }
+                    if (message.nameField != null && message.hasOwnProperty("nameField"))
+                        if (!$util.isString(message.nameField))
+                            return "nameField: string expected";
+                    if (message.history != null && message.hasOwnProperty("history"))
+                        switch (message.history) {
+                        default:
+                            return "history: enum value expected";
+                        case 0:
+                        case 1:
+                        case 2:
+                            break;
+                        }
+                    if (message.plural != null && message.hasOwnProperty("plural"))
+                        if (!$util.isString(message.plural))
+                            return "plural: string expected";
+                    if (message.singular != null && message.hasOwnProperty("singular"))
+                        if (!$util.isString(message.singular))
+                            return "singular: string expected";
+                    if (message.style != null && message.hasOwnProperty("style")) {
+                        if (!Array.isArray(message.style))
+                            return "style: array expected";
+                        for (var i = 0; i < message.style.length; ++i)
+                            switch (message.style[i]) {
+                            default:
+                                return "style: enum value[] expected";
+                            case 0:
+                            case 1:
+                                break;
+                            }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a ResourceDescriptor message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.api.ResourceDescriptor} ResourceDescriptor
+                 */
+                ResourceDescriptor.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.api.ResourceDescriptor)
+                        return object;
+                    var message = new $root.google.api.ResourceDescriptor();
+                    if (object.type != null)
+                        message.type = String(object.type);
+                    if (object.pattern) {
+                        if (!Array.isArray(object.pattern))
+                            throw TypeError(".google.api.ResourceDescriptor.pattern: array expected");
+                        message.pattern = [];
+                        for (var i = 0; i < object.pattern.length; ++i)
+                            message.pattern[i] = String(object.pattern[i]);
+                    }
+                    if (object.nameField != null)
+                        message.nameField = String(object.nameField);
+                    switch (object.history) {
+                    case "HISTORY_UNSPECIFIED":
+                    case 0:
+                        message.history = 0;
+                        break;
+                    case "ORIGINALLY_SINGLE_PATTERN":
+                    case 1:
+                        message.history = 1;
+                        break;
+                    case "FUTURE_MULTI_PATTERN":
+                    case 2:
+                        message.history = 2;
+                        break;
+                    }
+                    if (object.plural != null)
+                        message.plural = String(object.plural);
+                    if (object.singular != null)
+                        message.singular = String(object.singular);
+                    if (object.style) {
+                        if (!Array.isArray(object.style))
+                            throw TypeError(".google.api.ResourceDescriptor.style: array expected");
+                        message.style = [];
+                        for (var i = 0; i < object.style.length; ++i)
+                            switch (object.style[i]) {
+                            default:
+                            case "STYLE_UNSPECIFIED":
+                            case 0:
+                                message.style[i] = 0;
+                                break;
+                            case "DECLARATIVE_FRIENDLY":
+                            case 1:
+                                message.style[i] = 1;
+                                break;
+                            }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a ResourceDescriptor message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.api.ResourceDescriptor
+                 * @static
+                 * @param {google.api.ResourceDescriptor} message ResourceDescriptor
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                ResourceDescriptor.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults) {
+                        object.pattern = [];
+                        object.style = [];
+                    }
+                    if (options.defaults) {
+                        object.type = "";
+                        object.nameField = "";
+                        object.history = options.enums === String ? "HISTORY_UNSPECIFIED" : 0;
+                        object.plural = "";
+                        object.singular = "";
+                    }
+                    if (message.type != null && message.hasOwnProperty("type"))
+                        object.type = message.type;
+                    if (message.pattern && message.pattern.length) {
+                        object.pattern = [];
+                        for (var j = 0; j < message.pattern.length; ++j)
+                            object.pattern[j] = message.pattern[j];
+                    }
+                    if (message.nameField != null && message.hasOwnProperty("nameField"))
+                        object.nameField = message.nameField;
+                    if (message.history != null && message.hasOwnProperty("history"))
+                        object.history = options.enums === String ? $root.google.api.ResourceDescriptor.History[message.history] : message.history;
+                    if (message.plural != null && message.hasOwnProperty("plural"))
+                        object.plural = message.plural;
+                    if (message.singular != null && message.hasOwnProperty("singular"))
+                        object.singular = message.singular;
+                    if (message.style && message.style.length) {
+                        object.style = [];
+                        for (var j = 0; j < message.style.length; ++j)
+                            object.style[j] = options.enums === String ? $root.google.api.ResourceDescriptor.Style[message.style[j]] : message.style[j];
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this ResourceDescriptor to JSON.
+                 * @function toJSON
+                 * @memberof google.api.ResourceDescriptor
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                ResourceDescriptor.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                /**
+                 * History enum.
+                 * @name google.api.ResourceDescriptor.History
+                 * @enum {number}
+                 * @property {number} HISTORY_UNSPECIFIED=0 HISTORY_UNSPECIFIED value
+                 * @property {number} ORIGINALLY_SINGLE_PATTERN=1 ORIGINALLY_SINGLE_PATTERN value
+                 * @property {number} FUTURE_MULTI_PATTERN=2 FUTURE_MULTI_PATTERN value
+                 */
+                ResourceDescriptor.History = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[0] = "HISTORY_UNSPECIFIED"] = 0;
+                    values[valuesById[1] = "ORIGINALLY_SINGLE_PATTERN"] = 1;
+                    values[valuesById[2] = "FUTURE_MULTI_PATTERN"] = 2;
+                    return values;
+                })();
+    
+                /**
+                 * Style enum.
+                 * @name google.api.ResourceDescriptor.Style
+                 * @enum {number}
+                 * @property {number} STYLE_UNSPECIFIED=0 STYLE_UNSPECIFIED value
+                 * @property {number} DECLARATIVE_FRIENDLY=1 DECLARATIVE_FRIENDLY value
+                 */
+                ResourceDescriptor.Style = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[0] = "STYLE_UNSPECIFIED"] = 0;
+                    values[valuesById[1] = "DECLARATIVE_FRIENDLY"] = 1;
+                    return values;
+                })();
+    
+                return ResourceDescriptor;
+            })();
+    
+            api.ResourceReference = (function() {
+    
+                /**
+                 * Properties of a ResourceReference.
+                 * @memberof google.api
+                 * @interface IResourceReference
+                 * @property {string|null} [type] ResourceReference type
+                 * @property {string|null} [childType] ResourceReference childType
+                 */
+    
+                /**
+                 * Constructs a new ResourceReference.
+                 * @memberof google.api
+                 * @classdesc Represents a ResourceReference.
+                 * @implements IResourceReference
+                 * @constructor
+                 * @param {google.api.IResourceReference=} [properties] Properties to set
+                 */
+                function ResourceReference(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * ResourceReference type.
+                 * @member {string} type
+                 * @memberof google.api.ResourceReference
+                 * @instance
+                 */
+                ResourceReference.prototype.type = "";
+    
+                /**
+                 * ResourceReference childType.
+                 * @member {string} childType
+                 * @memberof google.api.ResourceReference
+                 * @instance
+                 */
+                ResourceReference.prototype.childType = "";
+    
+                /**
+                 * Creates a new ResourceReference instance using the specified properties.
+                 * @function create
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {google.api.IResourceReference=} [properties] Properties to set
+                 * @returns {google.api.ResourceReference} ResourceReference instance
+                 */
+                ResourceReference.create = function create(properties) {
+                    return new ResourceReference(properties);
+                };
+    
+                /**
+                 * Encodes the specified ResourceReference message. Does not implicitly {@link google.api.ResourceReference.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {google.api.IResourceReference} message ResourceReference message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ResourceReference.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.type != null && Object.hasOwnProperty.call(message, "type"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.type);
+                    if (message.childType != null && Object.hasOwnProperty.call(message, "childType"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.childType);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified ResourceReference message, length delimited. Does not implicitly {@link google.api.ResourceReference.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {google.api.IResourceReference} message ResourceReference message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ResourceReference.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a ResourceReference message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.api.ResourceReference} ResourceReference
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ResourceReference.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.api.ResourceReference();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.type = reader.string();
+                            break;
+                        case 2:
+                            message.childType = reader.string();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a ResourceReference message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.api.ResourceReference} ResourceReference
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ResourceReference.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a ResourceReference message.
+                 * @function verify
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                ResourceReference.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.type != null && message.hasOwnProperty("type"))
+                        if (!$util.isString(message.type))
+                            return "type: string expected";
+                    if (message.childType != null && message.hasOwnProperty("childType"))
+                        if (!$util.isString(message.childType))
+                            return "childType: string expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a ResourceReference message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.api.ResourceReference} ResourceReference
+                 */
+                ResourceReference.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.api.ResourceReference)
+                        return object;
+                    var message = new $root.google.api.ResourceReference();
+                    if (object.type != null)
+                        message.type = String(object.type);
+                    if (object.childType != null)
+                        message.childType = String(object.childType);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a ResourceReference message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.api.ResourceReference
+                 * @static
+                 * @param {google.api.ResourceReference} message ResourceReference
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                ResourceReference.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.type = "";
+                        object.childType = "";
+                    }
+                    if (message.type != null && message.hasOwnProperty("type"))
+                        object.type = message.type;
+                    if (message.childType != null && message.hasOwnProperty("childType"))
+                        object.childType = message.childType;
+                    return object;
+                };
+    
+                /**
+                 * Converts this ResourceReference to JSON.
+                 * @function toJSON
+                 * @memberof google.api.ResourceReference
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                ResourceReference.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return ResourceReference;
+            })();
+    
+            return api;
+        })();
+    
+        google.protobuf = (function() {
+    
+            /**
+             * Namespace protobuf.
+             * @memberof google
+             * @namespace
+             */
+            var protobuf = {};
+    
+            protobuf.FileDescriptorSet = (function() {
+    
+                /**
+                 * Properties of a FileDescriptorSet.
+                 * @memberof google.protobuf
+                 * @interface IFileDescriptorSet
+                 * @property {Array.<google.protobuf.IFileDescriptorProto>|null} [file] FileDescriptorSet file
+                 */
+    
+                /**
+                 * Constructs a new FileDescriptorSet.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a FileDescriptorSet.
+                 * @implements IFileDescriptorSet
+                 * @constructor
+                 * @param {google.protobuf.IFileDescriptorSet=} [properties] Properties to set
+                 */
+                function FileDescriptorSet(properties) {
+                    this.file = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * FileDescriptorSet file.
+                 * @member {Array.<google.protobuf.IFileDescriptorProto>} file
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @instance
+                 */
+                FileDescriptorSet.prototype.file = $util.emptyArray;
+    
+                /**
+                 * Creates a new FileDescriptorSet instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {google.protobuf.IFileDescriptorSet=} [properties] Properties to set
+                 * @returns {google.protobuf.FileDescriptorSet} FileDescriptorSet instance
+                 */
+                FileDescriptorSet.create = function create(properties) {
+                    return new FileDescriptorSet(properties);
+                };
+    
+                /**
+                 * Encodes the specified FileDescriptorSet message. Does not implicitly {@link google.protobuf.FileDescriptorSet.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {google.protobuf.IFileDescriptorSet} message FileDescriptorSet message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FileDescriptorSet.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.file != null && message.file.length)
+                        for (var i = 0; i < message.file.length; ++i)
+                            $root.google.protobuf.FileDescriptorProto.encode(message.file[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified FileDescriptorSet message, length delimited. Does not implicitly {@link google.protobuf.FileDescriptorSet.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {google.protobuf.IFileDescriptorSet} message FileDescriptorSet message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FileDescriptorSet.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a FileDescriptorSet message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.FileDescriptorSet} FileDescriptorSet
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FileDescriptorSet.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.FileDescriptorSet();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            if (!(message.file && message.file.length))
+                                message.file = [];
+                            message.file.push($root.google.protobuf.FileDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a FileDescriptorSet message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.FileDescriptorSet} FileDescriptorSet
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FileDescriptorSet.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a FileDescriptorSet message.
+                 * @function verify
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                FileDescriptorSet.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.file != null && message.hasOwnProperty("file")) {
+                        if (!Array.isArray(message.file))
+                            return "file: array expected";
+                        for (var i = 0; i < message.file.length; ++i) {
+                            var error = $root.google.protobuf.FileDescriptorProto.verify(message.file[i]);
+                            if (error)
+                                return "file." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a FileDescriptorSet message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.FileDescriptorSet} FileDescriptorSet
+                 */
+                FileDescriptorSet.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.FileDescriptorSet)
+                        return object;
+                    var message = new $root.google.protobuf.FileDescriptorSet();
+                    if (object.file) {
+                        if (!Array.isArray(object.file))
+                            throw TypeError(".google.protobuf.FileDescriptorSet.file: array expected");
+                        message.file = [];
+                        for (var i = 0; i < object.file.length; ++i) {
+                            if (typeof object.file[i] !== "object")
+                                throw TypeError(".google.protobuf.FileDescriptorSet.file: object expected");
+                            message.file[i] = $root.google.protobuf.FileDescriptorProto.fromObject(object.file[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a FileDescriptorSet message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @static
+                 * @param {google.protobuf.FileDescriptorSet} message FileDescriptorSet
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                FileDescriptorSet.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.file = [];
+                    if (message.file && message.file.length) {
+                        object.file = [];
+                        for (var j = 0; j < message.file.length; ++j)
+                            object.file[j] = $root.google.protobuf.FileDescriptorProto.toObject(message.file[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this FileDescriptorSet to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.FileDescriptorSet
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                FileDescriptorSet.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return FileDescriptorSet;
+            })();
+    
+            protobuf.FileDescriptorProto = (function() {
+    
+                /**
+                 * Properties of a FileDescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IFileDescriptorProto
+                 * @property {string|null} [name] FileDescriptorProto name
+                 * @property {string|null} ["package"] FileDescriptorProto package
+                 * @property {Array.<string>|null} [dependency] FileDescriptorProto dependency
+                 * @property {Array.<number>|null} [publicDependency] FileDescriptorProto publicDependency
+                 * @property {Array.<number>|null} [weakDependency] FileDescriptorProto weakDependency
+                 * @property {Array.<google.protobuf.IDescriptorProto>|null} [messageType] FileDescriptorProto messageType
+                 * @property {Array.<google.protobuf.IEnumDescriptorProto>|null} [enumType] FileDescriptorProto enumType
+                 * @property {Array.<google.protobuf.IServiceDescriptorProto>|null} [service] FileDescriptorProto service
+                 * @property {Array.<google.protobuf.IFieldDescriptorProto>|null} [extension] FileDescriptorProto extension
+                 * @property {google.protobuf.IFileOptions|null} [options] FileDescriptorProto options
+                 * @property {google.protobuf.ISourceCodeInfo|null} [sourceCodeInfo] FileDescriptorProto sourceCodeInfo
+                 * @property {string|null} [syntax] FileDescriptorProto syntax
+                 */
+    
+                /**
+                 * Constructs a new FileDescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a FileDescriptorProto.
+                 * @implements IFileDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IFileDescriptorProto=} [properties] Properties to set
+                 */
+                function FileDescriptorProto(properties) {
+                    this.dependency = [];
+                    this.publicDependency = [];
+                    this.weakDependency = [];
+                    this.messageType = [];
+                    this.enumType = [];
+                    this.service = [];
+                    this.extension = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * FileDescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.name = "";
+    
+                /**
+                 * FileDescriptorProto package.
+                 * @member {string} package
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype["package"] = "";
+    
+                /**
+                 * FileDescriptorProto dependency.
+                 * @member {Array.<string>} dependency
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.dependency = $util.emptyArray;
+    
+                /**
+                 * FileDescriptorProto publicDependency.
+                 * @member {Array.<number>} publicDependency
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.publicDependency = $util.emptyArray;
+    
+                /**
+                 * FileDescriptorProto weakDependency.
+                 * @member {Array.<number>} weakDependency
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.weakDependency = $util.emptyArray;
+    
+                /**
+                 * FileDescriptorProto messageType.
+                 * @member {Array.<google.protobuf.IDescriptorProto>} messageType
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.messageType = $util.emptyArray;
+    
+                /**
+                 * FileDescriptorProto enumType.
+                 * @member {Array.<google.protobuf.IEnumDescriptorProto>} enumType
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.enumType = $util.emptyArray;
+    
+                /**
+                 * FileDescriptorProto service.
+                 * @member {Array.<google.protobuf.IServiceDescriptorProto>} service
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.service = $util.emptyArray;
+    
+                /**
+                 * FileDescriptorProto extension.
+                 * @member {Array.<google.protobuf.IFieldDescriptorProto>} extension
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.extension = $util.emptyArray;
+    
+                /**
+                 * FileDescriptorProto options.
+                 * @member {google.protobuf.IFileOptions|null|undefined} options
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.options = null;
+    
+                /**
+                 * FileDescriptorProto sourceCodeInfo.
+                 * @member {google.protobuf.ISourceCodeInfo|null|undefined} sourceCodeInfo
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.sourceCodeInfo = null;
+    
+                /**
+                 * FileDescriptorProto syntax.
+                 * @member {string} syntax
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 */
+                FileDescriptorProto.prototype.syntax = "";
+    
+                /**
+                 * Creates a new FileDescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IFileDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.FileDescriptorProto} FileDescriptorProto instance
+                 */
+                FileDescriptorProto.create = function create(properties) {
+                    return new FileDescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified FileDescriptorProto message. Does not implicitly {@link google.protobuf.FileDescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IFileDescriptorProto} message FileDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FileDescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message["package"] != null && Object.hasOwnProperty.call(message, "package"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message["package"]);
+                    if (message.dependency != null && message.dependency.length)
+                        for (var i = 0; i < message.dependency.length; ++i)
+                            writer.uint32(/* id 3, wireType 2 =*/26).string(message.dependency[i]);
+                    if (message.messageType != null && message.messageType.length)
+                        for (var i = 0; i < message.messageType.length; ++i)
+                            $root.google.protobuf.DescriptorProto.encode(message.messageType[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                    if (message.enumType != null && message.enumType.length)
+                        for (var i = 0; i < message.enumType.length; ++i)
+                            $root.google.protobuf.EnumDescriptorProto.encode(message.enumType[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
+                    if (message.service != null && message.service.length)
+                        for (var i = 0; i < message.service.length; ++i)
+                            $root.google.protobuf.ServiceDescriptorProto.encode(message.service[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
+                    if (message.extension != null && message.extension.length)
+                        for (var i = 0; i < message.extension.length; ++i)
+                            $root.google.protobuf.FieldDescriptorProto.encode(message.extension[i], writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.FileOptions.encode(message.options, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
+                    if (message.sourceCodeInfo != null && Object.hasOwnProperty.call(message, "sourceCodeInfo"))
+                        $root.google.protobuf.SourceCodeInfo.encode(message.sourceCodeInfo, writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim();
+                    if (message.publicDependency != null && message.publicDependency.length)
+                        for (var i = 0; i < message.publicDependency.length; ++i)
+                            writer.uint32(/* id 10, wireType 0 =*/80).int32(message.publicDependency[i]);
+                    if (message.weakDependency != null && message.weakDependency.length)
+                        for (var i = 0; i < message.weakDependency.length; ++i)
+                            writer.uint32(/* id 11, wireType 0 =*/88).int32(message.weakDependency[i]);
+                    if (message.syntax != null && Object.hasOwnProperty.call(message, "syntax"))
+                        writer.uint32(/* id 12, wireType 2 =*/98).string(message.syntax);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified FileDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.FileDescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IFileDescriptorProto} message FileDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FileDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a FileDescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.FileDescriptorProto} FileDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FileDescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.FileDescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 2:
+                            message["package"] = reader.string();
+                            break;
+                        case 3:
+                            if (!(message.dependency && message.dependency.length))
+                                message.dependency = [];
+                            message.dependency.push(reader.string());
+                            break;
+                        case 10:
+                            if (!(message.publicDependency && message.publicDependency.length))
+                                message.publicDependency = [];
+                            if ((tag & 7) === 2) {
+                                var end2 = reader.uint32() + reader.pos;
+                                while (reader.pos < end2)
+                                    message.publicDependency.push(reader.int32());
+                            } else
+                                message.publicDependency.push(reader.int32());
+                            break;
+                        case 11:
+                            if (!(message.weakDependency && message.weakDependency.length))
+                                message.weakDependency = [];
+                            if ((tag & 7) === 2) {
+                                var end2 = reader.uint32() + reader.pos;
+                                while (reader.pos < end2)
+                                    message.weakDependency.push(reader.int32());
+                            } else
+                                message.weakDependency.push(reader.int32());
+                            break;
+                        case 4:
+                            if (!(message.messageType && message.messageType.length))
+                                message.messageType = [];
+                            message.messageType.push($root.google.protobuf.DescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 5:
+                            if (!(message.enumType && message.enumType.length))
+                                message.enumType = [];
+                            message.enumType.push($root.google.protobuf.EnumDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 6:
+                            if (!(message.service && message.service.length))
+                                message.service = [];
+                            message.service.push($root.google.protobuf.ServiceDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 7:
+                            if (!(message.extension && message.extension.length))
+                                message.extension = [];
+                            message.extension.push($root.google.protobuf.FieldDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 8:
+                            message.options = $root.google.protobuf.FileOptions.decode(reader, reader.uint32());
+                            break;
+                        case 9:
+                            message.sourceCodeInfo = $root.google.protobuf.SourceCodeInfo.decode(reader, reader.uint32());
+                            break;
+                        case 12:
+                            message.syntax = reader.string();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a FileDescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.FileDescriptorProto} FileDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FileDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a FileDescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                FileDescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message["package"] != null && message.hasOwnProperty("package"))
+                        if (!$util.isString(message["package"]))
+                            return "package: string expected";
+                    if (message.dependency != null && message.hasOwnProperty("dependency")) {
+                        if (!Array.isArray(message.dependency))
+                            return "dependency: array expected";
+                        for (var i = 0; i < message.dependency.length; ++i)
+                            if (!$util.isString(message.dependency[i]))
+                                return "dependency: string[] expected";
+                    }
+                    if (message.publicDependency != null && message.hasOwnProperty("publicDependency")) {
+                        if (!Array.isArray(message.publicDependency))
+                            return "publicDependency: array expected";
+                        for (var i = 0; i < message.publicDependency.length; ++i)
+                            if (!$util.isInteger(message.publicDependency[i]))
+                                return "publicDependency: integer[] expected";
+                    }
+                    if (message.weakDependency != null && message.hasOwnProperty("weakDependency")) {
+                        if (!Array.isArray(message.weakDependency))
+                            return "weakDependency: array expected";
+                        for (var i = 0; i < message.weakDependency.length; ++i)
+                            if (!$util.isInteger(message.weakDependency[i]))
+                                return "weakDependency: integer[] expected";
+                    }
+                    if (message.messageType != null && message.hasOwnProperty("messageType")) {
+                        if (!Array.isArray(message.messageType))
+                            return "messageType: array expected";
+                        for (var i = 0; i < message.messageType.length; ++i) {
+                            var error = $root.google.protobuf.DescriptorProto.verify(message.messageType[i]);
+                            if (error)
+                                return "messageType." + error;
+                        }
+                    }
+                    if (message.enumType != null && message.hasOwnProperty("enumType")) {
+                        if (!Array.isArray(message.enumType))
+                            return "enumType: array expected";
+                        for (var i = 0; i < message.enumType.length; ++i) {
+                            var error = $root.google.protobuf.EnumDescriptorProto.verify(message.enumType[i]);
+                            if (error)
+                                return "enumType." + error;
+                        }
+                    }
+                    if (message.service != null && message.hasOwnProperty("service")) {
+                        if (!Array.isArray(message.service))
+                            return "service: array expected";
+                        for (var i = 0; i < message.service.length; ++i) {
+                            var error = $root.google.protobuf.ServiceDescriptorProto.verify(message.service[i]);
+                            if (error)
+                                return "service." + error;
+                        }
+                    }
+                    if (message.extension != null && message.hasOwnProperty("extension")) {
+                        if (!Array.isArray(message.extension))
+                            return "extension: array expected";
+                        for (var i = 0; i < message.extension.length; ++i) {
+                            var error = $root.google.protobuf.FieldDescriptorProto.verify(message.extension[i]);
+                            if (error)
+                                return "extension." + error;
+                        }
+                    }
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.FileOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    if (message.sourceCodeInfo != null && message.hasOwnProperty("sourceCodeInfo")) {
+                        var error = $root.google.protobuf.SourceCodeInfo.verify(message.sourceCodeInfo);
+                        if (error)
+                            return "sourceCodeInfo." + error;
+                    }
+                    if (message.syntax != null && message.hasOwnProperty("syntax"))
+                        if (!$util.isString(message.syntax))
+                            return "syntax: string expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a FileDescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.FileDescriptorProto} FileDescriptorProto
+                 */
+                FileDescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.FileDescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.FileDescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object["package"] != null)
+                        message["package"] = String(object["package"]);
+                    if (object.dependency) {
+                        if (!Array.isArray(object.dependency))
+                            throw TypeError(".google.protobuf.FileDescriptorProto.dependency: array expected");
+                        message.dependency = [];
+                        for (var i = 0; i < object.dependency.length; ++i)
+                            message.dependency[i] = String(object.dependency[i]);
+                    }
+                    if (object.publicDependency) {
+                        if (!Array.isArray(object.publicDependency))
+                            throw TypeError(".google.protobuf.FileDescriptorProto.publicDependency: array expected");
+                        message.publicDependency = [];
+                        for (var i = 0; i < object.publicDependency.length; ++i)
+                            message.publicDependency[i] = object.publicDependency[i] | 0;
+                    }
+                    if (object.weakDependency) {
+                        if (!Array.isArray(object.weakDependency))
+                            throw TypeError(".google.protobuf.FileDescriptorProto.weakDependency: array expected");
+                        message.weakDependency = [];
+                        for (var i = 0; i < object.weakDependency.length; ++i)
+                            message.weakDependency[i] = object.weakDependency[i] | 0;
+                    }
+                    if (object.messageType) {
+                        if (!Array.isArray(object.messageType))
+                            throw TypeError(".google.protobuf.FileDescriptorProto.messageType: array expected");
+                        message.messageType = [];
+                        for (var i = 0; i < object.messageType.length; ++i) {
+                            if (typeof object.messageType[i] !== "object")
+                                throw TypeError(".google.protobuf.FileDescriptorProto.messageType: object expected");
+                            message.messageType[i] = $root.google.protobuf.DescriptorProto.fromObject(object.messageType[i]);
+                        }
+                    }
+                    if (object.enumType) {
+                        if (!Array.isArray(object.enumType))
+                            throw TypeError(".google.protobuf.FileDescriptorProto.enumType: array expected");
+                        message.enumType = [];
+                        for (var i = 0; i < object.enumType.length; ++i) {
+                            if (typeof object.enumType[i] !== "object")
+                                throw TypeError(".google.protobuf.FileDescriptorProto.enumType: object expected");
+                            message.enumType[i] = $root.google.protobuf.EnumDescriptorProto.fromObject(object.enumType[i]);
+                        }
+                    }
+                    if (object.service) {
+                        if (!Array.isArray(object.service))
+                            throw TypeError(".google.protobuf.FileDescriptorProto.service: array expected");
+                        message.service = [];
+                        for (var i = 0; i < object.service.length; ++i) {
+                            if (typeof object.service[i] !== "object")
+                                throw TypeError(".google.protobuf.FileDescriptorProto.service: object expected");
+                            message.service[i] = $root.google.protobuf.ServiceDescriptorProto.fromObject(object.service[i]);
+                        }
+                    }
+                    if (object.extension) {
+                        if (!Array.isArray(object.extension))
+                            throw TypeError(".google.protobuf.FileDescriptorProto.extension: array expected");
+                        message.extension = [];
+                        for (var i = 0; i < object.extension.length; ++i) {
+                            if (typeof object.extension[i] !== "object")
+                                throw TypeError(".google.protobuf.FileDescriptorProto.extension: object expected");
+                            message.extension[i] = $root.google.protobuf.FieldDescriptorProto.fromObject(object.extension[i]);
+                        }
+                    }
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.FileDescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.FileOptions.fromObject(object.options);
+                    }
+                    if (object.sourceCodeInfo != null) {
+                        if (typeof object.sourceCodeInfo !== "object")
+                            throw TypeError(".google.protobuf.FileDescriptorProto.sourceCodeInfo: object expected");
+                        message.sourceCodeInfo = $root.google.protobuf.SourceCodeInfo.fromObject(object.sourceCodeInfo);
+                    }
+                    if (object.syntax != null)
+                        message.syntax = String(object.syntax);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a FileDescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @static
+                 * @param {google.protobuf.FileDescriptorProto} message FileDescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                FileDescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults) {
+                        object.dependency = [];
+                        object.messageType = [];
+                        object.enumType = [];
+                        object.service = [];
+                        object.extension = [];
+                        object.publicDependency = [];
+                        object.weakDependency = [];
+                    }
+                    if (options.defaults) {
+                        object.name = "";
+                        object["package"] = "";
+                        object.options = null;
+                        object.sourceCodeInfo = null;
+                        object.syntax = "";
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message["package"] != null && message.hasOwnProperty("package"))
+                        object["package"] = message["package"];
+                    if (message.dependency && message.dependency.length) {
+                        object.dependency = [];
+                        for (var j = 0; j < message.dependency.length; ++j)
+                            object.dependency[j] = message.dependency[j];
+                    }
+                    if (message.messageType && message.messageType.length) {
+                        object.messageType = [];
+                        for (var j = 0; j < message.messageType.length; ++j)
+                            object.messageType[j] = $root.google.protobuf.DescriptorProto.toObject(message.messageType[j], options);
+                    }
+                    if (message.enumType && message.enumType.length) {
+                        object.enumType = [];
+                        for (var j = 0; j < message.enumType.length; ++j)
+                            object.enumType[j] = $root.google.protobuf.EnumDescriptorProto.toObject(message.enumType[j], options);
+                    }
+                    if (message.service && message.service.length) {
+                        object.service = [];
+                        for (var j = 0; j < message.service.length; ++j)
+                            object.service[j] = $root.google.protobuf.ServiceDescriptorProto.toObject(message.service[j], options);
+                    }
+                    if (message.extension && message.extension.length) {
+                        object.extension = [];
+                        for (var j = 0; j < message.extension.length; ++j)
+                            object.extension[j] = $root.google.protobuf.FieldDescriptorProto.toObject(message.extension[j], options);
+                    }
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.FileOptions.toObject(message.options, options);
+                    if (message.sourceCodeInfo != null && message.hasOwnProperty("sourceCodeInfo"))
+                        object.sourceCodeInfo = $root.google.protobuf.SourceCodeInfo.toObject(message.sourceCodeInfo, options);
+                    if (message.publicDependency && message.publicDependency.length) {
+                        object.publicDependency = [];
+                        for (var j = 0; j < message.publicDependency.length; ++j)
+                            object.publicDependency[j] = message.publicDependency[j];
+                    }
+                    if (message.weakDependency && message.weakDependency.length) {
+                        object.weakDependency = [];
+                        for (var j = 0; j < message.weakDependency.length; ++j)
+                            object.weakDependency[j] = message.weakDependency[j];
+                    }
+                    if (message.syntax != null && message.hasOwnProperty("syntax"))
+                        object.syntax = message.syntax;
+                    return object;
+                };
+    
+                /**
+                 * Converts this FileDescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.FileDescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                FileDescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return FileDescriptorProto;
+            })();
+    
+            protobuf.DescriptorProto = (function() {
+    
+                /**
+                 * Properties of a DescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IDescriptorProto
+                 * @property {string|null} [name] DescriptorProto name
+                 * @property {Array.<google.protobuf.IFieldDescriptorProto>|null} [field] DescriptorProto field
+                 * @property {Array.<google.protobuf.IFieldDescriptorProto>|null} [extension] DescriptorProto extension
+                 * @property {Array.<google.protobuf.IDescriptorProto>|null} [nestedType] DescriptorProto nestedType
+                 * @property {Array.<google.protobuf.IEnumDescriptorProto>|null} [enumType] DescriptorProto enumType
+                 * @property {Array.<google.protobuf.DescriptorProto.IExtensionRange>|null} [extensionRange] DescriptorProto extensionRange
+                 * @property {Array.<google.protobuf.IOneofDescriptorProto>|null} [oneofDecl] DescriptorProto oneofDecl
+                 * @property {google.protobuf.IMessageOptions|null} [options] DescriptorProto options
+                 * @property {Array.<google.protobuf.DescriptorProto.IReservedRange>|null} [reservedRange] DescriptorProto reservedRange
+                 * @property {Array.<string>|null} [reservedName] DescriptorProto reservedName
+                 */
+    
+                /**
+                 * Constructs a new DescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a DescriptorProto.
+                 * @implements IDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IDescriptorProto=} [properties] Properties to set
+                 */
+                function DescriptorProto(properties) {
+                    this.field = [];
+                    this.extension = [];
+                    this.nestedType = [];
+                    this.enumType = [];
+                    this.extensionRange = [];
+                    this.oneofDecl = [];
+                    this.reservedRange = [];
+                    this.reservedName = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * DescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.name = "";
+    
+                /**
+                 * DescriptorProto field.
+                 * @member {Array.<google.protobuf.IFieldDescriptorProto>} field
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.field = $util.emptyArray;
+    
+                /**
+                 * DescriptorProto extension.
+                 * @member {Array.<google.protobuf.IFieldDescriptorProto>} extension
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.extension = $util.emptyArray;
+    
+                /**
+                 * DescriptorProto nestedType.
+                 * @member {Array.<google.protobuf.IDescriptorProto>} nestedType
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.nestedType = $util.emptyArray;
+    
+                /**
+                 * DescriptorProto enumType.
+                 * @member {Array.<google.protobuf.IEnumDescriptorProto>} enumType
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.enumType = $util.emptyArray;
+    
+                /**
+                 * DescriptorProto extensionRange.
+                 * @member {Array.<google.protobuf.DescriptorProto.IExtensionRange>} extensionRange
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.extensionRange = $util.emptyArray;
+    
+                /**
+                 * DescriptorProto oneofDecl.
+                 * @member {Array.<google.protobuf.IOneofDescriptorProto>} oneofDecl
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.oneofDecl = $util.emptyArray;
+    
+                /**
+                 * DescriptorProto options.
+                 * @member {google.protobuf.IMessageOptions|null|undefined} options
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.options = null;
+    
+                /**
+                 * DescriptorProto reservedRange.
+                 * @member {Array.<google.protobuf.DescriptorProto.IReservedRange>} reservedRange
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.reservedRange = $util.emptyArray;
+    
+                /**
+                 * DescriptorProto reservedName.
+                 * @member {Array.<string>} reservedName
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 */
+                DescriptorProto.prototype.reservedName = $util.emptyArray;
+    
+                /**
+                 * Creates a new DescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {google.protobuf.IDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.DescriptorProto} DescriptorProto instance
+                 */
+                DescriptorProto.create = function create(properties) {
+                    return new DescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified DescriptorProto message. Does not implicitly {@link google.protobuf.DescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {google.protobuf.IDescriptorProto} message DescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                DescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message.field != null && message.field.length)
+                        for (var i = 0; i < message.field.length; ++i)
+                            $root.google.protobuf.FieldDescriptorProto.encode(message.field[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                    if (message.nestedType != null && message.nestedType.length)
+                        for (var i = 0; i < message.nestedType.length; ++i)
+                            $root.google.protobuf.DescriptorProto.encode(message.nestedType[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                    if (message.enumType != null && message.enumType.length)
+                        for (var i = 0; i < message.enumType.length; ++i)
+                            $root.google.protobuf.EnumDescriptorProto.encode(message.enumType[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                    if (message.extensionRange != null && message.extensionRange.length)
+                        for (var i = 0; i < message.extensionRange.length; ++i)
+                            $root.google.protobuf.DescriptorProto.ExtensionRange.encode(message.extensionRange[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
+                    if (message.extension != null && message.extension.length)
+                        for (var i = 0; i < message.extension.length; ++i)
+                            $root.google.protobuf.FieldDescriptorProto.encode(message.extension[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.MessageOptions.encode(message.options, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
+                    if (message.oneofDecl != null && message.oneofDecl.length)
+                        for (var i = 0; i < message.oneofDecl.length; ++i)
+                            $root.google.protobuf.OneofDescriptorProto.encode(message.oneofDecl[i], writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
+                    if (message.reservedRange != null && message.reservedRange.length)
+                        for (var i = 0; i < message.reservedRange.length; ++i)
+                            $root.google.protobuf.DescriptorProto.ReservedRange.encode(message.reservedRange[i], writer.uint32(/* id 9, wireType 2 =*/74).fork()).ldelim();
+                    if (message.reservedName != null && message.reservedName.length)
+                        for (var i = 0; i < message.reservedName.length; ++i)
+                            writer.uint32(/* id 10, wireType 2 =*/82).string(message.reservedName[i]);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified DescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.DescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {google.protobuf.IDescriptorProto} message DescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                DescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a DescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.DescriptorProto} DescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                DescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.DescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 2:
+                            if (!(message.field && message.field.length))
+                                message.field = [];
+                            message.field.push($root.google.protobuf.FieldDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 6:
+                            if (!(message.extension && message.extension.length))
+                                message.extension = [];
+                            message.extension.push($root.google.protobuf.FieldDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 3:
+                            if (!(message.nestedType && message.nestedType.length))
+                                message.nestedType = [];
+                            message.nestedType.push($root.google.protobuf.DescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 4:
+                            if (!(message.enumType && message.enumType.length))
+                                message.enumType = [];
+                            message.enumType.push($root.google.protobuf.EnumDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 5:
+                            if (!(message.extensionRange && message.extensionRange.length))
+                                message.extensionRange = [];
+                            message.extensionRange.push($root.google.protobuf.DescriptorProto.ExtensionRange.decode(reader, reader.uint32()));
+                            break;
+                        case 8:
+                            if (!(message.oneofDecl && message.oneofDecl.length))
+                                message.oneofDecl = [];
+                            message.oneofDecl.push($root.google.protobuf.OneofDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 7:
+                            message.options = $root.google.protobuf.MessageOptions.decode(reader, reader.uint32());
+                            break;
+                        case 9:
+                            if (!(message.reservedRange && message.reservedRange.length))
+                                message.reservedRange = [];
+                            message.reservedRange.push($root.google.protobuf.DescriptorProto.ReservedRange.decode(reader, reader.uint32()));
+                            break;
+                        case 10:
+                            if (!(message.reservedName && message.reservedName.length))
+                                message.reservedName = [];
+                            message.reservedName.push(reader.string());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a DescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.DescriptorProto} DescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                DescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a DescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                DescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message.field != null && message.hasOwnProperty("field")) {
+                        if (!Array.isArray(message.field))
+                            return "field: array expected";
+                        for (var i = 0; i < message.field.length; ++i) {
+                            var error = $root.google.protobuf.FieldDescriptorProto.verify(message.field[i]);
+                            if (error)
+                                return "field." + error;
+                        }
+                    }
+                    if (message.extension != null && message.hasOwnProperty("extension")) {
+                        if (!Array.isArray(message.extension))
+                            return "extension: array expected";
+                        for (var i = 0; i < message.extension.length; ++i) {
+                            var error = $root.google.protobuf.FieldDescriptorProto.verify(message.extension[i]);
+                            if (error)
+                                return "extension." + error;
+                        }
+                    }
+                    if (message.nestedType != null && message.hasOwnProperty("nestedType")) {
+                        if (!Array.isArray(message.nestedType))
+                            return "nestedType: array expected";
+                        for (var i = 0; i < message.nestedType.length; ++i) {
+                            var error = $root.google.protobuf.DescriptorProto.verify(message.nestedType[i]);
+                            if (error)
+                                return "nestedType." + error;
+                        }
+                    }
+                    if (message.enumType != null && message.hasOwnProperty("enumType")) {
+                        if (!Array.isArray(message.enumType))
+                            return "enumType: array expected";
+                        for (var i = 0; i < message.enumType.length; ++i) {
+                            var error = $root.google.protobuf.EnumDescriptorProto.verify(message.enumType[i]);
+                            if (error)
+                                return "enumType." + error;
+                        }
+                    }
+                    if (message.extensionRange != null && message.hasOwnProperty("extensionRange")) {
+                        if (!Array.isArray(message.extensionRange))
+                            return "extensionRange: array expected";
+                        for (var i = 0; i < message.extensionRange.length; ++i) {
+                            var error = $root.google.protobuf.DescriptorProto.ExtensionRange.verify(message.extensionRange[i]);
+                            if (error)
+                                return "extensionRange." + error;
+                        }
+                    }
+                    if (message.oneofDecl != null && message.hasOwnProperty("oneofDecl")) {
+                        if (!Array.isArray(message.oneofDecl))
+                            return "oneofDecl: array expected";
+                        for (var i = 0; i < message.oneofDecl.length; ++i) {
+                            var error = $root.google.protobuf.OneofDescriptorProto.verify(message.oneofDecl[i]);
+                            if (error)
+                                return "oneofDecl." + error;
+                        }
+                    }
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.MessageOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    if (message.reservedRange != null && message.hasOwnProperty("reservedRange")) {
+                        if (!Array.isArray(message.reservedRange))
+                            return "reservedRange: array expected";
+                        for (var i = 0; i < message.reservedRange.length; ++i) {
+                            var error = $root.google.protobuf.DescriptorProto.ReservedRange.verify(message.reservedRange[i]);
+                            if (error)
+                                return "reservedRange." + error;
+                        }
+                    }
+                    if (message.reservedName != null && message.hasOwnProperty("reservedName")) {
+                        if (!Array.isArray(message.reservedName))
+                            return "reservedName: array expected";
+                        for (var i = 0; i < message.reservedName.length; ++i)
+                            if (!$util.isString(message.reservedName[i]))
+                                return "reservedName: string[] expected";
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a DescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.DescriptorProto} DescriptorProto
+                 */
+                DescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.DescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.DescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object.field) {
+                        if (!Array.isArray(object.field))
+                            throw TypeError(".google.protobuf.DescriptorProto.field: array expected");
+                        message.field = [];
+                        for (var i = 0; i < object.field.length; ++i) {
+                            if (typeof object.field[i] !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.field: object expected");
+                            message.field[i] = $root.google.protobuf.FieldDescriptorProto.fromObject(object.field[i]);
+                        }
+                    }
+                    if (object.extension) {
+                        if (!Array.isArray(object.extension))
+                            throw TypeError(".google.protobuf.DescriptorProto.extension: array expected");
+                        message.extension = [];
+                        for (var i = 0; i < object.extension.length; ++i) {
+                            if (typeof object.extension[i] !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.extension: object expected");
+                            message.extension[i] = $root.google.protobuf.FieldDescriptorProto.fromObject(object.extension[i]);
+                        }
+                    }
+                    if (object.nestedType) {
+                        if (!Array.isArray(object.nestedType))
+                            throw TypeError(".google.protobuf.DescriptorProto.nestedType: array expected");
+                        message.nestedType = [];
+                        for (var i = 0; i < object.nestedType.length; ++i) {
+                            if (typeof object.nestedType[i] !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.nestedType: object expected");
+                            message.nestedType[i] = $root.google.protobuf.DescriptorProto.fromObject(object.nestedType[i]);
+                        }
+                    }
+                    if (object.enumType) {
+                        if (!Array.isArray(object.enumType))
+                            throw TypeError(".google.protobuf.DescriptorProto.enumType: array expected");
+                        message.enumType = [];
+                        for (var i = 0; i < object.enumType.length; ++i) {
+                            if (typeof object.enumType[i] !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.enumType: object expected");
+                            message.enumType[i] = $root.google.protobuf.EnumDescriptorProto.fromObject(object.enumType[i]);
+                        }
+                    }
+                    if (object.extensionRange) {
+                        if (!Array.isArray(object.extensionRange))
+                            throw TypeError(".google.protobuf.DescriptorProto.extensionRange: array expected");
+                        message.extensionRange = [];
+                        for (var i = 0; i < object.extensionRange.length; ++i) {
+                            if (typeof object.extensionRange[i] !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.extensionRange: object expected");
+                            message.extensionRange[i] = $root.google.protobuf.DescriptorProto.ExtensionRange.fromObject(object.extensionRange[i]);
+                        }
+                    }
+                    if (object.oneofDecl) {
+                        if (!Array.isArray(object.oneofDecl))
+                            throw TypeError(".google.protobuf.DescriptorProto.oneofDecl: array expected");
+                        message.oneofDecl = [];
+                        for (var i = 0; i < object.oneofDecl.length; ++i) {
+                            if (typeof object.oneofDecl[i] !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.oneofDecl: object expected");
+                            message.oneofDecl[i] = $root.google.protobuf.OneofDescriptorProto.fromObject(object.oneofDecl[i]);
+                        }
+                    }
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.DescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.MessageOptions.fromObject(object.options);
+                    }
+                    if (object.reservedRange) {
+                        if (!Array.isArray(object.reservedRange))
+                            throw TypeError(".google.protobuf.DescriptorProto.reservedRange: array expected");
+                        message.reservedRange = [];
+                        for (var i = 0; i < object.reservedRange.length; ++i) {
+                            if (typeof object.reservedRange[i] !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.reservedRange: object expected");
+                            message.reservedRange[i] = $root.google.protobuf.DescriptorProto.ReservedRange.fromObject(object.reservedRange[i]);
+                        }
+                    }
+                    if (object.reservedName) {
+                        if (!Array.isArray(object.reservedName))
+                            throw TypeError(".google.protobuf.DescriptorProto.reservedName: array expected");
+                        message.reservedName = [];
+                        for (var i = 0; i < object.reservedName.length; ++i)
+                            message.reservedName[i] = String(object.reservedName[i]);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a DescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.DescriptorProto
+                 * @static
+                 * @param {google.protobuf.DescriptorProto} message DescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                DescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults) {
+                        object.field = [];
+                        object.nestedType = [];
+                        object.enumType = [];
+                        object.extensionRange = [];
+                        object.extension = [];
+                        object.oneofDecl = [];
+                        object.reservedRange = [];
+                        object.reservedName = [];
+                    }
+                    if (options.defaults) {
+                        object.name = "";
+                        object.options = null;
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message.field && message.field.length) {
+                        object.field = [];
+                        for (var j = 0; j < message.field.length; ++j)
+                            object.field[j] = $root.google.protobuf.FieldDescriptorProto.toObject(message.field[j], options);
+                    }
+                    if (message.nestedType && message.nestedType.length) {
+                        object.nestedType = [];
+                        for (var j = 0; j < message.nestedType.length; ++j)
+                            object.nestedType[j] = $root.google.protobuf.DescriptorProto.toObject(message.nestedType[j], options);
+                    }
+                    if (message.enumType && message.enumType.length) {
+                        object.enumType = [];
+                        for (var j = 0; j < message.enumType.length; ++j)
+                            object.enumType[j] = $root.google.protobuf.EnumDescriptorProto.toObject(message.enumType[j], options);
+                    }
+                    if (message.extensionRange && message.extensionRange.length) {
+                        object.extensionRange = [];
+                        for (var j = 0; j < message.extensionRange.length; ++j)
+                            object.extensionRange[j] = $root.google.protobuf.DescriptorProto.ExtensionRange.toObject(message.extensionRange[j], options);
+                    }
+                    if (message.extension && message.extension.length) {
+                        object.extension = [];
+                        for (var j = 0; j < message.extension.length; ++j)
+                            object.extension[j] = $root.google.protobuf.FieldDescriptorProto.toObject(message.extension[j], options);
+                    }
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.MessageOptions.toObject(message.options, options);
+                    if (message.oneofDecl && message.oneofDecl.length) {
+                        object.oneofDecl = [];
+                        for (var j = 0; j < message.oneofDecl.length; ++j)
+                            object.oneofDecl[j] = $root.google.protobuf.OneofDescriptorProto.toObject(message.oneofDecl[j], options);
+                    }
+                    if (message.reservedRange && message.reservedRange.length) {
+                        object.reservedRange = [];
+                        for (var j = 0; j < message.reservedRange.length; ++j)
+                            object.reservedRange[j] = $root.google.protobuf.DescriptorProto.ReservedRange.toObject(message.reservedRange[j], options);
+                    }
+                    if (message.reservedName && message.reservedName.length) {
+                        object.reservedName = [];
+                        for (var j = 0; j < message.reservedName.length; ++j)
+                            object.reservedName[j] = message.reservedName[j];
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this DescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.DescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                DescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                DescriptorProto.ExtensionRange = (function() {
+    
+                    /**
+                     * Properties of an ExtensionRange.
+                     * @memberof google.protobuf.DescriptorProto
+                     * @interface IExtensionRange
+                     * @property {number|null} [start] ExtensionRange start
+                     * @property {number|null} [end] ExtensionRange end
+                     * @property {google.protobuf.IExtensionRangeOptions|null} [options] ExtensionRange options
+                     */
+    
+                    /**
+                     * Constructs a new ExtensionRange.
+                     * @memberof google.protobuf.DescriptorProto
+                     * @classdesc Represents an ExtensionRange.
+                     * @implements IExtensionRange
+                     * @constructor
+                     * @param {google.protobuf.DescriptorProto.IExtensionRange=} [properties] Properties to set
+                     */
+                    function ExtensionRange(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * ExtensionRange start.
+                     * @member {number} start
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @instance
+                     */
+                    ExtensionRange.prototype.start = 0;
+    
+                    /**
+                     * ExtensionRange end.
+                     * @member {number} end
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @instance
+                     */
+                    ExtensionRange.prototype.end = 0;
+    
+                    /**
+                     * ExtensionRange options.
+                     * @member {google.protobuf.IExtensionRangeOptions|null|undefined} options
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @instance
+                     */
+                    ExtensionRange.prototype.options = null;
+    
+                    /**
+                     * Creates a new ExtensionRange instance using the specified properties.
+                     * @function create
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.IExtensionRange=} [properties] Properties to set
+                     * @returns {google.protobuf.DescriptorProto.ExtensionRange} ExtensionRange instance
+                     */
+                    ExtensionRange.create = function create(properties) {
+                        return new ExtensionRange(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified ExtensionRange message. Does not implicitly {@link google.protobuf.DescriptorProto.ExtensionRange.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.IExtensionRange} message ExtensionRange message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    ExtensionRange.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.start != null && Object.hasOwnProperty.call(message, "start"))
+                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.start);
+                        if (message.end != null && Object.hasOwnProperty.call(message, "end"))
+                            writer.uint32(/* id 2, wireType 0 =*/16).int32(message.end);
+                        if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                            $root.google.protobuf.ExtensionRangeOptions.encode(message.options, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified ExtensionRange message, length delimited. Does not implicitly {@link google.protobuf.DescriptorProto.ExtensionRange.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.IExtensionRange} message ExtensionRange message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    ExtensionRange.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes an ExtensionRange message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.protobuf.DescriptorProto.ExtensionRange} ExtensionRange
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    ExtensionRange.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.DescriptorProto.ExtensionRange();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.start = reader.int32();
+                                break;
+                            case 2:
+                                message.end = reader.int32();
+                                break;
+                            case 3:
+                                message.options = $root.google.protobuf.ExtensionRangeOptions.decode(reader, reader.uint32());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes an ExtensionRange message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.protobuf.DescriptorProto.ExtensionRange} ExtensionRange
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    ExtensionRange.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies an ExtensionRange message.
+                     * @function verify
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    ExtensionRange.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.start != null && message.hasOwnProperty("start"))
+                            if (!$util.isInteger(message.start))
+                                return "start: integer expected";
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            if (!$util.isInteger(message.end))
+                                return "end: integer expected";
+                        if (message.options != null && message.hasOwnProperty("options")) {
+                            var error = $root.google.protobuf.ExtensionRangeOptions.verify(message.options);
+                            if (error)
+                                return "options." + error;
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates an ExtensionRange message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.protobuf.DescriptorProto.ExtensionRange} ExtensionRange
+                     */
+                    ExtensionRange.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.protobuf.DescriptorProto.ExtensionRange)
+                            return object;
+                        var message = new $root.google.protobuf.DescriptorProto.ExtensionRange();
+                        if (object.start != null)
+                            message.start = object.start | 0;
+                        if (object.end != null)
+                            message.end = object.end | 0;
+                        if (object.options != null) {
+                            if (typeof object.options !== "object")
+                                throw TypeError(".google.protobuf.DescriptorProto.ExtensionRange.options: object expected");
+                            message.options = $root.google.protobuf.ExtensionRangeOptions.fromObject(object.options);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from an ExtensionRange message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.ExtensionRange} message ExtensionRange
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    ExtensionRange.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.start = 0;
+                            object.end = 0;
+                            object.options = null;
+                        }
+                        if (message.start != null && message.hasOwnProperty("start"))
+                            object.start = message.start;
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            object.end = message.end;
+                        if (message.options != null && message.hasOwnProperty("options"))
+                            object.options = $root.google.protobuf.ExtensionRangeOptions.toObject(message.options, options);
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this ExtensionRange to JSON.
+                     * @function toJSON
+                     * @memberof google.protobuf.DescriptorProto.ExtensionRange
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    ExtensionRange.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return ExtensionRange;
+                })();
+    
+                DescriptorProto.ReservedRange = (function() {
+    
+                    /**
+                     * Properties of a ReservedRange.
+                     * @memberof google.protobuf.DescriptorProto
+                     * @interface IReservedRange
+                     * @property {number|null} [start] ReservedRange start
+                     * @property {number|null} [end] ReservedRange end
+                     */
+    
+                    /**
+                     * Constructs a new ReservedRange.
+                     * @memberof google.protobuf.DescriptorProto
+                     * @classdesc Represents a ReservedRange.
+                     * @implements IReservedRange
+                     * @constructor
+                     * @param {google.protobuf.DescriptorProto.IReservedRange=} [properties] Properties to set
+                     */
+                    function ReservedRange(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * ReservedRange start.
+                     * @member {number} start
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @instance
+                     */
+                    ReservedRange.prototype.start = 0;
+    
+                    /**
+                     * ReservedRange end.
+                     * @member {number} end
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @instance
+                     */
+                    ReservedRange.prototype.end = 0;
+    
+                    /**
+                     * Creates a new ReservedRange instance using the specified properties.
+                     * @function create
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.IReservedRange=} [properties] Properties to set
+                     * @returns {google.protobuf.DescriptorProto.ReservedRange} ReservedRange instance
+                     */
+                    ReservedRange.create = function create(properties) {
+                        return new ReservedRange(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified ReservedRange message. Does not implicitly {@link google.protobuf.DescriptorProto.ReservedRange.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.IReservedRange} message ReservedRange message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    ReservedRange.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.start != null && Object.hasOwnProperty.call(message, "start"))
+                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.start);
+                        if (message.end != null && Object.hasOwnProperty.call(message, "end"))
+                            writer.uint32(/* id 2, wireType 0 =*/16).int32(message.end);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified ReservedRange message, length delimited. Does not implicitly {@link google.protobuf.DescriptorProto.ReservedRange.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.IReservedRange} message ReservedRange message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    ReservedRange.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a ReservedRange message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.protobuf.DescriptorProto.ReservedRange} ReservedRange
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    ReservedRange.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.DescriptorProto.ReservedRange();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.start = reader.int32();
+                                break;
+                            case 2:
+                                message.end = reader.int32();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a ReservedRange message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.protobuf.DescriptorProto.ReservedRange} ReservedRange
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    ReservedRange.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a ReservedRange message.
+                     * @function verify
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    ReservedRange.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.start != null && message.hasOwnProperty("start"))
+                            if (!$util.isInteger(message.start))
+                                return "start: integer expected";
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            if (!$util.isInteger(message.end))
+                                return "end: integer expected";
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a ReservedRange message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.protobuf.DescriptorProto.ReservedRange} ReservedRange
+                     */
+                    ReservedRange.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.protobuf.DescriptorProto.ReservedRange)
+                            return object;
+                        var message = new $root.google.protobuf.DescriptorProto.ReservedRange();
+                        if (object.start != null)
+                            message.start = object.start | 0;
+                        if (object.end != null)
+                            message.end = object.end | 0;
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a ReservedRange message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @static
+                     * @param {google.protobuf.DescriptorProto.ReservedRange} message ReservedRange
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    ReservedRange.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.start = 0;
+                            object.end = 0;
+                        }
+                        if (message.start != null && message.hasOwnProperty("start"))
+                            object.start = message.start;
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            object.end = message.end;
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this ReservedRange to JSON.
+                     * @function toJSON
+                     * @memberof google.protobuf.DescriptorProto.ReservedRange
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    ReservedRange.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return ReservedRange;
+                })();
+    
+                return DescriptorProto;
+            })();
+    
+            protobuf.ExtensionRangeOptions = (function() {
+    
+                /**
+                 * Properties of an ExtensionRangeOptions.
+                 * @memberof google.protobuf
+                 * @interface IExtensionRangeOptions
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] ExtensionRangeOptions uninterpretedOption
+                 */
+    
+                /**
+                 * Constructs a new ExtensionRangeOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an ExtensionRangeOptions.
+                 * @implements IExtensionRangeOptions
+                 * @constructor
+                 * @param {google.protobuf.IExtensionRangeOptions=} [properties] Properties to set
+                 */
+                function ExtensionRangeOptions(properties) {
+                    this.uninterpretedOption = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * ExtensionRangeOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @instance
+                 */
+                ExtensionRangeOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * Creates a new ExtensionRangeOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {google.protobuf.IExtensionRangeOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.ExtensionRangeOptions} ExtensionRangeOptions instance
+                 */
+                ExtensionRangeOptions.create = function create(properties) {
+                    return new ExtensionRangeOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified ExtensionRangeOptions message. Does not implicitly {@link google.protobuf.ExtensionRangeOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {google.protobuf.IExtensionRangeOptions} message ExtensionRangeOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ExtensionRangeOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified ExtensionRangeOptions message, length delimited. Does not implicitly {@link google.protobuf.ExtensionRangeOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {google.protobuf.IExtensionRangeOptions} message ExtensionRangeOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ExtensionRangeOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an ExtensionRangeOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.ExtensionRangeOptions} ExtensionRangeOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ExtensionRangeOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.ExtensionRangeOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an ExtensionRangeOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.ExtensionRangeOptions} ExtensionRangeOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ExtensionRangeOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an ExtensionRangeOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                ExtensionRangeOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates an ExtensionRangeOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.ExtensionRangeOptions} ExtensionRangeOptions
+                 */
+                ExtensionRangeOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.ExtensionRangeOptions)
+                        return object;
+                    var message = new $root.google.protobuf.ExtensionRangeOptions();
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.ExtensionRangeOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.ExtensionRangeOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an ExtensionRangeOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @static
+                 * @param {google.protobuf.ExtensionRangeOptions} message ExtensionRangeOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                ExtensionRangeOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.uninterpretedOption = [];
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this ExtensionRangeOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.ExtensionRangeOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                ExtensionRangeOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return ExtensionRangeOptions;
+            })();
+    
+            protobuf.FieldDescriptorProto = (function() {
+    
+                /**
+                 * Properties of a FieldDescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IFieldDescriptorProto
+                 * @property {string|null} [name] FieldDescriptorProto name
+                 * @property {number|null} [number] FieldDescriptorProto number
+                 * @property {google.protobuf.FieldDescriptorProto.Label|null} [label] FieldDescriptorProto label
+                 * @property {google.protobuf.FieldDescriptorProto.Type|null} [type] FieldDescriptorProto type
+                 * @property {string|null} [typeName] FieldDescriptorProto typeName
+                 * @property {string|null} [extendee] FieldDescriptorProto extendee
+                 * @property {string|null} [defaultValue] FieldDescriptorProto defaultValue
+                 * @property {number|null} [oneofIndex] FieldDescriptorProto oneofIndex
+                 * @property {string|null} [jsonName] FieldDescriptorProto jsonName
+                 * @property {google.protobuf.IFieldOptions|null} [options] FieldDescriptorProto options
+                 * @property {boolean|null} [proto3Optional] FieldDescriptorProto proto3Optional
+                 */
+    
+                /**
+                 * Constructs a new FieldDescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a FieldDescriptorProto.
+                 * @implements IFieldDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IFieldDescriptorProto=} [properties] Properties to set
+                 */
+                function FieldDescriptorProto(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * FieldDescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.name = "";
+    
+                /**
+                 * FieldDescriptorProto number.
+                 * @member {number} number
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.number = 0;
+    
+                /**
+                 * FieldDescriptorProto label.
+                 * @member {google.protobuf.FieldDescriptorProto.Label} label
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.label = 1;
+    
+                /**
+                 * FieldDescriptorProto type.
+                 * @member {google.protobuf.FieldDescriptorProto.Type} type
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.type = 1;
+    
+                /**
+                 * FieldDescriptorProto typeName.
+                 * @member {string} typeName
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.typeName = "";
+    
+                /**
+                 * FieldDescriptorProto extendee.
+                 * @member {string} extendee
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.extendee = "";
+    
+                /**
+                 * FieldDescriptorProto defaultValue.
+                 * @member {string} defaultValue
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.defaultValue = "";
+    
+                /**
+                 * FieldDescriptorProto oneofIndex.
+                 * @member {number} oneofIndex
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.oneofIndex = 0;
+    
+                /**
+                 * FieldDescriptorProto jsonName.
+                 * @member {string} jsonName
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.jsonName = "";
+    
+                /**
+                 * FieldDescriptorProto options.
+                 * @member {google.protobuf.IFieldOptions|null|undefined} options
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.options = null;
+    
+                /**
+                 * FieldDescriptorProto proto3Optional.
+                 * @member {boolean} proto3Optional
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 */
+                FieldDescriptorProto.prototype.proto3Optional = false;
+    
+                /**
+                 * Creates a new FieldDescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IFieldDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.FieldDescriptorProto} FieldDescriptorProto instance
+                 */
+                FieldDescriptorProto.create = function create(properties) {
+                    return new FieldDescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified FieldDescriptorProto message. Does not implicitly {@link google.protobuf.FieldDescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IFieldDescriptorProto} message FieldDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FieldDescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message.extendee != null && Object.hasOwnProperty.call(message, "extendee"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.extendee);
+                    if (message.number != null && Object.hasOwnProperty.call(message, "number"))
+                        writer.uint32(/* id 3, wireType 0 =*/24).int32(message.number);
+                    if (message.label != null && Object.hasOwnProperty.call(message, "label"))
+                        writer.uint32(/* id 4, wireType 0 =*/32).int32(message.label);
+                    if (message.type != null && Object.hasOwnProperty.call(message, "type"))
+                        writer.uint32(/* id 5, wireType 0 =*/40).int32(message.type);
+                    if (message.typeName != null && Object.hasOwnProperty.call(message, "typeName"))
+                        writer.uint32(/* id 6, wireType 2 =*/50).string(message.typeName);
+                    if (message.defaultValue != null && Object.hasOwnProperty.call(message, "defaultValue"))
+                        writer.uint32(/* id 7, wireType 2 =*/58).string(message.defaultValue);
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.FieldOptions.encode(message.options, writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
+                    if (message.oneofIndex != null && Object.hasOwnProperty.call(message, "oneofIndex"))
+                        writer.uint32(/* id 9, wireType 0 =*/72).int32(message.oneofIndex);
+                    if (message.jsonName != null && Object.hasOwnProperty.call(message, "jsonName"))
+                        writer.uint32(/* id 10, wireType 2 =*/82).string(message.jsonName);
+                    if (message.proto3Optional != null && Object.hasOwnProperty.call(message, "proto3Optional"))
+                        writer.uint32(/* id 17, wireType 0 =*/136).bool(message.proto3Optional);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified FieldDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.FieldDescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IFieldDescriptorProto} message FieldDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FieldDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a FieldDescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.FieldDescriptorProto} FieldDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FieldDescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.FieldDescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 3:
+                            message.number = reader.int32();
+                            break;
+                        case 4:
+                            message.label = reader.int32();
+                            break;
+                        case 5:
+                            message.type = reader.int32();
+                            break;
+                        case 6:
+                            message.typeName = reader.string();
+                            break;
+                        case 2:
+                            message.extendee = reader.string();
+                            break;
+                        case 7:
+                            message.defaultValue = reader.string();
+                            break;
+                        case 9:
+                            message.oneofIndex = reader.int32();
+                            break;
+                        case 10:
+                            message.jsonName = reader.string();
+                            break;
+                        case 8:
+                            message.options = $root.google.protobuf.FieldOptions.decode(reader, reader.uint32());
+                            break;
+                        case 17:
+                            message.proto3Optional = reader.bool();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a FieldDescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.FieldDescriptorProto} FieldDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FieldDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a FieldDescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                FieldDescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message.number != null && message.hasOwnProperty("number"))
+                        if (!$util.isInteger(message.number))
+                            return "number: integer expected";
+                    if (message.label != null && message.hasOwnProperty("label"))
+                        switch (message.label) {
+                        default:
+                            return "label: enum value expected";
+                        case 1:
+                        case 2:
+                        case 3:
+                            break;
+                        }
+                    if (message.type != null && message.hasOwnProperty("type"))
+                        switch (message.type) {
+                        default:
+                            return "type: enum value expected";
+                        case 1:
+                        case 2:
+                        case 3:
+                        case 4:
+                        case 5:
+                        case 6:
+                        case 7:
+                        case 8:
+                        case 9:
+                        case 10:
+                        case 11:
+                        case 12:
+                        case 13:
+                        case 14:
+                        case 15:
+                        case 16:
+                        case 17:
+                        case 18:
+                            break;
+                        }
+                    if (message.typeName != null && message.hasOwnProperty("typeName"))
+                        if (!$util.isString(message.typeName))
+                            return "typeName: string expected";
+                    if (message.extendee != null && message.hasOwnProperty("extendee"))
+                        if (!$util.isString(message.extendee))
+                            return "extendee: string expected";
+                    if (message.defaultValue != null && message.hasOwnProperty("defaultValue"))
+                        if (!$util.isString(message.defaultValue))
+                            return "defaultValue: string expected";
+                    if (message.oneofIndex != null && message.hasOwnProperty("oneofIndex"))
+                        if (!$util.isInteger(message.oneofIndex))
+                            return "oneofIndex: integer expected";
+                    if (message.jsonName != null && message.hasOwnProperty("jsonName"))
+                        if (!$util.isString(message.jsonName))
+                            return "jsonName: string expected";
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.FieldOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    if (message.proto3Optional != null && message.hasOwnProperty("proto3Optional"))
+                        if (typeof message.proto3Optional !== "boolean")
+                            return "proto3Optional: boolean expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a FieldDescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.FieldDescriptorProto} FieldDescriptorProto
+                 */
+                FieldDescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.FieldDescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.FieldDescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object.number != null)
+                        message.number = object.number | 0;
+                    switch (object.label) {
+                    case "LABEL_OPTIONAL":
+                    case 1:
+                        message.label = 1;
+                        break;
+                    case "LABEL_REQUIRED":
+                    case 2:
+                        message.label = 2;
+                        break;
+                    case "LABEL_REPEATED":
+                    case 3:
+                        message.label = 3;
+                        break;
+                    }
+                    switch (object.type) {
+                    case "TYPE_DOUBLE":
+                    case 1:
+                        message.type = 1;
+                        break;
+                    case "TYPE_FLOAT":
+                    case 2:
+                        message.type = 2;
+                        break;
+                    case "TYPE_INT64":
+                    case 3:
+                        message.type = 3;
+                        break;
+                    case "TYPE_UINT64":
+                    case 4:
+                        message.type = 4;
+                        break;
+                    case "TYPE_INT32":
+                    case 5:
+                        message.type = 5;
+                        break;
+                    case "TYPE_FIXED64":
+                    case 6:
+                        message.type = 6;
+                        break;
+                    case "TYPE_FIXED32":
+                    case 7:
+                        message.type = 7;
+                        break;
+                    case "TYPE_BOOL":
+                    case 8:
+                        message.type = 8;
+                        break;
+                    case "TYPE_STRING":
+                    case 9:
+                        message.type = 9;
+                        break;
+                    case "TYPE_GROUP":
+                    case 10:
+                        message.type = 10;
+                        break;
+                    case "TYPE_MESSAGE":
+                    case 11:
+                        message.type = 11;
+                        break;
+                    case "TYPE_BYTES":
+                    case 12:
+                        message.type = 12;
+                        break;
+                    case "TYPE_UINT32":
+                    case 13:
+                        message.type = 13;
+                        break;
+                    case "TYPE_ENUM":
+                    case 14:
+                        message.type = 14;
+                        break;
+                    case "TYPE_SFIXED32":
+                    case 15:
+                        message.type = 15;
+                        break;
+                    case "TYPE_SFIXED64":
+                    case 16:
+                        message.type = 16;
+                        break;
+                    case "TYPE_SINT32":
+                    case 17:
+                        message.type = 17;
+                        break;
+                    case "TYPE_SINT64":
+                    case 18:
+                        message.type = 18;
+                        break;
+                    }
+                    if (object.typeName != null)
+                        message.typeName = String(object.typeName);
+                    if (object.extendee != null)
+                        message.extendee = String(object.extendee);
+                    if (object.defaultValue != null)
+                        message.defaultValue = String(object.defaultValue);
+                    if (object.oneofIndex != null)
+                        message.oneofIndex = object.oneofIndex | 0;
+                    if (object.jsonName != null)
+                        message.jsonName = String(object.jsonName);
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.FieldDescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.FieldOptions.fromObject(object.options);
+                    }
+                    if (object.proto3Optional != null)
+                        message.proto3Optional = Boolean(object.proto3Optional);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a FieldDescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @static
+                 * @param {google.protobuf.FieldDescriptorProto} message FieldDescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                FieldDescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.name = "";
+                        object.extendee = "";
+                        object.number = 0;
+                        object.label = options.enums === String ? "LABEL_OPTIONAL" : 1;
+                        object.type = options.enums === String ? "TYPE_DOUBLE" : 1;
+                        object.typeName = "";
+                        object.defaultValue = "";
+                        object.options = null;
+                        object.oneofIndex = 0;
+                        object.jsonName = "";
+                        object.proto3Optional = false;
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message.extendee != null && message.hasOwnProperty("extendee"))
+                        object.extendee = message.extendee;
+                    if (message.number != null && message.hasOwnProperty("number"))
+                        object.number = message.number;
+                    if (message.label != null && message.hasOwnProperty("label"))
+                        object.label = options.enums === String ? $root.google.protobuf.FieldDescriptorProto.Label[message.label] : message.label;
+                    if (message.type != null && message.hasOwnProperty("type"))
+                        object.type = options.enums === String ? $root.google.protobuf.FieldDescriptorProto.Type[message.type] : message.type;
+                    if (message.typeName != null && message.hasOwnProperty("typeName"))
+                        object.typeName = message.typeName;
+                    if (message.defaultValue != null && message.hasOwnProperty("defaultValue"))
+                        object.defaultValue = message.defaultValue;
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.FieldOptions.toObject(message.options, options);
+                    if (message.oneofIndex != null && message.hasOwnProperty("oneofIndex"))
+                        object.oneofIndex = message.oneofIndex;
+                    if (message.jsonName != null && message.hasOwnProperty("jsonName"))
+                        object.jsonName = message.jsonName;
+                    if (message.proto3Optional != null && message.hasOwnProperty("proto3Optional"))
+                        object.proto3Optional = message.proto3Optional;
+                    return object;
+                };
+    
+                /**
+                 * Converts this FieldDescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.FieldDescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                FieldDescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                /**
+                 * Type enum.
+                 * @name google.protobuf.FieldDescriptorProto.Type
+                 * @enum {number}
+                 * @property {number} TYPE_DOUBLE=1 TYPE_DOUBLE value
+                 * @property {number} TYPE_FLOAT=2 TYPE_FLOAT value
+                 * @property {number} TYPE_INT64=3 TYPE_INT64 value
+                 * @property {number} TYPE_UINT64=4 TYPE_UINT64 value
+                 * @property {number} TYPE_INT32=5 TYPE_INT32 value
+                 * @property {number} TYPE_FIXED64=6 TYPE_FIXED64 value
+                 * @property {number} TYPE_FIXED32=7 TYPE_FIXED32 value
+                 * @property {number} TYPE_BOOL=8 TYPE_BOOL value
+                 * @property {number} TYPE_STRING=9 TYPE_STRING value
+                 * @property {number} TYPE_GROUP=10 TYPE_GROUP value
+                 * @property {number} TYPE_MESSAGE=11 TYPE_MESSAGE value
+                 * @property {number} TYPE_BYTES=12 TYPE_BYTES value
+                 * @property {number} TYPE_UINT32=13 TYPE_UINT32 value
+                 * @property {number} TYPE_ENUM=14 TYPE_ENUM value
+                 * @property {number} TYPE_SFIXED32=15 TYPE_SFIXED32 value
+                 * @property {number} TYPE_SFIXED64=16 TYPE_SFIXED64 value
+                 * @property {number} TYPE_SINT32=17 TYPE_SINT32 value
+                 * @property {number} TYPE_SINT64=18 TYPE_SINT64 value
+                 */
+                FieldDescriptorProto.Type = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[1] = "TYPE_DOUBLE"] = 1;
+                    values[valuesById[2] = "TYPE_FLOAT"] = 2;
+                    values[valuesById[3] = "TYPE_INT64"] = 3;
+                    values[valuesById[4] = "TYPE_UINT64"] = 4;
+                    values[valuesById[5] = "TYPE_INT32"] = 5;
+                    values[valuesById[6] = "TYPE_FIXED64"] = 6;
+                    values[valuesById[7] = "TYPE_FIXED32"] = 7;
+                    values[valuesById[8] = "TYPE_BOOL"] = 8;
+                    values[valuesById[9] = "TYPE_STRING"] = 9;
+                    values[valuesById[10] = "TYPE_GROUP"] = 10;
+                    values[valuesById[11] = "TYPE_MESSAGE"] = 11;
+                    values[valuesById[12] = "TYPE_BYTES"] = 12;
+                    values[valuesById[13] = "TYPE_UINT32"] = 13;
+                    values[valuesById[14] = "TYPE_ENUM"] = 14;
+                    values[valuesById[15] = "TYPE_SFIXED32"] = 15;
+                    values[valuesById[16] = "TYPE_SFIXED64"] = 16;
+                    values[valuesById[17] = "TYPE_SINT32"] = 17;
+                    values[valuesById[18] = "TYPE_SINT64"] = 18;
+                    return values;
+                })();
+    
+                /**
+                 * Label enum.
+                 * @name google.protobuf.FieldDescriptorProto.Label
+                 * @enum {number}
+                 * @property {number} LABEL_OPTIONAL=1 LABEL_OPTIONAL value
+                 * @property {number} LABEL_REQUIRED=2 LABEL_REQUIRED value
+                 * @property {number} LABEL_REPEATED=3 LABEL_REPEATED value
+                 */
+                FieldDescriptorProto.Label = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[1] = "LABEL_OPTIONAL"] = 1;
+                    values[valuesById[2] = "LABEL_REQUIRED"] = 2;
+                    values[valuesById[3] = "LABEL_REPEATED"] = 3;
+                    return values;
+                })();
+    
+                return FieldDescriptorProto;
+            })();
+    
+            protobuf.OneofDescriptorProto = (function() {
+    
+                /**
+                 * Properties of an OneofDescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IOneofDescriptorProto
+                 * @property {string|null} [name] OneofDescriptorProto name
+                 * @property {google.protobuf.IOneofOptions|null} [options] OneofDescriptorProto options
+                 */
+    
+                /**
+                 * Constructs a new OneofDescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an OneofDescriptorProto.
+                 * @implements IOneofDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IOneofDescriptorProto=} [properties] Properties to set
+                 */
+                function OneofDescriptorProto(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * OneofDescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @instance
+                 */
+                OneofDescriptorProto.prototype.name = "";
+    
+                /**
+                 * OneofDescriptorProto options.
+                 * @member {google.protobuf.IOneofOptions|null|undefined} options
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @instance
+                 */
+                OneofDescriptorProto.prototype.options = null;
+    
+                /**
+                 * Creates a new OneofDescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IOneofDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.OneofDescriptorProto} OneofDescriptorProto instance
+                 */
+                OneofDescriptorProto.create = function create(properties) {
+                    return new OneofDescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified OneofDescriptorProto message. Does not implicitly {@link google.protobuf.OneofDescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IOneofDescriptorProto} message OneofDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                OneofDescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.OneofOptions.encode(message.options, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified OneofDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.OneofDescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IOneofDescriptorProto} message OneofDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                OneofDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an OneofDescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.OneofDescriptorProto} OneofDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                OneofDescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.OneofDescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 2:
+                            message.options = $root.google.protobuf.OneofOptions.decode(reader, reader.uint32());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an OneofDescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.OneofDescriptorProto} OneofDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                OneofDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an OneofDescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                OneofDescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.OneofOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates an OneofDescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.OneofDescriptorProto} OneofDescriptorProto
+                 */
+                OneofDescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.OneofDescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.OneofDescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.OneofDescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.OneofOptions.fromObject(object.options);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an OneofDescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @static
+                 * @param {google.protobuf.OneofDescriptorProto} message OneofDescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                OneofDescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.name = "";
+                        object.options = null;
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.OneofOptions.toObject(message.options, options);
+                    return object;
+                };
+    
+                /**
+                 * Converts this OneofDescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.OneofDescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                OneofDescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return OneofDescriptorProto;
+            })();
+    
+            protobuf.EnumDescriptorProto = (function() {
+    
+                /**
+                 * Properties of an EnumDescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IEnumDescriptorProto
+                 * @property {string|null} [name] EnumDescriptorProto name
+                 * @property {Array.<google.protobuf.IEnumValueDescriptorProto>|null} [value] EnumDescriptorProto value
+                 * @property {google.protobuf.IEnumOptions|null} [options] EnumDescriptorProto options
+                 * @property {Array.<google.protobuf.EnumDescriptorProto.IEnumReservedRange>|null} [reservedRange] EnumDescriptorProto reservedRange
+                 * @property {Array.<string>|null} [reservedName] EnumDescriptorProto reservedName
+                 */
+    
+                /**
+                 * Constructs a new EnumDescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an EnumDescriptorProto.
+                 * @implements IEnumDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IEnumDescriptorProto=} [properties] Properties to set
+                 */
+                function EnumDescriptorProto(properties) {
+                    this.value = [];
+                    this.reservedRange = [];
+                    this.reservedName = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * EnumDescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @instance
+                 */
+                EnumDescriptorProto.prototype.name = "";
+    
+                /**
+                 * EnumDescriptorProto value.
+                 * @member {Array.<google.protobuf.IEnumValueDescriptorProto>} value
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @instance
+                 */
+                EnumDescriptorProto.prototype.value = $util.emptyArray;
+    
+                /**
+                 * EnumDescriptorProto options.
+                 * @member {google.protobuf.IEnumOptions|null|undefined} options
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @instance
+                 */
+                EnumDescriptorProto.prototype.options = null;
+    
+                /**
+                 * EnumDescriptorProto reservedRange.
+                 * @member {Array.<google.protobuf.EnumDescriptorProto.IEnumReservedRange>} reservedRange
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @instance
+                 */
+                EnumDescriptorProto.prototype.reservedRange = $util.emptyArray;
+    
+                /**
+                 * EnumDescriptorProto reservedName.
+                 * @member {Array.<string>} reservedName
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @instance
+                 */
+                EnumDescriptorProto.prototype.reservedName = $util.emptyArray;
+    
+                /**
+                 * Creates a new EnumDescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IEnumDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.EnumDescriptorProto} EnumDescriptorProto instance
+                 */
+                EnumDescriptorProto.create = function create(properties) {
+                    return new EnumDescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified EnumDescriptorProto message. Does not implicitly {@link google.protobuf.EnumDescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IEnumDescriptorProto} message EnumDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumDescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message.value != null && message.value.length)
+                        for (var i = 0; i < message.value.length; ++i)
+                            $root.google.protobuf.EnumValueDescriptorProto.encode(message.value[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.EnumOptions.encode(message.options, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                    if (message.reservedRange != null && message.reservedRange.length)
+                        for (var i = 0; i < message.reservedRange.length; ++i)
+                            $root.google.protobuf.EnumDescriptorProto.EnumReservedRange.encode(message.reservedRange[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                    if (message.reservedName != null && message.reservedName.length)
+                        for (var i = 0; i < message.reservedName.length; ++i)
+                            writer.uint32(/* id 5, wireType 2 =*/42).string(message.reservedName[i]);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified EnumDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.EnumDescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IEnumDescriptorProto} message EnumDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an EnumDescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.EnumDescriptorProto} EnumDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumDescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.EnumDescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 2:
+                            if (!(message.value && message.value.length))
+                                message.value = [];
+                            message.value.push($root.google.protobuf.EnumValueDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 3:
+                            message.options = $root.google.protobuf.EnumOptions.decode(reader, reader.uint32());
+                            break;
+                        case 4:
+                            if (!(message.reservedRange && message.reservedRange.length))
+                                message.reservedRange = [];
+                            message.reservedRange.push($root.google.protobuf.EnumDescriptorProto.EnumReservedRange.decode(reader, reader.uint32()));
+                            break;
+                        case 5:
+                            if (!(message.reservedName && message.reservedName.length))
+                                message.reservedName = [];
+                            message.reservedName.push(reader.string());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an EnumDescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.EnumDescriptorProto} EnumDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an EnumDescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                EnumDescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message.value != null && message.hasOwnProperty("value")) {
+                        if (!Array.isArray(message.value))
+                            return "value: array expected";
+                        for (var i = 0; i < message.value.length; ++i) {
+                            var error = $root.google.protobuf.EnumValueDescriptorProto.verify(message.value[i]);
+                            if (error)
+                                return "value." + error;
+                        }
+                    }
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.EnumOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    if (message.reservedRange != null && message.hasOwnProperty("reservedRange")) {
+                        if (!Array.isArray(message.reservedRange))
+                            return "reservedRange: array expected";
+                        for (var i = 0; i < message.reservedRange.length; ++i) {
+                            var error = $root.google.protobuf.EnumDescriptorProto.EnumReservedRange.verify(message.reservedRange[i]);
+                            if (error)
+                                return "reservedRange." + error;
+                        }
+                    }
+                    if (message.reservedName != null && message.hasOwnProperty("reservedName")) {
+                        if (!Array.isArray(message.reservedName))
+                            return "reservedName: array expected";
+                        for (var i = 0; i < message.reservedName.length; ++i)
+                            if (!$util.isString(message.reservedName[i]))
+                                return "reservedName: string[] expected";
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates an EnumDescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.EnumDescriptorProto} EnumDescriptorProto
+                 */
+                EnumDescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.EnumDescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.EnumDescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object.value) {
+                        if (!Array.isArray(object.value))
+                            throw TypeError(".google.protobuf.EnumDescriptorProto.value: array expected");
+                        message.value = [];
+                        for (var i = 0; i < object.value.length; ++i) {
+                            if (typeof object.value[i] !== "object")
+                                throw TypeError(".google.protobuf.EnumDescriptorProto.value: object expected");
+                            message.value[i] = $root.google.protobuf.EnumValueDescriptorProto.fromObject(object.value[i]);
+                        }
+                    }
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.EnumDescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.EnumOptions.fromObject(object.options);
+                    }
+                    if (object.reservedRange) {
+                        if (!Array.isArray(object.reservedRange))
+                            throw TypeError(".google.protobuf.EnumDescriptorProto.reservedRange: array expected");
+                        message.reservedRange = [];
+                        for (var i = 0; i < object.reservedRange.length; ++i) {
+                            if (typeof object.reservedRange[i] !== "object")
+                                throw TypeError(".google.protobuf.EnumDescriptorProto.reservedRange: object expected");
+                            message.reservedRange[i] = $root.google.protobuf.EnumDescriptorProto.EnumReservedRange.fromObject(object.reservedRange[i]);
+                        }
+                    }
+                    if (object.reservedName) {
+                        if (!Array.isArray(object.reservedName))
+                            throw TypeError(".google.protobuf.EnumDescriptorProto.reservedName: array expected");
+                        message.reservedName = [];
+                        for (var i = 0; i < object.reservedName.length; ++i)
+                            message.reservedName[i] = String(object.reservedName[i]);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an EnumDescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @static
+                 * @param {google.protobuf.EnumDescriptorProto} message EnumDescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                EnumDescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults) {
+                        object.value = [];
+                        object.reservedRange = [];
+                        object.reservedName = [];
+                    }
+                    if (options.defaults) {
+                        object.name = "";
+                        object.options = null;
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message.value && message.value.length) {
+                        object.value = [];
+                        for (var j = 0; j < message.value.length; ++j)
+                            object.value[j] = $root.google.protobuf.EnumValueDescriptorProto.toObject(message.value[j], options);
+                    }
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.EnumOptions.toObject(message.options, options);
+                    if (message.reservedRange && message.reservedRange.length) {
+                        object.reservedRange = [];
+                        for (var j = 0; j < message.reservedRange.length; ++j)
+                            object.reservedRange[j] = $root.google.protobuf.EnumDescriptorProto.EnumReservedRange.toObject(message.reservedRange[j], options);
+                    }
+                    if (message.reservedName && message.reservedName.length) {
+                        object.reservedName = [];
+                        for (var j = 0; j < message.reservedName.length; ++j)
+                            object.reservedName[j] = message.reservedName[j];
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this EnumDescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.EnumDescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                EnumDescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                EnumDescriptorProto.EnumReservedRange = (function() {
+    
+                    /**
+                     * Properties of an EnumReservedRange.
+                     * @memberof google.protobuf.EnumDescriptorProto
+                     * @interface IEnumReservedRange
+                     * @property {number|null} [start] EnumReservedRange start
+                     * @property {number|null} [end] EnumReservedRange end
+                     */
+    
+                    /**
+                     * Constructs a new EnumReservedRange.
+                     * @memberof google.protobuf.EnumDescriptorProto
+                     * @classdesc Represents an EnumReservedRange.
+                     * @implements IEnumReservedRange
+                     * @constructor
+                     * @param {google.protobuf.EnumDescriptorProto.IEnumReservedRange=} [properties] Properties to set
+                     */
+                    function EnumReservedRange(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * EnumReservedRange start.
+                     * @member {number} start
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @instance
+                     */
+                    EnumReservedRange.prototype.start = 0;
+    
+                    /**
+                     * EnumReservedRange end.
+                     * @member {number} end
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @instance
+                     */
+                    EnumReservedRange.prototype.end = 0;
+    
+                    /**
+                     * Creates a new EnumReservedRange instance using the specified properties.
+                     * @function create
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {google.protobuf.EnumDescriptorProto.IEnumReservedRange=} [properties] Properties to set
+                     * @returns {google.protobuf.EnumDescriptorProto.EnumReservedRange} EnumReservedRange instance
+                     */
+                    EnumReservedRange.create = function create(properties) {
+                        return new EnumReservedRange(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified EnumReservedRange message. Does not implicitly {@link google.protobuf.EnumDescriptorProto.EnumReservedRange.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {google.protobuf.EnumDescriptorProto.IEnumReservedRange} message EnumReservedRange message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    EnumReservedRange.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.start != null && Object.hasOwnProperty.call(message, "start"))
+                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.start);
+                        if (message.end != null && Object.hasOwnProperty.call(message, "end"))
+                            writer.uint32(/* id 2, wireType 0 =*/16).int32(message.end);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified EnumReservedRange message, length delimited. Does not implicitly {@link google.protobuf.EnumDescriptorProto.EnumReservedRange.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {google.protobuf.EnumDescriptorProto.IEnumReservedRange} message EnumReservedRange message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    EnumReservedRange.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes an EnumReservedRange message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.protobuf.EnumDescriptorProto.EnumReservedRange} EnumReservedRange
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    EnumReservedRange.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.EnumDescriptorProto.EnumReservedRange();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.start = reader.int32();
+                                break;
+                            case 2:
+                                message.end = reader.int32();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes an EnumReservedRange message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.protobuf.EnumDescriptorProto.EnumReservedRange} EnumReservedRange
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    EnumReservedRange.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies an EnumReservedRange message.
+                     * @function verify
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    EnumReservedRange.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.start != null && message.hasOwnProperty("start"))
+                            if (!$util.isInteger(message.start))
+                                return "start: integer expected";
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            if (!$util.isInteger(message.end))
+                                return "end: integer expected";
+                        return null;
+                    };
+    
+                    /**
+                     * Creates an EnumReservedRange message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.protobuf.EnumDescriptorProto.EnumReservedRange} EnumReservedRange
+                     */
+                    EnumReservedRange.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.protobuf.EnumDescriptorProto.EnumReservedRange)
+                            return object;
+                        var message = new $root.google.protobuf.EnumDescriptorProto.EnumReservedRange();
+                        if (object.start != null)
+                            message.start = object.start | 0;
+                        if (object.end != null)
+                            message.end = object.end | 0;
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from an EnumReservedRange message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @static
+                     * @param {google.protobuf.EnumDescriptorProto.EnumReservedRange} message EnumReservedRange
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    EnumReservedRange.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.start = 0;
+                            object.end = 0;
+                        }
+                        if (message.start != null && message.hasOwnProperty("start"))
+                            object.start = message.start;
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            object.end = message.end;
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this EnumReservedRange to JSON.
+                     * @function toJSON
+                     * @memberof google.protobuf.EnumDescriptorProto.EnumReservedRange
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    EnumReservedRange.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return EnumReservedRange;
+                })();
+    
+                return EnumDescriptorProto;
+            })();
+    
+            protobuf.EnumValueDescriptorProto = (function() {
+    
+                /**
+                 * Properties of an EnumValueDescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IEnumValueDescriptorProto
+                 * @property {string|null} [name] EnumValueDescriptorProto name
+                 * @property {number|null} [number] EnumValueDescriptorProto number
+                 * @property {google.protobuf.IEnumValueOptions|null} [options] EnumValueDescriptorProto options
+                 */
+    
+                /**
+                 * Constructs a new EnumValueDescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an EnumValueDescriptorProto.
+                 * @implements IEnumValueDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IEnumValueDescriptorProto=} [properties] Properties to set
+                 */
+                function EnumValueDescriptorProto(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * EnumValueDescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @instance
+                 */
+                EnumValueDescriptorProto.prototype.name = "";
+    
+                /**
+                 * EnumValueDescriptorProto number.
+                 * @member {number} number
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @instance
+                 */
+                EnumValueDescriptorProto.prototype.number = 0;
+    
+                /**
+                 * EnumValueDescriptorProto options.
+                 * @member {google.protobuf.IEnumValueOptions|null|undefined} options
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @instance
+                 */
+                EnumValueDescriptorProto.prototype.options = null;
+    
+                /**
+                 * Creates a new EnumValueDescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IEnumValueDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.EnumValueDescriptorProto} EnumValueDescriptorProto instance
+                 */
+                EnumValueDescriptorProto.create = function create(properties) {
+                    return new EnumValueDescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified EnumValueDescriptorProto message. Does not implicitly {@link google.protobuf.EnumValueDescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IEnumValueDescriptorProto} message EnumValueDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumValueDescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message.number != null && Object.hasOwnProperty.call(message, "number"))
+                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.number);
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.EnumValueOptions.encode(message.options, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified EnumValueDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.EnumValueDescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IEnumValueDescriptorProto} message EnumValueDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumValueDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an EnumValueDescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.EnumValueDescriptorProto} EnumValueDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumValueDescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.EnumValueDescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 2:
+                            message.number = reader.int32();
+                            break;
+                        case 3:
+                            message.options = $root.google.protobuf.EnumValueOptions.decode(reader, reader.uint32());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an EnumValueDescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.EnumValueDescriptorProto} EnumValueDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumValueDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an EnumValueDescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                EnumValueDescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message.number != null && message.hasOwnProperty("number"))
+                        if (!$util.isInteger(message.number))
+                            return "number: integer expected";
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.EnumValueOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates an EnumValueDescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.EnumValueDescriptorProto} EnumValueDescriptorProto
+                 */
+                EnumValueDescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.EnumValueDescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.EnumValueDescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object.number != null)
+                        message.number = object.number | 0;
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.EnumValueDescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.EnumValueOptions.fromObject(object.options);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an EnumValueDescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @static
+                 * @param {google.protobuf.EnumValueDescriptorProto} message EnumValueDescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                EnumValueDescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.name = "";
+                        object.number = 0;
+                        object.options = null;
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message.number != null && message.hasOwnProperty("number"))
+                        object.number = message.number;
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.EnumValueOptions.toObject(message.options, options);
+                    return object;
+                };
+    
+                /**
+                 * Converts this EnumValueDescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.EnumValueDescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                EnumValueDescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return EnumValueDescriptorProto;
+            })();
+    
+            protobuf.ServiceDescriptorProto = (function() {
+    
+                /**
+                 * Properties of a ServiceDescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IServiceDescriptorProto
+                 * @property {string|null} [name] ServiceDescriptorProto name
+                 * @property {Array.<google.protobuf.IMethodDescriptorProto>|null} [method] ServiceDescriptorProto method
+                 * @property {google.protobuf.IServiceOptions|null} [options] ServiceDescriptorProto options
+                 */
+    
+                /**
+                 * Constructs a new ServiceDescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a ServiceDescriptorProto.
+                 * @implements IServiceDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IServiceDescriptorProto=} [properties] Properties to set
+                 */
+                function ServiceDescriptorProto(properties) {
+                    this.method = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * ServiceDescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @instance
+                 */
+                ServiceDescriptorProto.prototype.name = "";
+    
+                /**
+                 * ServiceDescriptorProto method.
+                 * @member {Array.<google.protobuf.IMethodDescriptorProto>} method
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @instance
+                 */
+                ServiceDescriptorProto.prototype.method = $util.emptyArray;
+    
+                /**
+                 * ServiceDescriptorProto options.
+                 * @member {google.protobuf.IServiceOptions|null|undefined} options
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @instance
+                 */
+                ServiceDescriptorProto.prototype.options = null;
+    
+                /**
+                 * Creates a new ServiceDescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IServiceDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.ServiceDescriptorProto} ServiceDescriptorProto instance
+                 */
+                ServiceDescriptorProto.create = function create(properties) {
+                    return new ServiceDescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified ServiceDescriptorProto message. Does not implicitly {@link google.protobuf.ServiceDescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IServiceDescriptorProto} message ServiceDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ServiceDescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message.method != null && message.method.length)
+                        for (var i = 0; i < message.method.length; ++i)
+                            $root.google.protobuf.MethodDescriptorProto.encode(message.method[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.ServiceOptions.encode(message.options, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified ServiceDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.ServiceDescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IServiceDescriptorProto} message ServiceDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ServiceDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a ServiceDescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.ServiceDescriptorProto} ServiceDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ServiceDescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.ServiceDescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 2:
+                            if (!(message.method && message.method.length))
+                                message.method = [];
+                            message.method.push($root.google.protobuf.MethodDescriptorProto.decode(reader, reader.uint32()));
+                            break;
+                        case 3:
+                            message.options = $root.google.protobuf.ServiceOptions.decode(reader, reader.uint32());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a ServiceDescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.ServiceDescriptorProto} ServiceDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ServiceDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a ServiceDescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                ServiceDescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message.method != null && message.hasOwnProperty("method")) {
+                        if (!Array.isArray(message.method))
+                            return "method: array expected";
+                        for (var i = 0; i < message.method.length; ++i) {
+                            var error = $root.google.protobuf.MethodDescriptorProto.verify(message.method[i]);
+                            if (error)
+                                return "method." + error;
+                        }
+                    }
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.ServiceOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a ServiceDescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.ServiceDescriptorProto} ServiceDescriptorProto
+                 */
+                ServiceDescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.ServiceDescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.ServiceDescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object.method) {
+                        if (!Array.isArray(object.method))
+                            throw TypeError(".google.protobuf.ServiceDescriptorProto.method: array expected");
+                        message.method = [];
+                        for (var i = 0; i < object.method.length; ++i) {
+                            if (typeof object.method[i] !== "object")
+                                throw TypeError(".google.protobuf.ServiceDescriptorProto.method: object expected");
+                            message.method[i] = $root.google.protobuf.MethodDescriptorProto.fromObject(object.method[i]);
+                        }
+                    }
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.ServiceDescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.ServiceOptions.fromObject(object.options);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a ServiceDescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @static
+                 * @param {google.protobuf.ServiceDescriptorProto} message ServiceDescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                ServiceDescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.method = [];
+                    if (options.defaults) {
+                        object.name = "";
+                        object.options = null;
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message.method && message.method.length) {
+                        object.method = [];
+                        for (var j = 0; j < message.method.length; ++j)
+                            object.method[j] = $root.google.protobuf.MethodDescriptorProto.toObject(message.method[j], options);
+                    }
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.ServiceOptions.toObject(message.options, options);
+                    return object;
+                };
+    
+                /**
+                 * Converts this ServiceDescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.ServiceDescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                ServiceDescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return ServiceDescriptorProto;
+            })();
+    
+            protobuf.MethodDescriptorProto = (function() {
+    
+                /**
+                 * Properties of a MethodDescriptorProto.
+                 * @memberof google.protobuf
+                 * @interface IMethodDescriptorProto
+                 * @property {string|null} [name] MethodDescriptorProto name
+                 * @property {string|null} [inputType] MethodDescriptorProto inputType
+                 * @property {string|null} [outputType] MethodDescriptorProto outputType
+                 * @property {google.protobuf.IMethodOptions|null} [options] MethodDescriptorProto options
+                 * @property {boolean|null} [clientStreaming] MethodDescriptorProto clientStreaming
+                 * @property {boolean|null} [serverStreaming] MethodDescriptorProto serverStreaming
+                 */
+    
+                /**
+                 * Constructs a new MethodDescriptorProto.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a MethodDescriptorProto.
+                 * @implements IMethodDescriptorProto
+                 * @constructor
+                 * @param {google.protobuf.IMethodDescriptorProto=} [properties] Properties to set
+                 */
+                function MethodDescriptorProto(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * MethodDescriptorProto name.
+                 * @member {string} name
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @instance
+                 */
+                MethodDescriptorProto.prototype.name = "";
+    
+                /**
+                 * MethodDescriptorProto inputType.
+                 * @member {string} inputType
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @instance
+                 */
+                MethodDescriptorProto.prototype.inputType = "";
+    
+                /**
+                 * MethodDescriptorProto outputType.
+                 * @member {string} outputType
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @instance
+                 */
+                MethodDescriptorProto.prototype.outputType = "";
+    
+                /**
+                 * MethodDescriptorProto options.
+                 * @member {google.protobuf.IMethodOptions|null|undefined} options
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @instance
+                 */
+                MethodDescriptorProto.prototype.options = null;
+    
+                /**
+                 * MethodDescriptorProto clientStreaming.
+                 * @member {boolean} clientStreaming
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @instance
+                 */
+                MethodDescriptorProto.prototype.clientStreaming = false;
+    
+                /**
+                 * MethodDescriptorProto serverStreaming.
+                 * @member {boolean} serverStreaming
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @instance
+                 */
+                MethodDescriptorProto.prototype.serverStreaming = false;
+    
+                /**
+                 * Creates a new MethodDescriptorProto instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IMethodDescriptorProto=} [properties] Properties to set
+                 * @returns {google.protobuf.MethodDescriptorProto} MethodDescriptorProto instance
+                 */
+                MethodDescriptorProto.create = function create(properties) {
+                    return new MethodDescriptorProto(properties);
+                };
+    
+                /**
+                 * Encodes the specified MethodDescriptorProto message. Does not implicitly {@link google.protobuf.MethodDescriptorProto.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IMethodDescriptorProto} message MethodDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                MethodDescriptorProto.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
+                    if (message.inputType != null && Object.hasOwnProperty.call(message, "inputType"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.inputType);
+                    if (message.outputType != null && Object.hasOwnProperty.call(message, "outputType"))
+                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.outputType);
+                    if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                        $root.google.protobuf.MethodOptions.encode(message.options, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                    if (message.clientStreaming != null && Object.hasOwnProperty.call(message, "clientStreaming"))
+                        writer.uint32(/* id 5, wireType 0 =*/40).bool(message.clientStreaming);
+                    if (message.serverStreaming != null && Object.hasOwnProperty.call(message, "serverStreaming"))
+                        writer.uint32(/* id 6, wireType 0 =*/48).bool(message.serverStreaming);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified MethodDescriptorProto message, length delimited. Does not implicitly {@link google.protobuf.MethodDescriptorProto.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {google.protobuf.IMethodDescriptorProto} message MethodDescriptorProto message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                MethodDescriptorProto.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a MethodDescriptorProto message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.MethodDescriptorProto} MethodDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                MethodDescriptorProto.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.MethodDescriptorProto();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.name = reader.string();
+                            break;
+                        case 2:
+                            message.inputType = reader.string();
+                            break;
+                        case 3:
+                            message.outputType = reader.string();
+                            break;
+                        case 4:
+                            message.options = $root.google.protobuf.MethodOptions.decode(reader, reader.uint32());
+                            break;
+                        case 5:
+                            message.clientStreaming = reader.bool();
+                            break;
+                        case 6:
+                            message.serverStreaming = reader.bool();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a MethodDescriptorProto message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.MethodDescriptorProto} MethodDescriptorProto
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                MethodDescriptorProto.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a MethodDescriptorProto message.
+                 * @function verify
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                MethodDescriptorProto.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        if (!$util.isString(message.name))
+                            return "name: string expected";
+                    if (message.inputType != null && message.hasOwnProperty("inputType"))
+                        if (!$util.isString(message.inputType))
+                            return "inputType: string expected";
+                    if (message.outputType != null && message.hasOwnProperty("outputType"))
+                        if (!$util.isString(message.outputType))
+                            return "outputType: string expected";
+                    if (message.options != null && message.hasOwnProperty("options")) {
+                        var error = $root.google.protobuf.MethodOptions.verify(message.options);
+                        if (error)
+                            return "options." + error;
+                    }
+                    if (message.clientStreaming != null && message.hasOwnProperty("clientStreaming"))
+                        if (typeof message.clientStreaming !== "boolean")
+                            return "clientStreaming: boolean expected";
+                    if (message.serverStreaming != null && message.hasOwnProperty("serverStreaming"))
+                        if (typeof message.serverStreaming !== "boolean")
+                            return "serverStreaming: boolean expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a MethodDescriptorProto message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.MethodDescriptorProto} MethodDescriptorProto
+                 */
+                MethodDescriptorProto.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.MethodDescriptorProto)
+                        return object;
+                    var message = new $root.google.protobuf.MethodDescriptorProto();
+                    if (object.name != null)
+                        message.name = String(object.name);
+                    if (object.inputType != null)
+                        message.inputType = String(object.inputType);
+                    if (object.outputType != null)
+                        message.outputType = String(object.outputType);
+                    if (object.options != null) {
+                        if (typeof object.options !== "object")
+                            throw TypeError(".google.protobuf.MethodDescriptorProto.options: object expected");
+                        message.options = $root.google.protobuf.MethodOptions.fromObject(object.options);
+                    }
+                    if (object.clientStreaming != null)
+                        message.clientStreaming = Boolean(object.clientStreaming);
+                    if (object.serverStreaming != null)
+                        message.serverStreaming = Boolean(object.serverStreaming);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a MethodDescriptorProto message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @static
+                 * @param {google.protobuf.MethodDescriptorProto} message MethodDescriptorProto
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                MethodDescriptorProto.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.name = "";
+                        object.inputType = "";
+                        object.outputType = "";
+                        object.options = null;
+                        object.clientStreaming = false;
+                        object.serverStreaming = false;
+                    }
+                    if (message.name != null && message.hasOwnProperty("name"))
+                        object.name = message.name;
+                    if (message.inputType != null && message.hasOwnProperty("inputType"))
+                        object.inputType = message.inputType;
+                    if (message.outputType != null && message.hasOwnProperty("outputType"))
+                        object.outputType = message.outputType;
+                    if (message.options != null && message.hasOwnProperty("options"))
+                        object.options = $root.google.protobuf.MethodOptions.toObject(message.options, options);
+                    if (message.clientStreaming != null && message.hasOwnProperty("clientStreaming"))
+                        object.clientStreaming = message.clientStreaming;
+                    if (message.serverStreaming != null && message.hasOwnProperty("serverStreaming"))
+                        object.serverStreaming = message.serverStreaming;
+                    return object;
+                };
+    
+                /**
+                 * Converts this MethodDescriptorProto to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.MethodDescriptorProto
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                MethodDescriptorProto.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return MethodDescriptorProto;
+            })();
+    
+            protobuf.FileOptions = (function() {
+    
+                /**
+                 * Properties of a FileOptions.
+                 * @memberof google.protobuf
+                 * @interface IFileOptions
+                 * @property {string|null} [javaPackage] FileOptions javaPackage
+                 * @property {string|null} [javaOuterClassname] FileOptions javaOuterClassname
+                 * @property {boolean|null} [javaMultipleFiles] FileOptions javaMultipleFiles
+                 * @property {boolean|null} [javaGenerateEqualsAndHash] FileOptions javaGenerateEqualsAndHash
+                 * @property {boolean|null} [javaStringCheckUtf8] FileOptions javaStringCheckUtf8
+                 * @property {google.protobuf.FileOptions.OptimizeMode|null} [optimizeFor] FileOptions optimizeFor
+                 * @property {string|null} [goPackage] FileOptions goPackage
+                 * @property {boolean|null} [ccGenericServices] FileOptions ccGenericServices
+                 * @property {boolean|null} [javaGenericServices] FileOptions javaGenericServices
+                 * @property {boolean|null} [pyGenericServices] FileOptions pyGenericServices
+                 * @property {boolean|null} [phpGenericServices] FileOptions phpGenericServices
+                 * @property {boolean|null} [deprecated] FileOptions deprecated
+                 * @property {boolean|null} [ccEnableArenas] FileOptions ccEnableArenas
+                 * @property {string|null} [objcClassPrefix] FileOptions objcClassPrefix
+                 * @property {string|null} [csharpNamespace] FileOptions csharpNamespace
+                 * @property {string|null} [swiftPrefix] FileOptions swiftPrefix
+                 * @property {string|null} [phpClassPrefix] FileOptions phpClassPrefix
+                 * @property {string|null} [phpNamespace] FileOptions phpNamespace
+                 * @property {string|null} [phpMetadataNamespace] FileOptions phpMetadataNamespace
+                 * @property {string|null} [rubyPackage] FileOptions rubyPackage
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] FileOptions uninterpretedOption
+                 * @property {Array.<google.api.IResourceDescriptor>|null} [".google.api.resourceDefinition"] FileOptions .google.api.resourceDefinition
+                 */
+    
+                /**
+                 * Constructs a new FileOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a FileOptions.
+                 * @implements IFileOptions
+                 * @constructor
+                 * @param {google.protobuf.IFileOptions=} [properties] Properties to set
+                 */
+                function FileOptions(properties) {
+                    this.uninterpretedOption = [];
+                    this[".google.api.resourceDefinition"] = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * FileOptions javaPackage.
+                 * @member {string} javaPackage
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.javaPackage = "";
+    
+                /**
+                 * FileOptions javaOuterClassname.
+                 * @member {string} javaOuterClassname
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.javaOuterClassname = "";
+    
+                /**
+                 * FileOptions javaMultipleFiles.
+                 * @member {boolean} javaMultipleFiles
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.javaMultipleFiles = false;
+    
+                /**
+                 * FileOptions javaGenerateEqualsAndHash.
+                 * @member {boolean} javaGenerateEqualsAndHash
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.javaGenerateEqualsAndHash = false;
+    
+                /**
+                 * FileOptions javaStringCheckUtf8.
+                 * @member {boolean} javaStringCheckUtf8
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.javaStringCheckUtf8 = false;
+    
+                /**
+                 * FileOptions optimizeFor.
+                 * @member {google.protobuf.FileOptions.OptimizeMode} optimizeFor
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.optimizeFor = 1;
+    
+                /**
+                 * FileOptions goPackage.
+                 * @member {string} goPackage
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.goPackage = "";
+    
+                /**
+                 * FileOptions ccGenericServices.
+                 * @member {boolean} ccGenericServices
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.ccGenericServices = false;
+    
+                /**
+                 * FileOptions javaGenericServices.
+                 * @member {boolean} javaGenericServices
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.javaGenericServices = false;
+    
+                /**
+                 * FileOptions pyGenericServices.
+                 * @member {boolean} pyGenericServices
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.pyGenericServices = false;
+    
+                /**
+                 * FileOptions phpGenericServices.
+                 * @member {boolean} phpGenericServices
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.phpGenericServices = false;
+    
+                /**
+                 * FileOptions deprecated.
+                 * @member {boolean} deprecated
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.deprecated = false;
+    
+                /**
+                 * FileOptions ccEnableArenas.
+                 * @member {boolean} ccEnableArenas
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.ccEnableArenas = true;
+    
+                /**
+                 * FileOptions objcClassPrefix.
+                 * @member {string} objcClassPrefix
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.objcClassPrefix = "";
+    
+                /**
+                 * FileOptions csharpNamespace.
+                 * @member {string} csharpNamespace
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.csharpNamespace = "";
+    
+                /**
+                 * FileOptions swiftPrefix.
+                 * @member {string} swiftPrefix
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.swiftPrefix = "";
+    
+                /**
+                 * FileOptions phpClassPrefix.
+                 * @member {string} phpClassPrefix
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.phpClassPrefix = "";
+    
+                /**
+                 * FileOptions phpNamespace.
+                 * @member {string} phpNamespace
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.phpNamespace = "";
+    
+                /**
+                 * FileOptions phpMetadataNamespace.
+                 * @member {string} phpMetadataNamespace
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.phpMetadataNamespace = "";
+    
+                /**
+                 * FileOptions rubyPackage.
+                 * @member {string} rubyPackage
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.rubyPackage = "";
+    
+                /**
+                 * FileOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * FileOptions .google.api.resourceDefinition.
+                 * @member {Array.<google.api.IResourceDescriptor>} .google.api.resourceDefinition
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 */
+                FileOptions.prototype[".google.api.resourceDefinition"] = $util.emptyArray;
+    
+                /**
+                 * Creates a new FileOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {google.protobuf.IFileOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.FileOptions} FileOptions instance
+                 */
+                FileOptions.create = function create(properties) {
+                    return new FileOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified FileOptions message. Does not implicitly {@link google.protobuf.FileOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {google.protobuf.IFileOptions} message FileOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FileOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.javaPackage != null && Object.hasOwnProperty.call(message, "javaPackage"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.javaPackage);
+                    if (message.javaOuterClassname != null && Object.hasOwnProperty.call(message, "javaOuterClassname"))
+                        writer.uint32(/* id 8, wireType 2 =*/66).string(message.javaOuterClassname);
+                    if (message.optimizeFor != null && Object.hasOwnProperty.call(message, "optimizeFor"))
+                        writer.uint32(/* id 9, wireType 0 =*/72).int32(message.optimizeFor);
+                    if (message.javaMultipleFiles != null && Object.hasOwnProperty.call(message, "javaMultipleFiles"))
+                        writer.uint32(/* id 10, wireType 0 =*/80).bool(message.javaMultipleFiles);
+                    if (message.goPackage != null && Object.hasOwnProperty.call(message, "goPackage"))
+                        writer.uint32(/* id 11, wireType 2 =*/90).string(message.goPackage);
+                    if (message.ccGenericServices != null && Object.hasOwnProperty.call(message, "ccGenericServices"))
+                        writer.uint32(/* id 16, wireType 0 =*/128).bool(message.ccGenericServices);
+                    if (message.javaGenericServices != null && Object.hasOwnProperty.call(message, "javaGenericServices"))
+                        writer.uint32(/* id 17, wireType 0 =*/136).bool(message.javaGenericServices);
+                    if (message.pyGenericServices != null && Object.hasOwnProperty.call(message, "pyGenericServices"))
+                        writer.uint32(/* id 18, wireType 0 =*/144).bool(message.pyGenericServices);
+                    if (message.javaGenerateEqualsAndHash != null && Object.hasOwnProperty.call(message, "javaGenerateEqualsAndHash"))
+                        writer.uint32(/* id 20, wireType 0 =*/160).bool(message.javaGenerateEqualsAndHash);
+                    if (message.deprecated != null && Object.hasOwnProperty.call(message, "deprecated"))
+                        writer.uint32(/* id 23, wireType 0 =*/184).bool(message.deprecated);
+                    if (message.javaStringCheckUtf8 != null && Object.hasOwnProperty.call(message, "javaStringCheckUtf8"))
+                        writer.uint32(/* id 27, wireType 0 =*/216).bool(message.javaStringCheckUtf8);
+                    if (message.ccEnableArenas != null && Object.hasOwnProperty.call(message, "ccEnableArenas"))
+                        writer.uint32(/* id 31, wireType 0 =*/248).bool(message.ccEnableArenas);
+                    if (message.objcClassPrefix != null && Object.hasOwnProperty.call(message, "objcClassPrefix"))
+                        writer.uint32(/* id 36, wireType 2 =*/290).string(message.objcClassPrefix);
+                    if (message.csharpNamespace != null && Object.hasOwnProperty.call(message, "csharpNamespace"))
+                        writer.uint32(/* id 37, wireType 2 =*/298).string(message.csharpNamespace);
+                    if (message.swiftPrefix != null && Object.hasOwnProperty.call(message, "swiftPrefix"))
+                        writer.uint32(/* id 39, wireType 2 =*/314).string(message.swiftPrefix);
+                    if (message.phpClassPrefix != null && Object.hasOwnProperty.call(message, "phpClassPrefix"))
+                        writer.uint32(/* id 40, wireType 2 =*/322).string(message.phpClassPrefix);
+                    if (message.phpNamespace != null && Object.hasOwnProperty.call(message, "phpNamespace"))
+                        writer.uint32(/* id 41, wireType 2 =*/330).string(message.phpNamespace);
+                    if (message.phpGenericServices != null && Object.hasOwnProperty.call(message, "phpGenericServices"))
+                        writer.uint32(/* id 42, wireType 0 =*/336).bool(message.phpGenericServices);
+                    if (message.phpMetadataNamespace != null && Object.hasOwnProperty.call(message, "phpMetadataNamespace"))
+                        writer.uint32(/* id 44, wireType 2 =*/354).string(message.phpMetadataNamespace);
+                    if (message.rubyPackage != null && Object.hasOwnProperty.call(message, "rubyPackage"))
+                        writer.uint32(/* id 45, wireType 2 =*/362).string(message.rubyPackage);
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    if (message[".google.api.resourceDefinition"] != null && message[".google.api.resourceDefinition"].length)
+                        for (var i = 0; i < message[".google.api.resourceDefinition"].length; ++i)
+                            $root.google.api.ResourceDescriptor.encode(message[".google.api.resourceDefinition"][i], writer.uint32(/* id 1053, wireType 2 =*/8426).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified FileOptions message, length delimited. Does not implicitly {@link google.protobuf.FileOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {google.protobuf.IFileOptions} message FileOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FileOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a FileOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.FileOptions} FileOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FileOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.FileOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.javaPackage = reader.string();
+                            break;
+                        case 8:
+                            message.javaOuterClassname = reader.string();
+                            break;
+                        case 10:
+                            message.javaMultipleFiles = reader.bool();
+                            break;
+                        case 20:
+                            message.javaGenerateEqualsAndHash = reader.bool();
+                            break;
+                        case 27:
+                            message.javaStringCheckUtf8 = reader.bool();
+                            break;
+                        case 9:
+                            message.optimizeFor = reader.int32();
+                            break;
+                        case 11:
+                            message.goPackage = reader.string();
+                            break;
+                        case 16:
+                            message.ccGenericServices = reader.bool();
+                            break;
+                        case 17:
+                            message.javaGenericServices = reader.bool();
+                            break;
+                        case 18:
+                            message.pyGenericServices = reader.bool();
+                            break;
+                        case 42:
+                            message.phpGenericServices = reader.bool();
+                            break;
+                        case 23:
+                            message.deprecated = reader.bool();
+                            break;
+                        case 31:
+                            message.ccEnableArenas = reader.bool();
+                            break;
+                        case 36:
+                            message.objcClassPrefix = reader.string();
+                            break;
+                        case 37:
+                            message.csharpNamespace = reader.string();
+                            break;
+                        case 39:
+                            message.swiftPrefix = reader.string();
+                            break;
+                        case 40:
+                            message.phpClassPrefix = reader.string();
+                            break;
+                        case 41:
+                            message.phpNamespace = reader.string();
+                            break;
+                        case 44:
+                            message.phpMetadataNamespace = reader.string();
+                            break;
+                        case 45:
+                            message.rubyPackage = reader.string();
+                            break;
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        case 1053:
+                            if (!(message[".google.api.resourceDefinition"] && message[".google.api.resourceDefinition"].length))
+                                message[".google.api.resourceDefinition"] = [];
+                            message[".google.api.resourceDefinition"].push($root.google.api.ResourceDescriptor.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a FileOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.FileOptions} FileOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FileOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a FileOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                FileOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.javaPackage != null && message.hasOwnProperty("javaPackage"))
+                        if (!$util.isString(message.javaPackage))
+                            return "javaPackage: string expected";
+                    if (message.javaOuterClassname != null && message.hasOwnProperty("javaOuterClassname"))
+                        if (!$util.isString(message.javaOuterClassname))
+                            return "javaOuterClassname: string expected";
+                    if (message.javaMultipleFiles != null && message.hasOwnProperty("javaMultipleFiles"))
+                        if (typeof message.javaMultipleFiles !== "boolean")
+                            return "javaMultipleFiles: boolean expected";
+                    if (message.javaGenerateEqualsAndHash != null && message.hasOwnProperty("javaGenerateEqualsAndHash"))
+                        if (typeof message.javaGenerateEqualsAndHash !== "boolean")
+                            return "javaGenerateEqualsAndHash: boolean expected";
+                    if (message.javaStringCheckUtf8 != null && message.hasOwnProperty("javaStringCheckUtf8"))
+                        if (typeof message.javaStringCheckUtf8 !== "boolean")
+                            return "javaStringCheckUtf8: boolean expected";
+                    if (message.optimizeFor != null && message.hasOwnProperty("optimizeFor"))
+                        switch (message.optimizeFor) {
+                        default:
+                            return "optimizeFor: enum value expected";
+                        case 1:
+                        case 2:
+                        case 3:
+                            break;
+                        }
+                    if (message.goPackage != null && message.hasOwnProperty("goPackage"))
+                        if (!$util.isString(message.goPackage))
+                            return "goPackage: string expected";
+                    if (message.ccGenericServices != null && message.hasOwnProperty("ccGenericServices"))
+                        if (typeof message.ccGenericServices !== "boolean")
+                            return "ccGenericServices: boolean expected";
+                    if (message.javaGenericServices != null && message.hasOwnProperty("javaGenericServices"))
+                        if (typeof message.javaGenericServices !== "boolean")
+                            return "javaGenericServices: boolean expected";
+                    if (message.pyGenericServices != null && message.hasOwnProperty("pyGenericServices"))
+                        if (typeof message.pyGenericServices !== "boolean")
+                            return "pyGenericServices: boolean expected";
+                    if (message.phpGenericServices != null && message.hasOwnProperty("phpGenericServices"))
+                        if (typeof message.phpGenericServices !== "boolean")
+                            return "phpGenericServices: boolean expected";
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        if (typeof message.deprecated !== "boolean")
+                            return "deprecated: boolean expected";
+                    if (message.ccEnableArenas != null && message.hasOwnProperty("ccEnableArenas"))
+                        if (typeof message.ccEnableArenas !== "boolean")
+                            return "ccEnableArenas: boolean expected";
+                    if (message.objcClassPrefix != null && message.hasOwnProperty("objcClassPrefix"))
+                        if (!$util.isString(message.objcClassPrefix))
+                            return "objcClassPrefix: string expected";
+                    if (message.csharpNamespace != null && message.hasOwnProperty("csharpNamespace"))
+                        if (!$util.isString(message.csharpNamespace))
+                            return "csharpNamespace: string expected";
+                    if (message.swiftPrefix != null && message.hasOwnProperty("swiftPrefix"))
+                        if (!$util.isString(message.swiftPrefix))
+                            return "swiftPrefix: string expected";
+                    if (message.phpClassPrefix != null && message.hasOwnProperty("phpClassPrefix"))
+                        if (!$util.isString(message.phpClassPrefix))
+                            return "phpClassPrefix: string expected";
+                    if (message.phpNamespace != null && message.hasOwnProperty("phpNamespace"))
+                        if (!$util.isString(message.phpNamespace))
+                            return "phpNamespace: string expected";
+                    if (message.phpMetadataNamespace != null && message.hasOwnProperty("phpMetadataNamespace"))
+                        if (!$util.isString(message.phpMetadataNamespace))
+                            return "phpMetadataNamespace: string expected";
+                    if (message.rubyPackage != null && message.hasOwnProperty("rubyPackage"))
+                        if (!$util.isString(message.rubyPackage))
+                            return "rubyPackage: string expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    if (message[".google.api.resourceDefinition"] != null && message.hasOwnProperty(".google.api.resourceDefinition")) {
+                        if (!Array.isArray(message[".google.api.resourceDefinition"]))
+                            return ".google.api.resourceDefinition: array expected";
+                        for (var i = 0; i < message[".google.api.resourceDefinition"].length; ++i) {
+                            var error = $root.google.api.ResourceDescriptor.verify(message[".google.api.resourceDefinition"][i]);
+                            if (error)
+                                return ".google.api.resourceDefinition." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a FileOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.FileOptions} FileOptions
+                 */
+                FileOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.FileOptions)
+                        return object;
+                    var message = new $root.google.protobuf.FileOptions();
+                    if (object.javaPackage != null)
+                        message.javaPackage = String(object.javaPackage);
+                    if (object.javaOuterClassname != null)
+                        message.javaOuterClassname = String(object.javaOuterClassname);
+                    if (object.javaMultipleFiles != null)
+                        message.javaMultipleFiles = Boolean(object.javaMultipleFiles);
+                    if (object.javaGenerateEqualsAndHash != null)
+                        message.javaGenerateEqualsAndHash = Boolean(object.javaGenerateEqualsAndHash);
+                    if (object.javaStringCheckUtf8 != null)
+                        message.javaStringCheckUtf8 = Boolean(object.javaStringCheckUtf8);
+                    switch (object.optimizeFor) {
+                    case "SPEED":
+                    case 1:
+                        message.optimizeFor = 1;
+                        break;
+                    case "CODE_SIZE":
+                    case 2:
+                        message.optimizeFor = 2;
+                        break;
+                    case "LITE_RUNTIME":
+                    case 3:
+                        message.optimizeFor = 3;
+                        break;
+                    }
+                    if (object.goPackage != null)
+                        message.goPackage = String(object.goPackage);
+                    if (object.ccGenericServices != null)
+                        message.ccGenericServices = Boolean(object.ccGenericServices);
+                    if (object.javaGenericServices != null)
+                        message.javaGenericServices = Boolean(object.javaGenericServices);
+                    if (object.pyGenericServices != null)
+                        message.pyGenericServices = Boolean(object.pyGenericServices);
+                    if (object.phpGenericServices != null)
+                        message.phpGenericServices = Boolean(object.phpGenericServices);
+                    if (object.deprecated != null)
+                        message.deprecated = Boolean(object.deprecated);
+                    if (object.ccEnableArenas != null)
+                        message.ccEnableArenas = Boolean(object.ccEnableArenas);
+                    if (object.objcClassPrefix != null)
+                        message.objcClassPrefix = String(object.objcClassPrefix);
+                    if (object.csharpNamespace != null)
+                        message.csharpNamespace = String(object.csharpNamespace);
+                    if (object.swiftPrefix != null)
+                        message.swiftPrefix = String(object.swiftPrefix);
+                    if (object.phpClassPrefix != null)
+                        message.phpClassPrefix = String(object.phpClassPrefix);
+                    if (object.phpNamespace != null)
+                        message.phpNamespace = String(object.phpNamespace);
+                    if (object.phpMetadataNamespace != null)
+                        message.phpMetadataNamespace = String(object.phpMetadataNamespace);
+                    if (object.rubyPackage != null)
+                        message.rubyPackage = String(object.rubyPackage);
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.FileOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.FileOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    if (object[".google.api.resourceDefinition"]) {
+                        if (!Array.isArray(object[".google.api.resourceDefinition"]))
+                            throw TypeError(".google.protobuf.FileOptions..google.api.resourceDefinition: array expected");
+                        message[".google.api.resourceDefinition"] = [];
+                        for (var i = 0; i < object[".google.api.resourceDefinition"].length; ++i) {
+                            if (typeof object[".google.api.resourceDefinition"][i] !== "object")
+                                throw TypeError(".google.protobuf.FileOptions..google.api.resourceDefinition: object expected");
+                            message[".google.api.resourceDefinition"][i] = $root.google.api.ResourceDescriptor.fromObject(object[".google.api.resourceDefinition"][i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a FileOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.FileOptions
+                 * @static
+                 * @param {google.protobuf.FileOptions} message FileOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                FileOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults) {
+                        object.uninterpretedOption = [];
+                        object[".google.api.resourceDefinition"] = [];
+                    }
+                    if (options.defaults) {
+                        object.javaPackage = "";
+                        object.javaOuterClassname = "";
+                        object.optimizeFor = options.enums === String ? "SPEED" : 1;
+                        object.javaMultipleFiles = false;
+                        object.goPackage = "";
+                        object.ccGenericServices = false;
+                        object.javaGenericServices = false;
+                        object.pyGenericServices = false;
+                        object.javaGenerateEqualsAndHash = false;
+                        object.deprecated = false;
+                        object.javaStringCheckUtf8 = false;
+                        object.ccEnableArenas = true;
+                        object.objcClassPrefix = "";
+                        object.csharpNamespace = "";
+                        object.swiftPrefix = "";
+                        object.phpClassPrefix = "";
+                        object.phpNamespace = "";
+                        object.phpGenericServices = false;
+                        object.phpMetadataNamespace = "";
+                        object.rubyPackage = "";
+                    }
+                    if (message.javaPackage != null && message.hasOwnProperty("javaPackage"))
+                        object.javaPackage = message.javaPackage;
+                    if (message.javaOuterClassname != null && message.hasOwnProperty("javaOuterClassname"))
+                        object.javaOuterClassname = message.javaOuterClassname;
+                    if (message.optimizeFor != null && message.hasOwnProperty("optimizeFor"))
+                        object.optimizeFor = options.enums === String ? $root.google.protobuf.FileOptions.OptimizeMode[message.optimizeFor] : message.optimizeFor;
+                    if (message.javaMultipleFiles != null && message.hasOwnProperty("javaMultipleFiles"))
+                        object.javaMultipleFiles = message.javaMultipleFiles;
+                    if (message.goPackage != null && message.hasOwnProperty("goPackage"))
+                        object.goPackage = message.goPackage;
+                    if (message.ccGenericServices != null && message.hasOwnProperty("ccGenericServices"))
+                        object.ccGenericServices = message.ccGenericServices;
+                    if (message.javaGenericServices != null && message.hasOwnProperty("javaGenericServices"))
+                        object.javaGenericServices = message.javaGenericServices;
+                    if (message.pyGenericServices != null && message.hasOwnProperty("pyGenericServices"))
+                        object.pyGenericServices = message.pyGenericServices;
+                    if (message.javaGenerateEqualsAndHash != null && message.hasOwnProperty("javaGenerateEqualsAndHash"))
+                        object.javaGenerateEqualsAndHash = message.javaGenerateEqualsAndHash;
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        object.deprecated = message.deprecated;
+                    if (message.javaStringCheckUtf8 != null && message.hasOwnProperty("javaStringCheckUtf8"))
+                        object.javaStringCheckUtf8 = message.javaStringCheckUtf8;
+                    if (message.ccEnableArenas != null && message.hasOwnProperty("ccEnableArenas"))
+                        object.ccEnableArenas = message.ccEnableArenas;
+                    if (message.objcClassPrefix != null && message.hasOwnProperty("objcClassPrefix"))
+                        object.objcClassPrefix = message.objcClassPrefix;
+                    if (message.csharpNamespace != null && message.hasOwnProperty("csharpNamespace"))
+                        object.csharpNamespace = message.csharpNamespace;
+                    if (message.swiftPrefix != null && message.hasOwnProperty("swiftPrefix"))
+                        object.swiftPrefix = message.swiftPrefix;
+                    if (message.phpClassPrefix != null && message.hasOwnProperty("phpClassPrefix"))
+                        object.phpClassPrefix = message.phpClassPrefix;
+                    if (message.phpNamespace != null && message.hasOwnProperty("phpNamespace"))
+                        object.phpNamespace = message.phpNamespace;
+                    if (message.phpGenericServices != null && message.hasOwnProperty("phpGenericServices"))
+                        object.phpGenericServices = message.phpGenericServices;
+                    if (message.phpMetadataNamespace != null && message.hasOwnProperty("phpMetadataNamespace"))
+                        object.phpMetadataNamespace = message.phpMetadataNamespace;
+                    if (message.rubyPackage != null && message.hasOwnProperty("rubyPackage"))
+                        object.rubyPackage = message.rubyPackage;
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    if (message[".google.api.resourceDefinition"] && message[".google.api.resourceDefinition"].length) {
+                        object[".google.api.resourceDefinition"] = [];
+                        for (var j = 0; j < message[".google.api.resourceDefinition"].length; ++j)
+                            object[".google.api.resourceDefinition"][j] = $root.google.api.ResourceDescriptor.toObject(message[".google.api.resourceDefinition"][j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this FileOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.FileOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                FileOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                /**
+                 * OptimizeMode enum.
+                 * @name google.protobuf.FileOptions.OptimizeMode
+                 * @enum {number}
+                 * @property {number} SPEED=1 SPEED value
+                 * @property {number} CODE_SIZE=2 CODE_SIZE value
+                 * @property {number} LITE_RUNTIME=3 LITE_RUNTIME value
+                 */
+                FileOptions.OptimizeMode = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[1] = "SPEED"] = 1;
+                    values[valuesById[2] = "CODE_SIZE"] = 2;
+                    values[valuesById[3] = "LITE_RUNTIME"] = 3;
+                    return values;
+                })();
+    
+                return FileOptions;
+            })();
+    
+            protobuf.MessageOptions = (function() {
+    
+                /**
+                 * Properties of a MessageOptions.
+                 * @memberof google.protobuf
+                 * @interface IMessageOptions
+                 * @property {boolean|null} [messageSetWireFormat] MessageOptions messageSetWireFormat
+                 * @property {boolean|null} [noStandardDescriptorAccessor] MessageOptions noStandardDescriptorAccessor
+                 * @property {boolean|null} [deprecated] MessageOptions deprecated
+                 * @property {boolean|null} [mapEntry] MessageOptions mapEntry
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] MessageOptions uninterpretedOption
+                 * @property {google.api.IResourceDescriptor|null} [".google.api.resource"] MessageOptions .google.api.resource
+                 */
+    
+                /**
+                 * Constructs a new MessageOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a MessageOptions.
+                 * @implements IMessageOptions
+                 * @constructor
+                 * @param {google.protobuf.IMessageOptions=} [properties] Properties to set
+                 */
+                function MessageOptions(properties) {
+                    this.uninterpretedOption = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * MessageOptions messageSetWireFormat.
+                 * @member {boolean} messageSetWireFormat
+                 * @memberof google.protobuf.MessageOptions
+                 * @instance
+                 */
+                MessageOptions.prototype.messageSetWireFormat = false;
+    
+                /**
+                 * MessageOptions noStandardDescriptorAccessor.
+                 * @member {boolean} noStandardDescriptorAccessor
+                 * @memberof google.protobuf.MessageOptions
+                 * @instance
+                 */
+                MessageOptions.prototype.noStandardDescriptorAccessor = false;
+    
+                /**
+                 * MessageOptions deprecated.
+                 * @member {boolean} deprecated
+                 * @memberof google.protobuf.MessageOptions
+                 * @instance
+                 */
+                MessageOptions.prototype.deprecated = false;
+    
+                /**
+                 * MessageOptions mapEntry.
+                 * @member {boolean} mapEntry
+                 * @memberof google.protobuf.MessageOptions
+                 * @instance
+                 */
+                MessageOptions.prototype.mapEntry = false;
+    
+                /**
+                 * MessageOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.MessageOptions
+                 * @instance
+                 */
+                MessageOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * MessageOptions .google.api.resource.
+                 * @member {google.api.IResourceDescriptor|null|undefined} .google.api.resource
+                 * @memberof google.protobuf.MessageOptions
+                 * @instance
+                 */
+                MessageOptions.prototype[".google.api.resource"] = null;
+    
+                /**
+                 * Creates a new MessageOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {google.protobuf.IMessageOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.MessageOptions} MessageOptions instance
+                 */
+                MessageOptions.create = function create(properties) {
+                    return new MessageOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified MessageOptions message. Does not implicitly {@link google.protobuf.MessageOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {google.protobuf.IMessageOptions} message MessageOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                MessageOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.messageSetWireFormat != null && Object.hasOwnProperty.call(message, "messageSetWireFormat"))
+                        writer.uint32(/* id 1, wireType 0 =*/8).bool(message.messageSetWireFormat);
+                    if (message.noStandardDescriptorAccessor != null && Object.hasOwnProperty.call(message, "noStandardDescriptorAccessor"))
+                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.noStandardDescriptorAccessor);
+                    if (message.deprecated != null && Object.hasOwnProperty.call(message, "deprecated"))
+                        writer.uint32(/* id 3, wireType 0 =*/24).bool(message.deprecated);
+                    if (message.mapEntry != null && Object.hasOwnProperty.call(message, "mapEntry"))
+                        writer.uint32(/* id 7, wireType 0 =*/56).bool(message.mapEntry);
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    if (message[".google.api.resource"] != null && Object.hasOwnProperty.call(message, ".google.api.resource"))
+                        $root.google.api.ResourceDescriptor.encode(message[".google.api.resource"], writer.uint32(/* id 1053, wireType 2 =*/8426).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified MessageOptions message, length delimited. Does not implicitly {@link google.protobuf.MessageOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {google.protobuf.IMessageOptions} message MessageOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                MessageOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a MessageOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.MessageOptions} MessageOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                MessageOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.MessageOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.messageSetWireFormat = reader.bool();
+                            break;
+                        case 2:
+                            message.noStandardDescriptorAccessor = reader.bool();
+                            break;
+                        case 3:
+                            message.deprecated = reader.bool();
+                            break;
+                        case 7:
+                            message.mapEntry = reader.bool();
+                            break;
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        case 1053:
+                            message[".google.api.resource"] = $root.google.api.ResourceDescriptor.decode(reader, reader.uint32());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a MessageOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.MessageOptions} MessageOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                MessageOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a MessageOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                MessageOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.messageSetWireFormat != null && message.hasOwnProperty("messageSetWireFormat"))
+                        if (typeof message.messageSetWireFormat !== "boolean")
+                            return "messageSetWireFormat: boolean expected";
+                    if (message.noStandardDescriptorAccessor != null && message.hasOwnProperty("noStandardDescriptorAccessor"))
+                        if (typeof message.noStandardDescriptorAccessor !== "boolean")
+                            return "noStandardDescriptorAccessor: boolean expected";
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        if (typeof message.deprecated !== "boolean")
+                            return "deprecated: boolean expected";
+                    if (message.mapEntry != null && message.hasOwnProperty("mapEntry"))
+                        if (typeof message.mapEntry !== "boolean")
+                            return "mapEntry: boolean expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    if (message[".google.api.resource"] != null && message.hasOwnProperty(".google.api.resource")) {
+                        var error = $root.google.api.ResourceDescriptor.verify(message[".google.api.resource"]);
+                        if (error)
+                            return ".google.api.resource." + error;
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a MessageOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.MessageOptions} MessageOptions
+                 */
+                MessageOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.MessageOptions)
+                        return object;
+                    var message = new $root.google.protobuf.MessageOptions();
+                    if (object.messageSetWireFormat != null)
+                        message.messageSetWireFormat = Boolean(object.messageSetWireFormat);
+                    if (object.noStandardDescriptorAccessor != null)
+                        message.noStandardDescriptorAccessor = Boolean(object.noStandardDescriptorAccessor);
+                    if (object.deprecated != null)
+                        message.deprecated = Boolean(object.deprecated);
+                    if (object.mapEntry != null)
+                        message.mapEntry = Boolean(object.mapEntry);
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.MessageOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.MessageOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    if (object[".google.api.resource"] != null) {
+                        if (typeof object[".google.api.resource"] !== "object")
+                            throw TypeError(".google.protobuf.MessageOptions..google.api.resource: object expected");
+                        message[".google.api.resource"] = $root.google.api.ResourceDescriptor.fromObject(object[".google.api.resource"]);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a MessageOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.MessageOptions
+                 * @static
+                 * @param {google.protobuf.MessageOptions} message MessageOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                MessageOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.uninterpretedOption = [];
+                    if (options.defaults) {
+                        object.messageSetWireFormat = false;
+                        object.noStandardDescriptorAccessor = false;
+                        object.deprecated = false;
+                        object.mapEntry = false;
+                        object[".google.api.resource"] = null;
+                    }
+                    if (message.messageSetWireFormat != null && message.hasOwnProperty("messageSetWireFormat"))
+                        object.messageSetWireFormat = message.messageSetWireFormat;
+                    if (message.noStandardDescriptorAccessor != null && message.hasOwnProperty("noStandardDescriptorAccessor"))
+                        object.noStandardDescriptorAccessor = message.noStandardDescriptorAccessor;
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        object.deprecated = message.deprecated;
+                    if (message.mapEntry != null && message.hasOwnProperty("mapEntry"))
+                        object.mapEntry = message.mapEntry;
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    if (message[".google.api.resource"] != null && message.hasOwnProperty(".google.api.resource"))
+                        object[".google.api.resource"] = $root.google.api.ResourceDescriptor.toObject(message[".google.api.resource"], options);
+                    return object;
+                };
+    
+                /**
+                 * Converts this MessageOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.MessageOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                MessageOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return MessageOptions;
+            })();
+    
+            protobuf.FieldOptions = (function() {
+    
+                /**
+                 * Properties of a FieldOptions.
+                 * @memberof google.protobuf
+                 * @interface IFieldOptions
+                 * @property {google.protobuf.FieldOptions.CType|null} [ctype] FieldOptions ctype
+                 * @property {boolean|null} [packed] FieldOptions packed
+                 * @property {google.protobuf.FieldOptions.JSType|null} [jstype] FieldOptions jstype
+                 * @property {boolean|null} [lazy] FieldOptions lazy
+                 * @property {boolean|null} [deprecated] FieldOptions deprecated
+                 * @property {boolean|null} [weak] FieldOptions weak
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] FieldOptions uninterpretedOption
+                 * @property {Array.<google.api.FieldBehavior>|null} [".google.api.fieldBehavior"] FieldOptions .google.api.fieldBehavior
+                 * @property {google.api.IResourceReference|null} [".google.api.resourceReference"] FieldOptions .google.api.resourceReference
+                 */
+    
+                /**
+                 * Constructs a new FieldOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a FieldOptions.
+                 * @implements IFieldOptions
+                 * @constructor
+                 * @param {google.protobuf.IFieldOptions=} [properties] Properties to set
+                 */
+                function FieldOptions(properties) {
+                    this.uninterpretedOption = [];
+                    this[".google.api.fieldBehavior"] = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * FieldOptions ctype.
+                 * @member {google.protobuf.FieldOptions.CType} ctype
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype.ctype = 0;
+    
+                /**
+                 * FieldOptions packed.
+                 * @member {boolean} packed
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype.packed = false;
+    
+                /**
+                 * FieldOptions jstype.
+                 * @member {google.protobuf.FieldOptions.JSType} jstype
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype.jstype = 0;
+    
+                /**
+                 * FieldOptions lazy.
+                 * @member {boolean} lazy
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype.lazy = false;
+    
+                /**
+                 * FieldOptions deprecated.
+                 * @member {boolean} deprecated
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype.deprecated = false;
+    
+                /**
+                 * FieldOptions weak.
+                 * @member {boolean} weak
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype.weak = false;
+    
+                /**
+                 * FieldOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * FieldOptions .google.api.fieldBehavior.
+                 * @member {Array.<google.api.FieldBehavior>} .google.api.fieldBehavior
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype[".google.api.fieldBehavior"] = $util.emptyArray;
+    
+                /**
+                 * FieldOptions .google.api.resourceReference.
+                 * @member {google.api.IResourceReference|null|undefined} .google.api.resourceReference
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 */
+                FieldOptions.prototype[".google.api.resourceReference"] = null;
+    
+                /**
+                 * Creates a new FieldOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {google.protobuf.IFieldOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.FieldOptions} FieldOptions instance
+                 */
+                FieldOptions.create = function create(properties) {
+                    return new FieldOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified FieldOptions message. Does not implicitly {@link google.protobuf.FieldOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {google.protobuf.IFieldOptions} message FieldOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FieldOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.ctype != null && Object.hasOwnProperty.call(message, "ctype"))
+                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.ctype);
+                    if (message.packed != null && Object.hasOwnProperty.call(message, "packed"))
+                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.packed);
+                    if (message.deprecated != null && Object.hasOwnProperty.call(message, "deprecated"))
+                        writer.uint32(/* id 3, wireType 0 =*/24).bool(message.deprecated);
+                    if (message.lazy != null && Object.hasOwnProperty.call(message, "lazy"))
+                        writer.uint32(/* id 5, wireType 0 =*/40).bool(message.lazy);
+                    if (message.jstype != null && Object.hasOwnProperty.call(message, "jstype"))
+                        writer.uint32(/* id 6, wireType 0 =*/48).int32(message.jstype);
+                    if (message.weak != null && Object.hasOwnProperty.call(message, "weak"))
+                        writer.uint32(/* id 10, wireType 0 =*/80).bool(message.weak);
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    if (message[".google.api.fieldBehavior"] != null && message[".google.api.fieldBehavior"].length) {
+                        writer.uint32(/* id 1052, wireType 2 =*/8418).fork();
+                        for (var i = 0; i < message[".google.api.fieldBehavior"].length; ++i)
+                            writer.int32(message[".google.api.fieldBehavior"][i]);
+                        writer.ldelim();
+                    }
+                    if (message[".google.api.resourceReference"] != null && Object.hasOwnProperty.call(message, ".google.api.resourceReference"))
+                        $root.google.api.ResourceReference.encode(message[".google.api.resourceReference"], writer.uint32(/* id 1055, wireType 2 =*/8442).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified FieldOptions message, length delimited. Does not implicitly {@link google.protobuf.FieldOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {google.protobuf.IFieldOptions} message FieldOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FieldOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a FieldOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.FieldOptions} FieldOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FieldOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.FieldOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.ctype = reader.int32();
+                            break;
+                        case 2:
+                            message.packed = reader.bool();
+                            break;
+                        case 6:
+                            message.jstype = reader.int32();
+                            break;
+                        case 5:
+                            message.lazy = reader.bool();
+                            break;
+                        case 3:
+                            message.deprecated = reader.bool();
+                            break;
+                        case 10:
+                            message.weak = reader.bool();
+                            break;
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        case 1052:
+                            if (!(message[".google.api.fieldBehavior"] && message[".google.api.fieldBehavior"].length))
+                                message[".google.api.fieldBehavior"] = [];
+                            if ((tag & 7) === 2) {
+                                var end2 = reader.uint32() + reader.pos;
+                                while (reader.pos < end2)
+                                    message[".google.api.fieldBehavior"].push(reader.int32());
+                            } else
+                                message[".google.api.fieldBehavior"].push(reader.int32());
+                            break;
+                        case 1055:
+                            message[".google.api.resourceReference"] = $root.google.api.ResourceReference.decode(reader, reader.uint32());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a FieldOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.FieldOptions} FieldOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FieldOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a FieldOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                FieldOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.ctype != null && message.hasOwnProperty("ctype"))
+                        switch (message.ctype) {
+                        default:
+                            return "ctype: enum value expected";
+                        case 0:
+                        case 1:
+                        case 2:
+                            break;
+                        }
+                    if (message.packed != null && message.hasOwnProperty("packed"))
+                        if (typeof message.packed !== "boolean")
+                            return "packed: boolean expected";
+                    if (message.jstype != null && message.hasOwnProperty("jstype"))
+                        switch (message.jstype) {
+                        default:
+                            return "jstype: enum value expected";
+                        case 0:
+                        case 1:
+                        case 2:
+                            break;
+                        }
+                    if (message.lazy != null && message.hasOwnProperty("lazy"))
+                        if (typeof message.lazy !== "boolean")
+                            return "lazy: boolean expected";
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        if (typeof message.deprecated !== "boolean")
+                            return "deprecated: boolean expected";
+                    if (message.weak != null && message.hasOwnProperty("weak"))
+                        if (typeof message.weak !== "boolean")
+                            return "weak: boolean expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    if (message[".google.api.fieldBehavior"] != null && message.hasOwnProperty(".google.api.fieldBehavior")) {
+                        if (!Array.isArray(message[".google.api.fieldBehavior"]))
+                            return ".google.api.fieldBehavior: array expected";
+                        for (var i = 0; i < message[".google.api.fieldBehavior"].length; ++i)
+                            switch (message[".google.api.fieldBehavior"][i]) {
+                            default:
+                                return ".google.api.fieldBehavior: enum value[] expected";
+                            case 0:
+                            case 1:
+                            case 2:
+                            case 3:
+                            case 4:
+                            case 5:
+                            case 6:
+                            case 7:
+                                break;
+                            }
+                    }
+                    if (message[".google.api.resourceReference"] != null && message.hasOwnProperty(".google.api.resourceReference")) {
+                        var error = $root.google.api.ResourceReference.verify(message[".google.api.resourceReference"]);
+                        if (error)
+                            return ".google.api.resourceReference." + error;
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a FieldOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.FieldOptions} FieldOptions
+                 */
+                FieldOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.FieldOptions)
+                        return object;
+                    var message = new $root.google.protobuf.FieldOptions();
+                    switch (object.ctype) {
+                    case "STRING":
+                    case 0:
+                        message.ctype = 0;
+                        break;
+                    case "CORD":
+                    case 1:
+                        message.ctype = 1;
+                        break;
+                    case "STRING_PIECE":
+                    case 2:
+                        message.ctype = 2;
+                        break;
+                    }
+                    if (object.packed != null)
+                        message.packed = Boolean(object.packed);
+                    switch (object.jstype) {
+                    case "JS_NORMAL":
+                    case 0:
+                        message.jstype = 0;
+                        break;
+                    case "JS_STRING":
+                    case 1:
+                        message.jstype = 1;
+                        break;
+                    case "JS_NUMBER":
+                    case 2:
+                        message.jstype = 2;
+                        break;
+                    }
+                    if (object.lazy != null)
+                        message.lazy = Boolean(object.lazy);
+                    if (object.deprecated != null)
+                        message.deprecated = Boolean(object.deprecated);
+                    if (object.weak != null)
+                        message.weak = Boolean(object.weak);
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.FieldOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.FieldOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    if (object[".google.api.fieldBehavior"]) {
+                        if (!Array.isArray(object[".google.api.fieldBehavior"]))
+                            throw TypeError(".google.protobuf.FieldOptions..google.api.fieldBehavior: array expected");
+                        message[".google.api.fieldBehavior"] = [];
+                        for (var i = 0; i < object[".google.api.fieldBehavior"].length; ++i)
+                            switch (object[".google.api.fieldBehavior"][i]) {
+                            default:
+                            case "FIELD_BEHAVIOR_UNSPECIFIED":
+                            case 0:
+                                message[".google.api.fieldBehavior"][i] = 0;
+                                break;
+                            case "OPTIONAL":
+                            case 1:
+                                message[".google.api.fieldBehavior"][i] = 1;
+                                break;
+                            case "REQUIRED":
+                            case 2:
+                                message[".google.api.fieldBehavior"][i] = 2;
+                                break;
+                            case "OUTPUT_ONLY":
+                            case 3:
+                                message[".google.api.fieldBehavior"][i] = 3;
+                                break;
+                            case "INPUT_ONLY":
+                            case 4:
+                                message[".google.api.fieldBehavior"][i] = 4;
+                                break;
+                            case "IMMUTABLE":
+                            case 5:
+                                message[".google.api.fieldBehavior"][i] = 5;
+                                break;
+                            case "UNORDERED_LIST":
+                            case 6:
+                                message[".google.api.fieldBehavior"][i] = 6;
+                                break;
+                            case "NON_EMPTY_DEFAULT":
+                            case 7:
+                                message[".google.api.fieldBehavior"][i] = 7;
+                                break;
+                            }
+                    }
+                    if (object[".google.api.resourceReference"] != null) {
+                        if (typeof object[".google.api.resourceReference"] !== "object")
+                            throw TypeError(".google.protobuf.FieldOptions..google.api.resourceReference: object expected");
+                        message[".google.api.resourceReference"] = $root.google.api.ResourceReference.fromObject(object[".google.api.resourceReference"]);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a FieldOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.FieldOptions
+                 * @static
+                 * @param {google.protobuf.FieldOptions} message FieldOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                FieldOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults) {
+                        object.uninterpretedOption = [];
+                        object[".google.api.fieldBehavior"] = [];
+                    }
+                    if (options.defaults) {
+                        object.ctype = options.enums === String ? "STRING" : 0;
+                        object.packed = false;
+                        object.deprecated = false;
+                        object.lazy = false;
+                        object.jstype = options.enums === String ? "JS_NORMAL" : 0;
+                        object.weak = false;
+                        object[".google.api.resourceReference"] = null;
+                    }
+                    if (message.ctype != null && message.hasOwnProperty("ctype"))
+                        object.ctype = options.enums === String ? $root.google.protobuf.FieldOptions.CType[message.ctype] : message.ctype;
+                    if (message.packed != null && message.hasOwnProperty("packed"))
+                        object.packed = message.packed;
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        object.deprecated = message.deprecated;
+                    if (message.lazy != null && message.hasOwnProperty("lazy"))
+                        object.lazy = message.lazy;
+                    if (message.jstype != null && message.hasOwnProperty("jstype"))
+                        object.jstype = options.enums === String ? $root.google.protobuf.FieldOptions.JSType[message.jstype] : message.jstype;
+                    if (message.weak != null && message.hasOwnProperty("weak"))
+                        object.weak = message.weak;
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    if (message[".google.api.fieldBehavior"] && message[".google.api.fieldBehavior"].length) {
+                        object[".google.api.fieldBehavior"] = [];
+                        for (var j = 0; j < message[".google.api.fieldBehavior"].length; ++j)
+                            object[".google.api.fieldBehavior"][j] = options.enums === String ? $root.google.api.FieldBehavior[message[".google.api.fieldBehavior"][j]] : message[".google.api.fieldBehavior"][j];
+                    }
+                    if (message[".google.api.resourceReference"] != null && message.hasOwnProperty(".google.api.resourceReference"))
+                        object[".google.api.resourceReference"] = $root.google.api.ResourceReference.toObject(message[".google.api.resourceReference"], options);
+                    return object;
+                };
+    
+                /**
+                 * Converts this FieldOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.FieldOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                FieldOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                /**
+                 * CType enum.
+                 * @name google.protobuf.FieldOptions.CType
+                 * @enum {number}
+                 * @property {number} STRING=0 STRING value
+                 * @property {number} CORD=1 CORD value
+                 * @property {number} STRING_PIECE=2 STRING_PIECE value
+                 */
+                FieldOptions.CType = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[0] = "STRING"] = 0;
+                    values[valuesById[1] = "CORD"] = 1;
+                    values[valuesById[2] = "STRING_PIECE"] = 2;
+                    return values;
+                })();
+    
+                /**
+                 * JSType enum.
+                 * @name google.protobuf.FieldOptions.JSType
+                 * @enum {number}
+                 * @property {number} JS_NORMAL=0 JS_NORMAL value
+                 * @property {number} JS_STRING=1 JS_STRING value
+                 * @property {number} JS_NUMBER=2 JS_NUMBER value
+                 */
+                FieldOptions.JSType = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[0] = "JS_NORMAL"] = 0;
+                    values[valuesById[1] = "JS_STRING"] = 1;
+                    values[valuesById[2] = "JS_NUMBER"] = 2;
+                    return values;
+                })();
+    
+                return FieldOptions;
+            })();
+    
+            protobuf.OneofOptions = (function() {
+    
+                /**
+                 * Properties of an OneofOptions.
+                 * @memberof google.protobuf
+                 * @interface IOneofOptions
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] OneofOptions uninterpretedOption
+                 */
+    
+                /**
+                 * Constructs a new OneofOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an OneofOptions.
+                 * @implements IOneofOptions
+                 * @constructor
+                 * @param {google.protobuf.IOneofOptions=} [properties] Properties to set
+                 */
+                function OneofOptions(properties) {
+                    this.uninterpretedOption = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * OneofOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.OneofOptions
+                 * @instance
+                 */
+                OneofOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * Creates a new OneofOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {google.protobuf.IOneofOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.OneofOptions} OneofOptions instance
+                 */
+                OneofOptions.create = function create(properties) {
+                    return new OneofOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified OneofOptions message. Does not implicitly {@link google.protobuf.OneofOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {google.protobuf.IOneofOptions} message OneofOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                OneofOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified OneofOptions message, length delimited. Does not implicitly {@link google.protobuf.OneofOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {google.protobuf.IOneofOptions} message OneofOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                OneofOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an OneofOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.OneofOptions} OneofOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                OneofOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.OneofOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an OneofOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.OneofOptions} OneofOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                OneofOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an OneofOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                OneofOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates an OneofOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.OneofOptions} OneofOptions
+                 */
+                OneofOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.OneofOptions)
+                        return object;
+                    var message = new $root.google.protobuf.OneofOptions();
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.OneofOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.OneofOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an OneofOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.OneofOptions
+                 * @static
+                 * @param {google.protobuf.OneofOptions} message OneofOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                OneofOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.uninterpretedOption = [];
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this OneofOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.OneofOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                OneofOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return OneofOptions;
+            })();
+    
+            protobuf.EnumOptions = (function() {
+    
+                /**
+                 * Properties of an EnumOptions.
+                 * @memberof google.protobuf
+                 * @interface IEnumOptions
+                 * @property {boolean|null} [allowAlias] EnumOptions allowAlias
+                 * @property {boolean|null} [deprecated] EnumOptions deprecated
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] EnumOptions uninterpretedOption
+                 */
+    
+                /**
+                 * Constructs a new EnumOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an EnumOptions.
+                 * @implements IEnumOptions
+                 * @constructor
+                 * @param {google.protobuf.IEnumOptions=} [properties] Properties to set
+                 */
+                function EnumOptions(properties) {
+                    this.uninterpretedOption = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * EnumOptions allowAlias.
+                 * @member {boolean} allowAlias
+                 * @memberof google.protobuf.EnumOptions
+                 * @instance
+                 */
+                EnumOptions.prototype.allowAlias = false;
+    
+                /**
+                 * EnumOptions deprecated.
+                 * @member {boolean} deprecated
+                 * @memberof google.protobuf.EnumOptions
+                 * @instance
+                 */
+                EnumOptions.prototype.deprecated = false;
+    
+                /**
+                 * EnumOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.EnumOptions
+                 * @instance
+                 */
+                EnumOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * Creates a new EnumOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {google.protobuf.IEnumOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.EnumOptions} EnumOptions instance
+                 */
+                EnumOptions.create = function create(properties) {
+                    return new EnumOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified EnumOptions message. Does not implicitly {@link google.protobuf.EnumOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {google.protobuf.IEnumOptions} message EnumOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.allowAlias != null && Object.hasOwnProperty.call(message, "allowAlias"))
+                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.allowAlias);
+                    if (message.deprecated != null && Object.hasOwnProperty.call(message, "deprecated"))
+                        writer.uint32(/* id 3, wireType 0 =*/24).bool(message.deprecated);
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified EnumOptions message, length delimited. Does not implicitly {@link google.protobuf.EnumOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {google.protobuf.IEnumOptions} message EnumOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an EnumOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.EnumOptions} EnumOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.EnumOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 2:
+                            message.allowAlias = reader.bool();
+                            break;
+                        case 3:
+                            message.deprecated = reader.bool();
+                            break;
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an EnumOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.EnumOptions} EnumOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an EnumOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                EnumOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.allowAlias != null && message.hasOwnProperty("allowAlias"))
+                        if (typeof message.allowAlias !== "boolean")
+                            return "allowAlias: boolean expected";
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        if (typeof message.deprecated !== "boolean")
+                            return "deprecated: boolean expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates an EnumOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.EnumOptions} EnumOptions
+                 */
+                EnumOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.EnumOptions)
+                        return object;
+                    var message = new $root.google.protobuf.EnumOptions();
+                    if (object.allowAlias != null)
+                        message.allowAlias = Boolean(object.allowAlias);
+                    if (object.deprecated != null)
+                        message.deprecated = Boolean(object.deprecated);
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.EnumOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.EnumOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an EnumOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.EnumOptions
+                 * @static
+                 * @param {google.protobuf.EnumOptions} message EnumOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                EnumOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.uninterpretedOption = [];
+                    if (options.defaults) {
+                        object.allowAlias = false;
+                        object.deprecated = false;
+                    }
+                    if (message.allowAlias != null && message.hasOwnProperty("allowAlias"))
+                        object.allowAlias = message.allowAlias;
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        object.deprecated = message.deprecated;
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this EnumOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.EnumOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                EnumOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return EnumOptions;
+            })();
+    
+            protobuf.EnumValueOptions = (function() {
+    
+                /**
+                 * Properties of an EnumValueOptions.
+                 * @memberof google.protobuf
+                 * @interface IEnumValueOptions
+                 * @property {boolean|null} [deprecated] EnumValueOptions deprecated
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] EnumValueOptions uninterpretedOption
+                 */
+    
+                /**
+                 * Constructs a new EnumValueOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an EnumValueOptions.
+                 * @implements IEnumValueOptions
+                 * @constructor
+                 * @param {google.protobuf.IEnumValueOptions=} [properties] Properties to set
+                 */
+                function EnumValueOptions(properties) {
+                    this.uninterpretedOption = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * EnumValueOptions deprecated.
+                 * @member {boolean} deprecated
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @instance
+                 */
+                EnumValueOptions.prototype.deprecated = false;
+    
+                /**
+                 * EnumValueOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @instance
+                 */
+                EnumValueOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * Creates a new EnumValueOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {google.protobuf.IEnumValueOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.EnumValueOptions} EnumValueOptions instance
+                 */
+                EnumValueOptions.create = function create(properties) {
+                    return new EnumValueOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified EnumValueOptions message. Does not implicitly {@link google.protobuf.EnumValueOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {google.protobuf.IEnumValueOptions} message EnumValueOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumValueOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.deprecated != null && Object.hasOwnProperty.call(message, "deprecated"))
+                        writer.uint32(/* id 1, wireType 0 =*/8).bool(message.deprecated);
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified EnumValueOptions message, length delimited. Does not implicitly {@link google.protobuf.EnumValueOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {google.protobuf.IEnumValueOptions} message EnumValueOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                EnumValueOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an EnumValueOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.EnumValueOptions} EnumValueOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumValueOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.EnumValueOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.deprecated = reader.bool();
+                            break;
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an EnumValueOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.EnumValueOptions} EnumValueOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                EnumValueOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an EnumValueOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                EnumValueOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        if (typeof message.deprecated !== "boolean")
+                            return "deprecated: boolean expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates an EnumValueOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.EnumValueOptions} EnumValueOptions
+                 */
+                EnumValueOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.EnumValueOptions)
+                        return object;
+                    var message = new $root.google.protobuf.EnumValueOptions();
+                    if (object.deprecated != null)
+                        message.deprecated = Boolean(object.deprecated);
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.EnumValueOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.EnumValueOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an EnumValueOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @static
+                 * @param {google.protobuf.EnumValueOptions} message EnumValueOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                EnumValueOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.uninterpretedOption = [];
+                    if (options.defaults)
+                        object.deprecated = false;
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        object.deprecated = message.deprecated;
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this EnumValueOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.EnumValueOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                EnumValueOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return EnumValueOptions;
+            })();
+    
+            protobuf.ServiceOptions = (function() {
+    
+                /**
+                 * Properties of a ServiceOptions.
+                 * @memberof google.protobuf
+                 * @interface IServiceOptions
+                 * @property {boolean|null} [deprecated] ServiceOptions deprecated
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] ServiceOptions uninterpretedOption
+                 * @property {string|null} [".google.api.defaultHost"] ServiceOptions .google.api.defaultHost
+                 * @property {string|null} [".google.api.oauthScopes"] ServiceOptions .google.api.oauthScopes
+                 */
+    
+                /**
+                 * Constructs a new ServiceOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a ServiceOptions.
+                 * @implements IServiceOptions
+                 * @constructor
+                 * @param {google.protobuf.IServiceOptions=} [properties] Properties to set
+                 */
+                function ServiceOptions(properties) {
+                    this.uninterpretedOption = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * ServiceOptions deprecated.
+                 * @member {boolean} deprecated
+                 * @memberof google.protobuf.ServiceOptions
+                 * @instance
+                 */
+                ServiceOptions.prototype.deprecated = false;
+    
+                /**
+                 * ServiceOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.ServiceOptions
+                 * @instance
+                 */
+                ServiceOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * ServiceOptions .google.api.defaultHost.
+                 * @member {string} .google.api.defaultHost
+                 * @memberof google.protobuf.ServiceOptions
+                 * @instance
+                 */
+                ServiceOptions.prototype[".google.api.defaultHost"] = "";
+    
+                /**
+                 * ServiceOptions .google.api.oauthScopes.
+                 * @member {string} .google.api.oauthScopes
+                 * @memberof google.protobuf.ServiceOptions
+                 * @instance
+                 */
+                ServiceOptions.prototype[".google.api.oauthScopes"] = "";
+    
+                /**
+                 * Creates a new ServiceOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {google.protobuf.IServiceOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.ServiceOptions} ServiceOptions instance
+                 */
+                ServiceOptions.create = function create(properties) {
+                    return new ServiceOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified ServiceOptions message. Does not implicitly {@link google.protobuf.ServiceOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {google.protobuf.IServiceOptions} message ServiceOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ServiceOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.deprecated != null && Object.hasOwnProperty.call(message, "deprecated"))
+                        writer.uint32(/* id 33, wireType 0 =*/264).bool(message.deprecated);
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    if (message[".google.api.defaultHost"] != null && Object.hasOwnProperty.call(message, ".google.api.defaultHost"))
+                        writer.uint32(/* id 1049, wireType 2 =*/8394).string(message[".google.api.defaultHost"]);
+                    if (message[".google.api.oauthScopes"] != null && Object.hasOwnProperty.call(message, ".google.api.oauthScopes"))
+                        writer.uint32(/* id 1050, wireType 2 =*/8402).string(message[".google.api.oauthScopes"]);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified ServiceOptions message, length delimited. Does not implicitly {@link google.protobuf.ServiceOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {google.protobuf.IServiceOptions} message ServiceOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                ServiceOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a ServiceOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.ServiceOptions} ServiceOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ServiceOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.ServiceOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 33:
+                            message.deprecated = reader.bool();
+                            break;
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        case 1049:
+                            message[".google.api.defaultHost"] = reader.string();
+                            break;
+                        case 1050:
+                            message[".google.api.oauthScopes"] = reader.string();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a ServiceOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.ServiceOptions} ServiceOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                ServiceOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a ServiceOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                ServiceOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        if (typeof message.deprecated !== "boolean")
+                            return "deprecated: boolean expected";
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    if (message[".google.api.defaultHost"] != null && message.hasOwnProperty(".google.api.defaultHost"))
+                        if (!$util.isString(message[".google.api.defaultHost"]))
+                            return ".google.api.defaultHost: string expected";
+                    if (message[".google.api.oauthScopes"] != null && message.hasOwnProperty(".google.api.oauthScopes"))
+                        if (!$util.isString(message[".google.api.oauthScopes"]))
+                            return ".google.api.oauthScopes: string expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a ServiceOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.ServiceOptions} ServiceOptions
+                 */
+                ServiceOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.ServiceOptions)
+                        return object;
+                    var message = new $root.google.protobuf.ServiceOptions();
+                    if (object.deprecated != null)
+                        message.deprecated = Boolean(object.deprecated);
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.ServiceOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.ServiceOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    if (object[".google.api.defaultHost"] != null)
+                        message[".google.api.defaultHost"] = String(object[".google.api.defaultHost"]);
+                    if (object[".google.api.oauthScopes"] != null)
+                        message[".google.api.oauthScopes"] = String(object[".google.api.oauthScopes"]);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a ServiceOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.ServiceOptions
+                 * @static
+                 * @param {google.protobuf.ServiceOptions} message ServiceOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                ServiceOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.uninterpretedOption = [];
+                    if (options.defaults) {
+                        object.deprecated = false;
+                        object[".google.api.defaultHost"] = "";
+                        object[".google.api.oauthScopes"] = "";
+                    }
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        object.deprecated = message.deprecated;
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    if (message[".google.api.defaultHost"] != null && message.hasOwnProperty(".google.api.defaultHost"))
+                        object[".google.api.defaultHost"] = message[".google.api.defaultHost"];
+                    if (message[".google.api.oauthScopes"] != null && message.hasOwnProperty(".google.api.oauthScopes"))
+                        object[".google.api.oauthScopes"] = message[".google.api.oauthScopes"];
+                    return object;
+                };
+    
+                /**
+                 * Converts this ServiceOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.ServiceOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                ServiceOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return ServiceOptions;
+            })();
+    
+            protobuf.MethodOptions = (function() {
+    
+                /**
+                 * Properties of a MethodOptions.
+                 * @memberof google.protobuf
+                 * @interface IMethodOptions
+                 * @property {boolean|null} [deprecated] MethodOptions deprecated
+                 * @property {google.protobuf.MethodOptions.IdempotencyLevel|null} [idempotencyLevel] MethodOptions idempotencyLevel
+                 * @property {Array.<google.protobuf.IUninterpretedOption>|null} [uninterpretedOption] MethodOptions uninterpretedOption
+                 * @property {google.api.IHttpRule|null} [".google.api.http"] MethodOptions .google.api.http
+                 * @property {Array.<string>|null} [".google.api.methodSignature"] MethodOptions .google.api.methodSignature
+                 */
+    
+                /**
+                 * Constructs a new MethodOptions.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a MethodOptions.
+                 * @implements IMethodOptions
+                 * @constructor
+                 * @param {google.protobuf.IMethodOptions=} [properties] Properties to set
+                 */
+                function MethodOptions(properties) {
+                    this.uninterpretedOption = [];
+                    this[".google.api.methodSignature"] = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * MethodOptions deprecated.
+                 * @member {boolean} deprecated
+                 * @memberof google.protobuf.MethodOptions
+                 * @instance
+                 */
+                MethodOptions.prototype.deprecated = false;
+    
+                /**
+                 * MethodOptions idempotencyLevel.
+                 * @member {google.protobuf.MethodOptions.IdempotencyLevel} idempotencyLevel
+                 * @memberof google.protobuf.MethodOptions
+                 * @instance
+                 */
+                MethodOptions.prototype.idempotencyLevel = 0;
+    
+                /**
+                 * MethodOptions uninterpretedOption.
+                 * @member {Array.<google.protobuf.IUninterpretedOption>} uninterpretedOption
+                 * @memberof google.protobuf.MethodOptions
+                 * @instance
+                 */
+                MethodOptions.prototype.uninterpretedOption = $util.emptyArray;
+    
+                /**
+                 * MethodOptions .google.api.http.
+                 * @member {google.api.IHttpRule|null|undefined} .google.api.http
+                 * @memberof google.protobuf.MethodOptions
+                 * @instance
+                 */
+                MethodOptions.prototype[".google.api.http"] = null;
+    
+                /**
+                 * MethodOptions .google.api.methodSignature.
+                 * @member {Array.<string>} .google.api.methodSignature
+                 * @memberof google.protobuf.MethodOptions
+                 * @instance
+                 */
+                MethodOptions.prototype[".google.api.methodSignature"] = $util.emptyArray;
+    
+                /**
+                 * Creates a new MethodOptions instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {google.protobuf.IMethodOptions=} [properties] Properties to set
+                 * @returns {google.protobuf.MethodOptions} MethodOptions instance
+                 */
+                MethodOptions.create = function create(properties) {
+                    return new MethodOptions(properties);
+                };
+    
+                /**
+                 * Encodes the specified MethodOptions message. Does not implicitly {@link google.protobuf.MethodOptions.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {google.protobuf.IMethodOptions} message MethodOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                MethodOptions.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.deprecated != null && Object.hasOwnProperty.call(message, "deprecated"))
+                        writer.uint32(/* id 33, wireType 0 =*/264).bool(message.deprecated);
+                    if (message.idempotencyLevel != null && Object.hasOwnProperty.call(message, "idempotencyLevel"))
+                        writer.uint32(/* id 34, wireType 0 =*/272).int32(message.idempotencyLevel);
+                    if (message.uninterpretedOption != null && message.uninterpretedOption.length)
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.encode(message.uninterpretedOption[i], writer.uint32(/* id 999, wireType 2 =*/7994).fork()).ldelim();
+                    if (message[".google.api.methodSignature"] != null && message[".google.api.methodSignature"].length)
+                        for (var i = 0; i < message[".google.api.methodSignature"].length; ++i)
+                            writer.uint32(/* id 1051, wireType 2 =*/8410).string(message[".google.api.methodSignature"][i]);
+                    if (message[".google.api.http"] != null && Object.hasOwnProperty.call(message, ".google.api.http"))
+                        $root.google.api.HttpRule.encode(message[".google.api.http"], writer.uint32(/* id 72295728, wireType 2 =*/578365826).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified MethodOptions message, length delimited. Does not implicitly {@link google.protobuf.MethodOptions.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {google.protobuf.IMethodOptions} message MethodOptions message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                MethodOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a MethodOptions message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.MethodOptions} MethodOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                MethodOptions.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.MethodOptions();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 33:
+                            message.deprecated = reader.bool();
+                            break;
+                        case 34:
+                            message.idempotencyLevel = reader.int32();
+                            break;
+                        case 999:
+                            if (!(message.uninterpretedOption && message.uninterpretedOption.length))
+                                message.uninterpretedOption = [];
+                            message.uninterpretedOption.push($root.google.protobuf.UninterpretedOption.decode(reader, reader.uint32()));
+                            break;
+                        case 72295728:
+                            message[".google.api.http"] = $root.google.api.HttpRule.decode(reader, reader.uint32());
+                            break;
+                        case 1051:
+                            if (!(message[".google.api.methodSignature"] && message[".google.api.methodSignature"].length))
+                                message[".google.api.methodSignature"] = [];
+                            message[".google.api.methodSignature"].push(reader.string());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a MethodOptions message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.MethodOptions} MethodOptions
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                MethodOptions.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a MethodOptions message.
+                 * @function verify
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                MethodOptions.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        if (typeof message.deprecated !== "boolean")
+                            return "deprecated: boolean expected";
+                    if (message.idempotencyLevel != null && message.hasOwnProperty("idempotencyLevel"))
+                        switch (message.idempotencyLevel) {
+                        default:
+                            return "idempotencyLevel: enum value expected";
+                        case 0:
+                        case 1:
+                        case 2:
+                            break;
+                        }
+                    if (message.uninterpretedOption != null && message.hasOwnProperty("uninterpretedOption")) {
+                        if (!Array.isArray(message.uninterpretedOption))
+                            return "uninterpretedOption: array expected";
+                        for (var i = 0; i < message.uninterpretedOption.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.verify(message.uninterpretedOption[i]);
+                            if (error)
+                                return "uninterpretedOption." + error;
+                        }
+                    }
+                    if (message[".google.api.http"] != null && message.hasOwnProperty(".google.api.http")) {
+                        var error = $root.google.api.HttpRule.verify(message[".google.api.http"]);
+                        if (error)
+                            return ".google.api.http." + error;
+                    }
+                    if (message[".google.api.methodSignature"] != null && message.hasOwnProperty(".google.api.methodSignature")) {
+                        if (!Array.isArray(message[".google.api.methodSignature"]))
+                            return ".google.api.methodSignature: array expected";
+                        for (var i = 0; i < message[".google.api.methodSignature"].length; ++i)
+                            if (!$util.isString(message[".google.api.methodSignature"][i]))
+                                return ".google.api.methodSignature: string[] expected";
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a MethodOptions message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.MethodOptions} MethodOptions
+                 */
+                MethodOptions.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.MethodOptions)
+                        return object;
+                    var message = new $root.google.protobuf.MethodOptions();
+                    if (object.deprecated != null)
+                        message.deprecated = Boolean(object.deprecated);
+                    switch (object.idempotencyLevel) {
+                    case "IDEMPOTENCY_UNKNOWN":
+                    case 0:
+                        message.idempotencyLevel = 0;
+                        break;
+                    case "NO_SIDE_EFFECTS":
+                    case 1:
+                        message.idempotencyLevel = 1;
+                        break;
+                    case "IDEMPOTENT":
+                    case 2:
+                        message.idempotencyLevel = 2;
+                        break;
+                    }
+                    if (object.uninterpretedOption) {
+                        if (!Array.isArray(object.uninterpretedOption))
+                            throw TypeError(".google.protobuf.MethodOptions.uninterpretedOption: array expected");
+                        message.uninterpretedOption = [];
+                        for (var i = 0; i < object.uninterpretedOption.length; ++i) {
+                            if (typeof object.uninterpretedOption[i] !== "object")
+                                throw TypeError(".google.protobuf.MethodOptions.uninterpretedOption: object expected");
+                            message.uninterpretedOption[i] = $root.google.protobuf.UninterpretedOption.fromObject(object.uninterpretedOption[i]);
+                        }
+                    }
+                    if (object[".google.api.http"] != null) {
+                        if (typeof object[".google.api.http"] !== "object")
+                            throw TypeError(".google.protobuf.MethodOptions..google.api.http: object expected");
+                        message[".google.api.http"] = $root.google.api.HttpRule.fromObject(object[".google.api.http"]);
+                    }
+                    if (object[".google.api.methodSignature"]) {
+                        if (!Array.isArray(object[".google.api.methodSignature"]))
+                            throw TypeError(".google.protobuf.MethodOptions..google.api.methodSignature: array expected");
+                        message[".google.api.methodSignature"] = [];
+                        for (var i = 0; i < object[".google.api.methodSignature"].length; ++i)
+                            message[".google.api.methodSignature"][i] = String(object[".google.api.methodSignature"][i]);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a MethodOptions message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.MethodOptions
+                 * @static
+                 * @param {google.protobuf.MethodOptions} message MethodOptions
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                MethodOptions.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults) {
+                        object.uninterpretedOption = [];
+                        object[".google.api.methodSignature"] = [];
+                    }
+                    if (options.defaults) {
+                        object.deprecated = false;
+                        object.idempotencyLevel = options.enums === String ? "IDEMPOTENCY_UNKNOWN" : 0;
+                        object[".google.api.http"] = null;
+                    }
+                    if (message.deprecated != null && message.hasOwnProperty("deprecated"))
+                        object.deprecated = message.deprecated;
+                    if (message.idempotencyLevel != null && message.hasOwnProperty("idempotencyLevel"))
+                        object.idempotencyLevel = options.enums === String ? $root.google.protobuf.MethodOptions.IdempotencyLevel[message.idempotencyLevel] : message.idempotencyLevel;
+                    if (message.uninterpretedOption && message.uninterpretedOption.length) {
+                        object.uninterpretedOption = [];
+                        for (var j = 0; j < message.uninterpretedOption.length; ++j)
+                            object.uninterpretedOption[j] = $root.google.protobuf.UninterpretedOption.toObject(message.uninterpretedOption[j], options);
+                    }
+                    if (message[".google.api.methodSignature"] && message[".google.api.methodSignature"].length) {
+                        object[".google.api.methodSignature"] = [];
+                        for (var j = 0; j < message[".google.api.methodSignature"].length; ++j)
+                            object[".google.api.methodSignature"][j] = message[".google.api.methodSignature"][j];
+                    }
+                    if (message[".google.api.http"] != null && message.hasOwnProperty(".google.api.http"))
+                        object[".google.api.http"] = $root.google.api.HttpRule.toObject(message[".google.api.http"], options);
+                    return object;
+                };
+    
+                /**
+                 * Converts this MethodOptions to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.MethodOptions
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                MethodOptions.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                /**
+                 * IdempotencyLevel enum.
+                 * @name google.protobuf.MethodOptions.IdempotencyLevel
+                 * @enum {number}
+                 * @property {number} IDEMPOTENCY_UNKNOWN=0 IDEMPOTENCY_UNKNOWN value
+                 * @property {number} NO_SIDE_EFFECTS=1 NO_SIDE_EFFECTS value
+                 * @property {number} IDEMPOTENT=2 IDEMPOTENT value
+                 */
+                MethodOptions.IdempotencyLevel = (function() {
+                    var valuesById = {}, values = Object.create(valuesById);
+                    values[valuesById[0] = "IDEMPOTENCY_UNKNOWN"] = 0;
+                    values[valuesById[1] = "NO_SIDE_EFFECTS"] = 1;
+                    values[valuesById[2] = "IDEMPOTENT"] = 2;
+                    return values;
+                })();
+    
+                return MethodOptions;
+            })();
+    
+            protobuf.UninterpretedOption = (function() {
+    
+                /**
+                 * Properties of an UninterpretedOption.
+                 * @memberof google.protobuf
+                 * @interface IUninterpretedOption
+                 * @property {Array.<google.protobuf.UninterpretedOption.INamePart>|null} [name] UninterpretedOption name
+                 * @property {string|null} [identifierValue] UninterpretedOption identifierValue
+                 * @property {number|Long|null} [positiveIntValue] UninterpretedOption positiveIntValue
+                 * @property {number|Long|null} [negativeIntValue] UninterpretedOption negativeIntValue
+                 * @property {number|null} [doubleValue] UninterpretedOption doubleValue
+                 * @property {Uint8Array|null} [stringValue] UninterpretedOption stringValue
+                 * @property {string|null} [aggregateValue] UninterpretedOption aggregateValue
+                 */
+    
+                /**
+                 * Constructs a new UninterpretedOption.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an UninterpretedOption.
+                 * @implements IUninterpretedOption
+                 * @constructor
+                 * @param {google.protobuf.IUninterpretedOption=} [properties] Properties to set
+                 */
+                function UninterpretedOption(properties) {
+                    this.name = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * UninterpretedOption name.
+                 * @member {Array.<google.protobuf.UninterpretedOption.INamePart>} name
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 */
+                UninterpretedOption.prototype.name = $util.emptyArray;
+    
+                /**
+                 * UninterpretedOption identifierValue.
+                 * @member {string} identifierValue
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 */
+                UninterpretedOption.prototype.identifierValue = "";
+    
+                /**
+                 * UninterpretedOption positiveIntValue.
+                 * @member {number|Long} positiveIntValue
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 */
+                UninterpretedOption.prototype.positiveIntValue = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
+    
+                /**
+                 * UninterpretedOption negativeIntValue.
+                 * @member {number|Long} negativeIntValue
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 */
+                UninterpretedOption.prototype.negativeIntValue = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
+    
+                /**
+                 * UninterpretedOption doubleValue.
+                 * @member {number} doubleValue
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 */
+                UninterpretedOption.prototype.doubleValue = 0;
+    
+                /**
+                 * UninterpretedOption stringValue.
+                 * @member {Uint8Array} stringValue
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 */
+                UninterpretedOption.prototype.stringValue = $util.newBuffer([]);
+    
+                /**
+                 * UninterpretedOption aggregateValue.
+                 * @member {string} aggregateValue
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 */
+                UninterpretedOption.prototype.aggregateValue = "";
+    
+                /**
+                 * Creates a new UninterpretedOption instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {google.protobuf.IUninterpretedOption=} [properties] Properties to set
+                 * @returns {google.protobuf.UninterpretedOption} UninterpretedOption instance
+                 */
+                UninterpretedOption.create = function create(properties) {
+                    return new UninterpretedOption(properties);
+                };
+    
+                /**
+                 * Encodes the specified UninterpretedOption message. Does not implicitly {@link google.protobuf.UninterpretedOption.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {google.protobuf.IUninterpretedOption} message UninterpretedOption message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                UninterpretedOption.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.name != null && message.name.length)
+                        for (var i = 0; i < message.name.length; ++i)
+                            $root.google.protobuf.UninterpretedOption.NamePart.encode(message.name[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                    if (message.identifierValue != null && Object.hasOwnProperty.call(message, "identifierValue"))
+                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.identifierValue);
+                    if (message.positiveIntValue != null && Object.hasOwnProperty.call(message, "positiveIntValue"))
+                        writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.positiveIntValue);
+                    if (message.negativeIntValue != null && Object.hasOwnProperty.call(message, "negativeIntValue"))
+                        writer.uint32(/* id 5, wireType 0 =*/40).int64(message.negativeIntValue);
+                    if (message.doubleValue != null && Object.hasOwnProperty.call(message, "doubleValue"))
+                        writer.uint32(/* id 6, wireType 1 =*/49).double(message.doubleValue);
+                    if (message.stringValue != null && Object.hasOwnProperty.call(message, "stringValue"))
+                        writer.uint32(/* id 7, wireType 2 =*/58).bytes(message.stringValue);
+                    if (message.aggregateValue != null && Object.hasOwnProperty.call(message, "aggregateValue"))
+                        writer.uint32(/* id 8, wireType 2 =*/66).string(message.aggregateValue);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified UninterpretedOption message, length delimited. Does not implicitly {@link google.protobuf.UninterpretedOption.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {google.protobuf.IUninterpretedOption} message UninterpretedOption message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                UninterpretedOption.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an UninterpretedOption message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.UninterpretedOption} UninterpretedOption
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                UninterpretedOption.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.UninterpretedOption();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 2:
+                            if (!(message.name && message.name.length))
+                                message.name = [];
+                            message.name.push($root.google.protobuf.UninterpretedOption.NamePart.decode(reader, reader.uint32()));
+                            break;
+                        case 3:
+                            message.identifierValue = reader.string();
+                            break;
+                        case 4:
+                            message.positiveIntValue = reader.uint64();
+                            break;
+                        case 5:
+                            message.negativeIntValue = reader.int64();
+                            break;
+                        case 6:
+                            message.doubleValue = reader.double();
+                            break;
+                        case 7:
+                            message.stringValue = reader.bytes();
+                            break;
+                        case 8:
+                            message.aggregateValue = reader.string();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an UninterpretedOption message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.UninterpretedOption} UninterpretedOption
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                UninterpretedOption.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an UninterpretedOption message.
+                 * @function verify
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                UninterpretedOption.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.name != null && message.hasOwnProperty("name")) {
+                        if (!Array.isArray(message.name))
+                            return "name: array expected";
+                        for (var i = 0; i < message.name.length; ++i) {
+                            var error = $root.google.protobuf.UninterpretedOption.NamePart.verify(message.name[i]);
+                            if (error)
+                                return "name." + error;
+                        }
+                    }
+                    if (message.identifierValue != null && message.hasOwnProperty("identifierValue"))
+                        if (!$util.isString(message.identifierValue))
+                            return "identifierValue: string expected";
+                    if (message.positiveIntValue != null && message.hasOwnProperty("positiveIntValue"))
+                        if (!$util.isInteger(message.positiveIntValue) && !(message.positiveIntValue && $util.isInteger(message.positiveIntValue.low) && $util.isInteger(message.positiveIntValue.high)))
+                            return "positiveIntValue: integer|Long expected";
+                    if (message.negativeIntValue != null && message.hasOwnProperty("negativeIntValue"))
+                        if (!$util.isInteger(message.negativeIntValue) && !(message.negativeIntValue && $util.isInteger(message.negativeIntValue.low) && $util.isInteger(message.negativeIntValue.high)))
+                            return "negativeIntValue: integer|Long expected";
+                    if (message.doubleValue != null && message.hasOwnProperty("doubleValue"))
+                        if (typeof message.doubleValue !== "number")
+                            return "doubleValue: number expected";
+                    if (message.stringValue != null && message.hasOwnProperty("stringValue"))
+                        if (!(message.stringValue && typeof message.stringValue.length === "number" || $util.isString(message.stringValue)))
+                            return "stringValue: buffer expected";
+                    if (message.aggregateValue != null && message.hasOwnProperty("aggregateValue"))
+                        if (!$util.isString(message.aggregateValue))
+                            return "aggregateValue: string expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates an UninterpretedOption message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.UninterpretedOption} UninterpretedOption
+                 */
+                UninterpretedOption.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.UninterpretedOption)
+                        return object;
+                    var message = new $root.google.protobuf.UninterpretedOption();
+                    if (object.name) {
+                        if (!Array.isArray(object.name))
+                            throw TypeError(".google.protobuf.UninterpretedOption.name: array expected");
+                        message.name = [];
+                        for (var i = 0; i < object.name.length; ++i) {
+                            if (typeof object.name[i] !== "object")
+                                throw TypeError(".google.protobuf.UninterpretedOption.name: object expected");
+                            message.name[i] = $root.google.protobuf.UninterpretedOption.NamePart.fromObject(object.name[i]);
+                        }
+                    }
+                    if (object.identifierValue != null)
+                        message.identifierValue = String(object.identifierValue);
+                    if (object.positiveIntValue != null)
+                        if ($util.Long)
+                            (message.positiveIntValue = $util.Long.fromValue(object.positiveIntValue)).unsigned = true;
+                        else if (typeof object.positiveIntValue === "string")
+                            message.positiveIntValue = parseInt(object.positiveIntValue, 10);
+                        else if (typeof object.positiveIntValue === "number")
+                            message.positiveIntValue = object.positiveIntValue;
+                        else if (typeof object.positiveIntValue === "object")
+                            message.positiveIntValue = new $util.LongBits(object.positiveIntValue.low >>> 0, object.positiveIntValue.high >>> 0).toNumber(true);
+                    if (object.negativeIntValue != null)
+                        if ($util.Long)
+                            (message.negativeIntValue = $util.Long.fromValue(object.negativeIntValue)).unsigned = false;
+                        else if (typeof object.negativeIntValue === "string")
+                            message.negativeIntValue = parseInt(object.negativeIntValue, 10);
+                        else if (typeof object.negativeIntValue === "number")
+                            message.negativeIntValue = object.negativeIntValue;
+                        else if (typeof object.negativeIntValue === "object")
+                            message.negativeIntValue = new $util.LongBits(object.negativeIntValue.low >>> 0, object.negativeIntValue.high >>> 0).toNumber();
+                    if (object.doubleValue != null)
+                        message.doubleValue = Number(object.doubleValue);
+                    if (object.stringValue != null)
+                        if (typeof object.stringValue === "string")
+                            $util.base64.decode(object.stringValue, message.stringValue = $util.newBuffer($util.base64.length(object.stringValue)), 0);
+                        else if (object.stringValue.length)
+                            message.stringValue = object.stringValue;
+                    if (object.aggregateValue != null)
+                        message.aggregateValue = String(object.aggregateValue);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an UninterpretedOption message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @static
+                 * @param {google.protobuf.UninterpretedOption} message UninterpretedOption
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                UninterpretedOption.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.name = [];
+                    if (options.defaults) {
+                        object.identifierValue = "";
+                        if ($util.Long) {
+                            var long = new $util.Long(0, 0, true);
+                            object.positiveIntValue = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+                        } else
+                            object.positiveIntValue = options.longs === String ? "0" : 0;
+                        if ($util.Long) {
+                            var long = new $util.Long(0, 0, false);
+                            object.negativeIntValue = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+                        } else
+                            object.negativeIntValue = options.longs === String ? "0" : 0;
+                        object.doubleValue = 0;
+                        if (options.bytes === String)
+                            object.stringValue = "";
+                        else {
+                            object.stringValue = [];
+                            if (options.bytes !== Array)
+                                object.stringValue = $util.newBuffer(object.stringValue);
+                        }
+                        object.aggregateValue = "";
+                    }
+                    if (message.name && message.name.length) {
+                        object.name = [];
+                        for (var j = 0; j < message.name.length; ++j)
+                            object.name[j] = $root.google.protobuf.UninterpretedOption.NamePart.toObject(message.name[j], options);
+                    }
+                    if (message.identifierValue != null && message.hasOwnProperty("identifierValue"))
+                        object.identifierValue = message.identifierValue;
+                    if (message.positiveIntValue != null && message.hasOwnProperty("positiveIntValue"))
+                        if (typeof message.positiveIntValue === "number")
+                            object.positiveIntValue = options.longs === String ? String(message.positiveIntValue) : message.positiveIntValue;
+                        else
+                            object.positiveIntValue = options.longs === String ? $util.Long.prototype.toString.call(message.positiveIntValue) : options.longs === Number ? new $util.LongBits(message.positiveIntValue.low >>> 0, message.positiveIntValue.high >>> 0).toNumber(true) : message.positiveIntValue;
+                    if (message.negativeIntValue != null && message.hasOwnProperty("negativeIntValue"))
+                        if (typeof message.negativeIntValue === "number")
+                            object.negativeIntValue = options.longs === String ? String(message.negativeIntValue) : message.negativeIntValue;
+                        else
+                            object.negativeIntValue = options.longs === String ? $util.Long.prototype.toString.call(message.negativeIntValue) : options.longs === Number ? new $util.LongBits(message.negativeIntValue.low >>> 0, message.negativeIntValue.high >>> 0).toNumber() : message.negativeIntValue;
+                    if (message.doubleValue != null && message.hasOwnProperty("doubleValue"))
+                        object.doubleValue = options.json && !isFinite(message.doubleValue) ? String(message.doubleValue) : message.doubleValue;
+                    if (message.stringValue != null && message.hasOwnProperty("stringValue"))
+                        object.stringValue = options.bytes === String ? $util.base64.encode(message.stringValue, 0, message.stringValue.length) : options.bytes === Array ? Array.prototype.slice.call(message.stringValue) : message.stringValue;
+                    if (message.aggregateValue != null && message.hasOwnProperty("aggregateValue"))
+                        object.aggregateValue = message.aggregateValue;
+                    return object;
+                };
+    
+                /**
+                 * Converts this UninterpretedOption to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.UninterpretedOption
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                UninterpretedOption.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                UninterpretedOption.NamePart = (function() {
+    
+                    /**
+                     * Properties of a NamePart.
+                     * @memberof google.protobuf.UninterpretedOption
+                     * @interface INamePart
+                     * @property {string} namePart NamePart namePart
+                     * @property {boolean} isExtension NamePart isExtension
+                     */
+    
+                    /**
+                     * Constructs a new NamePart.
+                     * @memberof google.protobuf.UninterpretedOption
+                     * @classdesc Represents a NamePart.
+                     * @implements INamePart
+                     * @constructor
+                     * @param {google.protobuf.UninterpretedOption.INamePart=} [properties] Properties to set
+                     */
+                    function NamePart(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * NamePart namePart.
+                     * @member {string} namePart
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @instance
+                     */
+                    NamePart.prototype.namePart = "";
+    
+                    /**
+                     * NamePart isExtension.
+                     * @member {boolean} isExtension
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @instance
+                     */
+                    NamePart.prototype.isExtension = false;
+    
+                    /**
+                     * Creates a new NamePart instance using the specified properties.
+                     * @function create
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {google.protobuf.UninterpretedOption.INamePart=} [properties] Properties to set
+                     * @returns {google.protobuf.UninterpretedOption.NamePart} NamePart instance
+                     */
+                    NamePart.create = function create(properties) {
+                        return new NamePart(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified NamePart message. Does not implicitly {@link google.protobuf.UninterpretedOption.NamePart.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {google.protobuf.UninterpretedOption.INamePart} message NamePart message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    NamePart.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.namePart);
+                        writer.uint32(/* id 2, wireType 0 =*/16).bool(message.isExtension);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified NamePart message, length delimited. Does not implicitly {@link google.protobuf.UninterpretedOption.NamePart.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {google.protobuf.UninterpretedOption.INamePart} message NamePart message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    NamePart.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a NamePart message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.protobuf.UninterpretedOption.NamePart} NamePart
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    NamePart.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.UninterpretedOption.NamePart();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.namePart = reader.string();
+                                break;
+                            case 2:
+                                message.isExtension = reader.bool();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        if (!message.hasOwnProperty("namePart"))
+                            throw $util.ProtocolError("missing required 'namePart'", { instance: message });
+                        if (!message.hasOwnProperty("isExtension"))
+                            throw $util.ProtocolError("missing required 'isExtension'", { instance: message });
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a NamePart message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.protobuf.UninterpretedOption.NamePart} NamePart
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    NamePart.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a NamePart message.
+                     * @function verify
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    NamePart.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (!$util.isString(message.namePart))
+                            return "namePart: string expected";
+                        if (typeof message.isExtension !== "boolean")
+                            return "isExtension: boolean expected";
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a NamePart message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.protobuf.UninterpretedOption.NamePart} NamePart
+                     */
+                    NamePart.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.protobuf.UninterpretedOption.NamePart)
+                            return object;
+                        var message = new $root.google.protobuf.UninterpretedOption.NamePart();
+                        if (object.namePart != null)
+                            message.namePart = String(object.namePart);
+                        if (object.isExtension != null)
+                            message.isExtension = Boolean(object.isExtension);
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a NamePart message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @static
+                     * @param {google.protobuf.UninterpretedOption.NamePart} message NamePart
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    NamePart.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.namePart = "";
+                            object.isExtension = false;
+                        }
+                        if (message.namePart != null && message.hasOwnProperty("namePart"))
+                            object.namePart = message.namePart;
+                        if (message.isExtension != null && message.hasOwnProperty("isExtension"))
+                            object.isExtension = message.isExtension;
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this NamePart to JSON.
+                     * @function toJSON
+                     * @memberof google.protobuf.UninterpretedOption.NamePart
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    NamePart.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return NamePart;
+                })();
+    
+                return UninterpretedOption;
+            })();
+    
+            protobuf.SourceCodeInfo = (function() {
+    
+                /**
+                 * Properties of a SourceCodeInfo.
+                 * @memberof google.protobuf
+                 * @interface ISourceCodeInfo
+                 * @property {Array.<google.protobuf.SourceCodeInfo.ILocation>|null} [location] SourceCodeInfo location
+                 */
+    
+                /**
+                 * Constructs a new SourceCodeInfo.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a SourceCodeInfo.
+                 * @implements ISourceCodeInfo
+                 * @constructor
+                 * @param {google.protobuf.ISourceCodeInfo=} [properties] Properties to set
+                 */
+                function SourceCodeInfo(properties) {
+                    this.location = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * SourceCodeInfo location.
+                 * @member {Array.<google.protobuf.SourceCodeInfo.ILocation>} location
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @instance
+                 */
+                SourceCodeInfo.prototype.location = $util.emptyArray;
+    
+                /**
+                 * Creates a new SourceCodeInfo instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {google.protobuf.ISourceCodeInfo=} [properties] Properties to set
+                 * @returns {google.protobuf.SourceCodeInfo} SourceCodeInfo instance
+                 */
+                SourceCodeInfo.create = function create(properties) {
+                    return new SourceCodeInfo(properties);
+                };
+    
+                /**
+                 * Encodes the specified SourceCodeInfo message. Does not implicitly {@link google.protobuf.SourceCodeInfo.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {google.protobuf.ISourceCodeInfo} message SourceCodeInfo message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                SourceCodeInfo.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.location != null && message.location.length)
+                        for (var i = 0; i < message.location.length; ++i)
+                            $root.google.protobuf.SourceCodeInfo.Location.encode(message.location[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified SourceCodeInfo message, length delimited. Does not implicitly {@link google.protobuf.SourceCodeInfo.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {google.protobuf.ISourceCodeInfo} message SourceCodeInfo message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                SourceCodeInfo.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a SourceCodeInfo message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.SourceCodeInfo} SourceCodeInfo
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                SourceCodeInfo.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.SourceCodeInfo();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            if (!(message.location && message.location.length))
+                                message.location = [];
+                            message.location.push($root.google.protobuf.SourceCodeInfo.Location.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a SourceCodeInfo message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.SourceCodeInfo} SourceCodeInfo
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                SourceCodeInfo.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a SourceCodeInfo message.
+                 * @function verify
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                SourceCodeInfo.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.location != null && message.hasOwnProperty("location")) {
+                        if (!Array.isArray(message.location))
+                            return "location: array expected";
+                        for (var i = 0; i < message.location.length; ++i) {
+                            var error = $root.google.protobuf.SourceCodeInfo.Location.verify(message.location[i]);
+                            if (error)
+                                return "location." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a SourceCodeInfo message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.SourceCodeInfo} SourceCodeInfo
+                 */
+                SourceCodeInfo.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.SourceCodeInfo)
+                        return object;
+                    var message = new $root.google.protobuf.SourceCodeInfo();
+                    if (object.location) {
+                        if (!Array.isArray(object.location))
+                            throw TypeError(".google.protobuf.SourceCodeInfo.location: array expected");
+                        message.location = [];
+                        for (var i = 0; i < object.location.length; ++i) {
+                            if (typeof object.location[i] !== "object")
+                                throw TypeError(".google.protobuf.SourceCodeInfo.location: object expected");
+                            message.location[i] = $root.google.protobuf.SourceCodeInfo.Location.fromObject(object.location[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a SourceCodeInfo message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @static
+                 * @param {google.protobuf.SourceCodeInfo} message SourceCodeInfo
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                SourceCodeInfo.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.location = [];
+                    if (message.location && message.location.length) {
+                        object.location = [];
+                        for (var j = 0; j < message.location.length; ++j)
+                            object.location[j] = $root.google.protobuf.SourceCodeInfo.Location.toObject(message.location[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this SourceCodeInfo to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.SourceCodeInfo
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                SourceCodeInfo.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                SourceCodeInfo.Location = (function() {
+    
+                    /**
+                     * Properties of a Location.
+                     * @memberof google.protobuf.SourceCodeInfo
+                     * @interface ILocation
+                     * @property {Array.<number>|null} [path] Location path
+                     * @property {Array.<number>|null} [span] Location span
+                     * @property {string|null} [leadingComments] Location leadingComments
+                     * @property {string|null} [trailingComments] Location trailingComments
+                     * @property {Array.<string>|null} [leadingDetachedComments] Location leadingDetachedComments
+                     */
+    
+                    /**
+                     * Constructs a new Location.
+                     * @memberof google.protobuf.SourceCodeInfo
+                     * @classdesc Represents a Location.
+                     * @implements ILocation
+                     * @constructor
+                     * @param {google.protobuf.SourceCodeInfo.ILocation=} [properties] Properties to set
+                     */
+                    function Location(properties) {
+                        this.path = [];
+                        this.span = [];
+                        this.leadingDetachedComments = [];
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * Location path.
+                     * @member {Array.<number>} path
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @instance
+                     */
+                    Location.prototype.path = $util.emptyArray;
+    
+                    /**
+                     * Location span.
+                     * @member {Array.<number>} span
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @instance
+                     */
+                    Location.prototype.span = $util.emptyArray;
+    
+                    /**
+                     * Location leadingComments.
+                     * @member {string} leadingComments
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @instance
+                     */
+                    Location.prototype.leadingComments = "";
+    
+                    /**
+                     * Location trailingComments.
+                     * @member {string} trailingComments
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @instance
+                     */
+                    Location.prototype.trailingComments = "";
+    
+                    /**
+                     * Location leadingDetachedComments.
+                     * @member {Array.<string>} leadingDetachedComments
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @instance
+                     */
+                    Location.prototype.leadingDetachedComments = $util.emptyArray;
+    
+                    /**
+                     * Creates a new Location instance using the specified properties.
+                     * @function create
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {google.protobuf.SourceCodeInfo.ILocation=} [properties] Properties to set
+                     * @returns {google.protobuf.SourceCodeInfo.Location} Location instance
+                     */
+                    Location.create = function create(properties) {
+                        return new Location(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified Location message. Does not implicitly {@link google.protobuf.SourceCodeInfo.Location.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {google.protobuf.SourceCodeInfo.ILocation} message Location message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Location.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.path != null && message.path.length) {
+                            writer.uint32(/* id 1, wireType 2 =*/10).fork();
+                            for (var i = 0; i < message.path.length; ++i)
+                                writer.int32(message.path[i]);
+                            writer.ldelim();
+                        }
+                        if (message.span != null && message.span.length) {
+                            writer.uint32(/* id 2, wireType 2 =*/18).fork();
+                            for (var i = 0; i < message.span.length; ++i)
+                                writer.int32(message.span[i]);
+                            writer.ldelim();
+                        }
+                        if (message.leadingComments != null && Object.hasOwnProperty.call(message, "leadingComments"))
+                            writer.uint32(/* id 3, wireType 2 =*/26).string(message.leadingComments);
+                        if (message.trailingComments != null && Object.hasOwnProperty.call(message, "trailingComments"))
+                            writer.uint32(/* id 4, wireType 2 =*/34).string(message.trailingComments);
+                        if (message.leadingDetachedComments != null && message.leadingDetachedComments.length)
+                            for (var i = 0; i < message.leadingDetachedComments.length; ++i)
+                                writer.uint32(/* id 6, wireType 2 =*/50).string(message.leadingDetachedComments[i]);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified Location message, length delimited. Does not implicitly {@link google.protobuf.SourceCodeInfo.Location.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {google.protobuf.SourceCodeInfo.ILocation} message Location message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Location.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a Location message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.protobuf.SourceCodeInfo.Location} Location
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Location.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.SourceCodeInfo.Location();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                if (!(message.path && message.path.length))
+                                    message.path = [];
+                                if ((tag & 7) === 2) {
+                                    var end2 = reader.uint32() + reader.pos;
+                                    while (reader.pos < end2)
+                                        message.path.push(reader.int32());
+                                } else
+                                    message.path.push(reader.int32());
+                                break;
+                            case 2:
+                                if (!(message.span && message.span.length))
+                                    message.span = [];
+                                if ((tag & 7) === 2) {
+                                    var end2 = reader.uint32() + reader.pos;
+                                    while (reader.pos < end2)
+                                        message.span.push(reader.int32());
+                                } else
+                                    message.span.push(reader.int32());
+                                break;
+                            case 3:
+                                message.leadingComments = reader.string();
+                                break;
+                            case 4:
+                                message.trailingComments = reader.string();
+                                break;
+                            case 6:
+                                if (!(message.leadingDetachedComments && message.leadingDetachedComments.length))
+                                    message.leadingDetachedComments = [];
+                                message.leadingDetachedComments.push(reader.string());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a Location message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.protobuf.SourceCodeInfo.Location} Location
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Location.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a Location message.
+                     * @function verify
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    Location.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.path != null && message.hasOwnProperty("path")) {
+                            if (!Array.isArray(message.path))
+                                return "path: array expected";
+                            for (var i = 0; i < message.path.length; ++i)
+                                if (!$util.isInteger(message.path[i]))
+                                    return "path: integer[] expected";
+                        }
+                        if (message.span != null && message.hasOwnProperty("span")) {
+                            if (!Array.isArray(message.span))
+                                return "span: array expected";
+                            for (var i = 0; i < message.span.length; ++i)
+                                if (!$util.isInteger(message.span[i]))
+                                    return "span: integer[] expected";
+                        }
+                        if (message.leadingComments != null && message.hasOwnProperty("leadingComments"))
+                            if (!$util.isString(message.leadingComments))
+                                return "leadingComments: string expected";
+                        if (message.trailingComments != null && message.hasOwnProperty("trailingComments"))
+                            if (!$util.isString(message.trailingComments))
+                                return "trailingComments: string expected";
+                        if (message.leadingDetachedComments != null && message.hasOwnProperty("leadingDetachedComments")) {
+                            if (!Array.isArray(message.leadingDetachedComments))
+                                return "leadingDetachedComments: array expected";
+                            for (var i = 0; i < message.leadingDetachedComments.length; ++i)
+                                if (!$util.isString(message.leadingDetachedComments[i]))
+                                    return "leadingDetachedComments: string[] expected";
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a Location message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.protobuf.SourceCodeInfo.Location} Location
+                     */
+                    Location.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.protobuf.SourceCodeInfo.Location)
+                            return object;
+                        var message = new $root.google.protobuf.SourceCodeInfo.Location();
+                        if (object.path) {
+                            if (!Array.isArray(object.path))
+                                throw TypeError(".google.protobuf.SourceCodeInfo.Location.path: array expected");
+                            message.path = [];
+                            for (var i = 0; i < object.path.length; ++i)
+                                message.path[i] = object.path[i] | 0;
+                        }
+                        if (object.span) {
+                            if (!Array.isArray(object.span))
+                                throw TypeError(".google.protobuf.SourceCodeInfo.Location.span: array expected");
+                            message.span = [];
+                            for (var i = 0; i < object.span.length; ++i)
+                                message.span[i] = object.span[i] | 0;
+                        }
+                        if (object.leadingComments != null)
+                            message.leadingComments = String(object.leadingComments);
+                        if (object.trailingComments != null)
+                            message.trailingComments = String(object.trailingComments);
+                        if (object.leadingDetachedComments) {
+                            if (!Array.isArray(object.leadingDetachedComments))
+                                throw TypeError(".google.protobuf.SourceCodeInfo.Location.leadingDetachedComments: array expected");
+                            message.leadingDetachedComments = [];
+                            for (var i = 0; i < object.leadingDetachedComments.length; ++i)
+                                message.leadingDetachedComments[i] = String(object.leadingDetachedComments[i]);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a Location message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @static
+                     * @param {google.protobuf.SourceCodeInfo.Location} message Location
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    Location.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.arrays || options.defaults) {
+                            object.path = [];
+                            object.span = [];
+                            object.leadingDetachedComments = [];
+                        }
+                        if (options.defaults) {
+                            object.leadingComments = "";
+                            object.trailingComments = "";
+                        }
+                        if (message.path && message.path.length) {
+                            object.path = [];
+                            for (var j = 0; j < message.path.length; ++j)
+                                object.path[j] = message.path[j];
+                        }
+                        if (message.span && message.span.length) {
+                            object.span = [];
+                            for (var j = 0; j < message.span.length; ++j)
+                                object.span[j] = message.span[j];
+                        }
+                        if (message.leadingComments != null && message.hasOwnProperty("leadingComments"))
+                            object.leadingComments = message.leadingComments;
+                        if (message.trailingComments != null && message.hasOwnProperty("trailingComments"))
+                            object.trailingComments = message.trailingComments;
+                        if (message.leadingDetachedComments && message.leadingDetachedComments.length) {
+                            object.leadingDetachedComments = [];
+                            for (var j = 0; j < message.leadingDetachedComments.length; ++j)
+                                object.leadingDetachedComments[j] = message.leadingDetachedComments[j];
+                        }
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this Location to JSON.
+                     * @function toJSON
+                     * @memberof google.protobuf.SourceCodeInfo.Location
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    Location.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return Location;
+                })();
+    
+                return SourceCodeInfo;
+            })();
+    
+            protobuf.GeneratedCodeInfo = (function() {
+    
+                /**
+                 * Properties of a GeneratedCodeInfo.
+                 * @memberof google.protobuf
+                 * @interface IGeneratedCodeInfo
+                 * @property {Array.<google.protobuf.GeneratedCodeInfo.IAnnotation>|null} [annotation] GeneratedCodeInfo annotation
+                 */
+    
+                /**
+                 * Constructs a new GeneratedCodeInfo.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a GeneratedCodeInfo.
+                 * @implements IGeneratedCodeInfo
+                 * @constructor
+                 * @param {google.protobuf.IGeneratedCodeInfo=} [properties] Properties to set
+                 */
+                function GeneratedCodeInfo(properties) {
+                    this.annotation = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * GeneratedCodeInfo annotation.
+                 * @member {Array.<google.protobuf.GeneratedCodeInfo.IAnnotation>} annotation
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @instance
+                 */
+                GeneratedCodeInfo.prototype.annotation = $util.emptyArray;
+    
+                /**
+                 * Creates a new GeneratedCodeInfo instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {google.protobuf.IGeneratedCodeInfo=} [properties] Properties to set
+                 * @returns {google.protobuf.GeneratedCodeInfo} GeneratedCodeInfo instance
+                 */
+                GeneratedCodeInfo.create = function create(properties) {
+                    return new GeneratedCodeInfo(properties);
+                };
+    
+                /**
+                 * Encodes the specified GeneratedCodeInfo message. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {google.protobuf.IGeneratedCodeInfo} message GeneratedCodeInfo message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                GeneratedCodeInfo.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.annotation != null && message.annotation.length)
+                        for (var i = 0; i < message.annotation.length; ++i)
+                            $root.google.protobuf.GeneratedCodeInfo.Annotation.encode(message.annotation[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified GeneratedCodeInfo message, length delimited. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {google.protobuf.IGeneratedCodeInfo} message GeneratedCodeInfo message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                GeneratedCodeInfo.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a GeneratedCodeInfo message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.GeneratedCodeInfo} GeneratedCodeInfo
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                GeneratedCodeInfo.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.GeneratedCodeInfo();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            if (!(message.annotation && message.annotation.length))
+                                message.annotation = [];
+                            message.annotation.push($root.google.protobuf.GeneratedCodeInfo.Annotation.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a GeneratedCodeInfo message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.GeneratedCodeInfo} GeneratedCodeInfo
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                GeneratedCodeInfo.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a GeneratedCodeInfo message.
+                 * @function verify
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                GeneratedCodeInfo.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.annotation != null && message.hasOwnProperty("annotation")) {
+                        if (!Array.isArray(message.annotation))
+                            return "annotation: array expected";
+                        for (var i = 0; i < message.annotation.length; ++i) {
+                            var error = $root.google.protobuf.GeneratedCodeInfo.Annotation.verify(message.annotation[i]);
+                            if (error)
+                                return "annotation." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a GeneratedCodeInfo message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.GeneratedCodeInfo} GeneratedCodeInfo
+                 */
+                GeneratedCodeInfo.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.GeneratedCodeInfo)
+                        return object;
+                    var message = new $root.google.protobuf.GeneratedCodeInfo();
+                    if (object.annotation) {
+                        if (!Array.isArray(object.annotation))
+                            throw TypeError(".google.protobuf.GeneratedCodeInfo.annotation: array expected");
+                        message.annotation = [];
+                        for (var i = 0; i < object.annotation.length; ++i) {
+                            if (typeof object.annotation[i] !== "object")
+                                throw TypeError(".google.protobuf.GeneratedCodeInfo.annotation: object expected");
+                            message.annotation[i] = $root.google.protobuf.GeneratedCodeInfo.Annotation.fromObject(object.annotation[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a GeneratedCodeInfo message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @static
+                 * @param {google.protobuf.GeneratedCodeInfo} message GeneratedCodeInfo
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                GeneratedCodeInfo.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.annotation = [];
+                    if (message.annotation && message.annotation.length) {
+                        object.annotation = [];
+                        for (var j = 0; j < message.annotation.length; ++j)
+                            object.annotation[j] = $root.google.protobuf.GeneratedCodeInfo.Annotation.toObject(message.annotation[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this GeneratedCodeInfo to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.GeneratedCodeInfo
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                GeneratedCodeInfo.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                GeneratedCodeInfo.Annotation = (function() {
+    
+                    /**
+                     * Properties of an Annotation.
+                     * @memberof google.protobuf.GeneratedCodeInfo
+                     * @interface IAnnotation
+                     * @property {Array.<number>|null} [path] Annotation path
+                     * @property {string|null} [sourceFile] Annotation sourceFile
+                     * @property {number|null} [begin] Annotation begin
+                     * @property {number|null} [end] Annotation end
+                     */
+    
+                    /**
+                     * Constructs a new Annotation.
+                     * @memberof google.protobuf.GeneratedCodeInfo
+                     * @classdesc Represents an Annotation.
+                     * @implements IAnnotation
+                     * @constructor
+                     * @param {google.protobuf.GeneratedCodeInfo.IAnnotation=} [properties] Properties to set
+                     */
+                    function Annotation(properties) {
+                        this.path = [];
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * Annotation path.
+                     * @member {Array.<number>} path
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @instance
+                     */
+                    Annotation.prototype.path = $util.emptyArray;
+    
+                    /**
+                     * Annotation sourceFile.
+                     * @member {string} sourceFile
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @instance
+                     */
+                    Annotation.prototype.sourceFile = "";
+    
+                    /**
+                     * Annotation begin.
+                     * @member {number} begin
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @instance
+                     */
+                    Annotation.prototype.begin = 0;
+    
+                    /**
+                     * Annotation end.
+                     * @member {number} end
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @instance
+                     */
+                    Annotation.prototype.end = 0;
+    
+                    /**
+                     * Creates a new Annotation instance using the specified properties.
+                     * @function create
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {google.protobuf.GeneratedCodeInfo.IAnnotation=} [properties] Properties to set
+                     * @returns {google.protobuf.GeneratedCodeInfo.Annotation} Annotation instance
+                     */
+                    Annotation.create = function create(properties) {
+                        return new Annotation(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified Annotation message. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.Annotation.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {google.protobuf.GeneratedCodeInfo.IAnnotation} message Annotation message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Annotation.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.path != null && message.path.length) {
+                            writer.uint32(/* id 1, wireType 2 =*/10).fork();
+                            for (var i = 0; i < message.path.length; ++i)
+                                writer.int32(message.path[i]);
+                            writer.ldelim();
+                        }
+                        if (message.sourceFile != null && Object.hasOwnProperty.call(message, "sourceFile"))
+                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.sourceFile);
+                        if (message.begin != null && Object.hasOwnProperty.call(message, "begin"))
+                            writer.uint32(/* id 3, wireType 0 =*/24).int32(message.begin);
+                        if (message.end != null && Object.hasOwnProperty.call(message, "end"))
+                            writer.uint32(/* id 4, wireType 0 =*/32).int32(message.end);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified Annotation message, length delimited. Does not implicitly {@link google.protobuf.GeneratedCodeInfo.Annotation.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {google.protobuf.GeneratedCodeInfo.IAnnotation} message Annotation message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Annotation.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes an Annotation message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.protobuf.GeneratedCodeInfo.Annotation} Annotation
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Annotation.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.GeneratedCodeInfo.Annotation();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                if (!(message.path && message.path.length))
+                                    message.path = [];
+                                if ((tag & 7) === 2) {
+                                    var end2 = reader.uint32() + reader.pos;
+                                    while (reader.pos < end2)
+                                        message.path.push(reader.int32());
+                                } else
+                                    message.path.push(reader.int32());
+                                break;
+                            case 2:
+                                message.sourceFile = reader.string();
+                                break;
+                            case 3:
+                                message.begin = reader.int32();
+                                break;
+                            case 4:
+                                message.end = reader.int32();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes an Annotation message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.protobuf.GeneratedCodeInfo.Annotation} Annotation
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Annotation.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies an Annotation message.
+                     * @function verify
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    Annotation.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.path != null && message.hasOwnProperty("path")) {
+                            if (!Array.isArray(message.path))
+                                return "path: array expected";
+                            for (var i = 0; i < message.path.length; ++i)
+                                if (!$util.isInteger(message.path[i]))
+                                    return "path: integer[] expected";
+                        }
+                        if (message.sourceFile != null && message.hasOwnProperty("sourceFile"))
+                            if (!$util.isString(message.sourceFile))
+                                return "sourceFile: string expected";
+                        if (message.begin != null && message.hasOwnProperty("begin"))
+                            if (!$util.isInteger(message.begin))
+                                return "begin: integer expected";
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            if (!$util.isInteger(message.end))
+                                return "end: integer expected";
+                        return null;
+                    };
+    
+                    /**
+                     * Creates an Annotation message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.protobuf.GeneratedCodeInfo.Annotation} Annotation
+                     */
+                    Annotation.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.protobuf.GeneratedCodeInfo.Annotation)
+                            return object;
+                        var message = new $root.google.protobuf.GeneratedCodeInfo.Annotation();
+                        if (object.path) {
+                            if (!Array.isArray(object.path))
+                                throw TypeError(".google.protobuf.GeneratedCodeInfo.Annotation.path: array expected");
+                            message.path = [];
+                            for (var i = 0; i < object.path.length; ++i)
+                                message.path[i] = object.path[i] | 0;
+                        }
+                        if (object.sourceFile != null)
+                            message.sourceFile = String(object.sourceFile);
+                        if (object.begin != null)
+                            message.begin = object.begin | 0;
+                        if (object.end != null)
+                            message.end = object.end | 0;
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from an Annotation message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @static
+                     * @param {google.protobuf.GeneratedCodeInfo.Annotation} message Annotation
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    Annotation.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.arrays || options.defaults)
+                            object.path = [];
+                        if (options.defaults) {
+                            object.sourceFile = "";
+                            object.begin = 0;
+                            object.end = 0;
+                        }
+                        if (message.path && message.path.length) {
+                            object.path = [];
+                            for (var j = 0; j < message.path.length; ++j)
+                                object.path[j] = message.path[j];
+                        }
+                        if (message.sourceFile != null && message.hasOwnProperty("sourceFile"))
+                            object.sourceFile = message.sourceFile;
+                        if (message.begin != null && message.hasOwnProperty("begin"))
+                            object.begin = message.begin;
+                        if (message.end != null && message.hasOwnProperty("end"))
+                            object.end = message.end;
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this Annotation to JSON.
+                     * @function toJSON
+                     * @memberof google.protobuf.GeneratedCodeInfo.Annotation
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    Annotation.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return Annotation;
+                })();
+    
+                return GeneratedCodeInfo;
+            })();
+    
+            protobuf.Timestamp = (function() {
+    
+                /**
+                 * Properties of a Timestamp.
+                 * @memberof google.protobuf
+                 * @interface ITimestamp
+                 * @property {number|Long|null} [seconds] Timestamp seconds
+                 * @property {number|null} [nanos] Timestamp nanos
+                 */
+    
+                /**
+                 * Constructs a new Timestamp.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a Timestamp.
+                 * @implements ITimestamp
+                 * @constructor
+                 * @param {google.protobuf.ITimestamp=} [properties] Properties to set
+                 */
+                function Timestamp(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * Timestamp seconds.
+                 * @member {number|Long} seconds
+                 * @memberof google.protobuf.Timestamp
+                 * @instance
+                 */
+                Timestamp.prototype.seconds = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
+    
+                /**
+                 * Timestamp nanos.
+                 * @member {number} nanos
+                 * @memberof google.protobuf.Timestamp
+                 * @instance
+                 */
+                Timestamp.prototype.nanos = 0;
+    
+                /**
+                 * Creates a new Timestamp instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {google.protobuf.ITimestamp=} [properties] Properties to set
+                 * @returns {google.protobuf.Timestamp} Timestamp instance
+                 */
+                Timestamp.create = function create(properties) {
+                    return new Timestamp(properties);
+                };
+    
+                /**
+                 * Encodes the specified Timestamp message. Does not implicitly {@link google.protobuf.Timestamp.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {google.protobuf.ITimestamp} message Timestamp message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Timestamp.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.seconds != null && Object.hasOwnProperty.call(message, "seconds"))
+                        writer.uint32(/* id 1, wireType 0 =*/8).int64(message.seconds);
+                    if (message.nanos != null && Object.hasOwnProperty.call(message, "nanos"))
+                        writer.uint32(/* id 2, wireType 0 =*/16).int32(message.nanos);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified Timestamp message, length delimited. Does not implicitly {@link google.protobuf.Timestamp.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {google.protobuf.ITimestamp} message Timestamp message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Timestamp.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a Timestamp message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.Timestamp} Timestamp
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Timestamp.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.Timestamp();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.seconds = reader.int64();
+                            break;
+                        case 2:
+                            message.nanos = reader.int32();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a Timestamp message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.Timestamp} Timestamp
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Timestamp.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a Timestamp message.
+                 * @function verify
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                Timestamp.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.seconds != null && message.hasOwnProperty("seconds"))
+                        if (!$util.isInteger(message.seconds) && !(message.seconds && $util.isInteger(message.seconds.low) && $util.isInteger(message.seconds.high)))
+                            return "seconds: integer|Long expected";
+                    if (message.nanos != null && message.hasOwnProperty("nanos"))
+                        if (!$util.isInteger(message.nanos))
+                            return "nanos: integer expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates a Timestamp message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.Timestamp} Timestamp
+                 */
+                Timestamp.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.Timestamp)
+                        return object;
+                    var message = new $root.google.protobuf.Timestamp();
+                    if (object.seconds != null)
+                        if ($util.Long)
+                            (message.seconds = $util.Long.fromValue(object.seconds)).unsigned = false;
+                        else if (typeof object.seconds === "string")
+                            message.seconds = parseInt(object.seconds, 10);
+                        else if (typeof object.seconds === "number")
+                            message.seconds = object.seconds;
+                        else if (typeof object.seconds === "object")
+                            message.seconds = new $util.LongBits(object.seconds.low >>> 0, object.seconds.high >>> 0).toNumber();
+                    if (object.nanos != null)
+                        message.nanos = object.nanos | 0;
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a Timestamp message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.Timestamp
+                 * @static
+                 * @param {google.protobuf.Timestamp} message Timestamp
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                Timestamp.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        if ($util.Long) {
+                            var long = new $util.Long(0, 0, false);
+                            object.seconds = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+                        } else
+                            object.seconds = options.longs === String ? "0" : 0;
+                        object.nanos = 0;
+                    }
+                    if (message.seconds != null && message.hasOwnProperty("seconds"))
+                        if (typeof message.seconds === "number")
+                            object.seconds = options.longs === String ? String(message.seconds) : message.seconds;
+                        else
+                            object.seconds = options.longs === String ? $util.Long.prototype.toString.call(message.seconds) : options.longs === Number ? new $util.LongBits(message.seconds.low >>> 0, message.seconds.high >>> 0).toNumber() : message.seconds;
+                    if (message.nanos != null && message.hasOwnProperty("nanos"))
+                        object.nanos = message.nanos;
+                    return object;
+                };
+    
+                /**
+                 * Converts this Timestamp to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.Timestamp
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                Timestamp.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return Timestamp;
+            })();
+    
+            protobuf.Any = (function() {
+    
+                /**
+                 * Properties of an Any.
+                 * @memberof google.protobuf
+                 * @interface IAny
+                 * @property {string|null} [type_url] Any type_url
+                 * @property {Uint8Array|null} [value] Any value
+                 */
+    
+                /**
+                 * Constructs a new Any.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an Any.
+                 * @implements IAny
+                 * @constructor
+                 * @param {google.protobuf.IAny=} [properties] Properties to set
+                 */
+                function Any(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * Any type_url.
+                 * @member {string} type_url
+                 * @memberof google.protobuf.Any
+                 * @instance
+                 */
+                Any.prototype.type_url = "";
+    
+                /**
+                 * Any value.
+                 * @member {Uint8Array} value
+                 * @memberof google.protobuf.Any
+                 * @instance
+                 */
+                Any.prototype.value = $util.newBuffer([]);
+    
+                /**
+                 * Creates a new Any instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {google.protobuf.IAny=} [properties] Properties to set
+                 * @returns {google.protobuf.Any} Any instance
+                 */
+                Any.create = function create(properties) {
+                    return new Any(properties);
+                };
+    
+                /**
+                 * Encodes the specified Any message. Does not implicitly {@link google.protobuf.Any.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {google.protobuf.IAny} message Any message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Any.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.type_url != null && Object.hasOwnProperty.call(message, "type_url"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.type_url);
+                    if (message.value != null && Object.hasOwnProperty.call(message, "value"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified Any message, length delimited. Does not implicitly {@link google.protobuf.Any.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {google.protobuf.IAny} message Any message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Any.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an Any message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.Any} Any
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Any.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.Any();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.type_url = reader.string();
+                            break;
+                        case 2:
+                            message.value = reader.bytes();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an Any message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.Any} Any
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Any.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an Any message.
+                 * @function verify
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                Any.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.type_url != null && message.hasOwnProperty("type_url"))
+                        if (!$util.isString(message.type_url))
+                            return "type_url: string expected";
+                    if (message.value != null && message.hasOwnProperty("value"))
+                        if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value)))
+                            return "value: buffer expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates an Any message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.Any} Any
+                 */
+                Any.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.Any)
+                        return object;
+                    var message = new $root.google.protobuf.Any();
+                    if (object.type_url != null)
+                        message.type_url = String(object.type_url);
+                    if (object.value != null)
+                        if (typeof object.value === "string")
+                            $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0);
+                        else if (object.value.length)
+                            message.value = object.value;
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an Any message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.Any
+                 * @static
+                 * @param {google.protobuf.Any} message Any
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                Any.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.type_url = "";
+                        if (options.bytes === String)
+                            object.value = "";
+                        else {
+                            object.value = [];
+                            if (options.bytes !== Array)
+                                object.value = $util.newBuffer(object.value);
+                        }
+                    }
+                    if (message.type_url != null && message.hasOwnProperty("type_url"))
+                        object.type_url = message.type_url;
+                    if (message.value != null && message.hasOwnProperty("value"))
+                        object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value;
+                    return object;
+                };
+    
+                /**
+                 * Converts this Any to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.Any
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                Any.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return Any;
+            })();
+    
+            protobuf.Empty = (function() {
+    
+                /**
+                 * Properties of an Empty.
+                 * @memberof google.protobuf
+                 * @interface IEmpty
+                 */
+    
+                /**
+                 * Constructs a new Empty.
+                 * @memberof google.protobuf
+                 * @classdesc Represents an Empty.
+                 * @implements IEmpty
+                 * @constructor
+                 * @param {google.protobuf.IEmpty=} [properties] Properties to set
+                 */
+                function Empty(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * Creates a new Empty instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {google.protobuf.IEmpty=} [properties] Properties to set
+                 * @returns {google.protobuf.Empty} Empty instance
+                 */
+                Empty.create = function create(properties) {
+                    return new Empty(properties);
+                };
+    
+                /**
+                 * Encodes the specified Empty message. Does not implicitly {@link google.protobuf.Empty.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {google.protobuf.IEmpty} message Empty message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Empty.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified Empty message, length delimited. Does not implicitly {@link google.protobuf.Empty.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {google.protobuf.IEmpty} message Empty message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Empty.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an Empty message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.Empty} Empty
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Empty.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.Empty();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an Empty message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.Empty} Empty
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Empty.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an Empty message.
+                 * @function verify
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                Empty.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates an Empty message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.Empty} Empty
+                 */
+                Empty.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.Empty)
+                        return object;
+                    return new $root.google.protobuf.Empty();
+                };
+    
+                /**
+                 * Creates a plain object from an Empty message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.Empty
+                 * @static
+                 * @param {google.protobuf.Empty} message Empty
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                Empty.toObject = function toObject() {
+                    return {};
+                };
+    
+                /**
+                 * Converts this Empty to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.Empty
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                Empty.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return Empty;
+            })();
+    
+            protobuf.FieldMask = (function() {
+    
+                /**
+                 * Properties of a FieldMask.
+                 * @memberof google.protobuf
+                 * @interface IFieldMask
+                 * @property {Array.<string>|null} [paths] FieldMask paths
+                 */
+    
+                /**
+                 * Constructs a new FieldMask.
+                 * @memberof google.protobuf
+                 * @classdesc Represents a FieldMask.
+                 * @implements IFieldMask
+                 * @constructor
+                 * @param {google.protobuf.IFieldMask=} [properties] Properties to set
+                 */
+                function FieldMask(properties) {
+                    this.paths = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * FieldMask paths.
+                 * @member {Array.<string>} paths
+                 * @memberof google.protobuf.FieldMask
+                 * @instance
+                 */
+                FieldMask.prototype.paths = $util.emptyArray;
+    
+                /**
+                 * Creates a new FieldMask instance using the specified properties.
+                 * @function create
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {google.protobuf.IFieldMask=} [properties] Properties to set
+                 * @returns {google.protobuf.FieldMask} FieldMask instance
+                 */
+                FieldMask.create = function create(properties) {
+                    return new FieldMask(properties);
+                };
+    
+                /**
+                 * Encodes the specified FieldMask message. Does not implicitly {@link google.protobuf.FieldMask.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {google.protobuf.IFieldMask} message FieldMask message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FieldMask.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.paths != null && message.paths.length)
+                        for (var i = 0; i < message.paths.length; ++i)
+                            writer.uint32(/* id 1, wireType 2 =*/10).string(message.paths[i]);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified FieldMask message, length delimited. Does not implicitly {@link google.protobuf.FieldMask.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {google.protobuf.IFieldMask} message FieldMask message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                FieldMask.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a FieldMask message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.protobuf.FieldMask} FieldMask
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FieldMask.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.protobuf.FieldMask();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            if (!(message.paths && message.paths.length))
+                                message.paths = [];
+                            message.paths.push(reader.string());
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a FieldMask message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.protobuf.FieldMask} FieldMask
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                FieldMask.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a FieldMask message.
+                 * @function verify
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                FieldMask.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.paths != null && message.hasOwnProperty("paths")) {
+                        if (!Array.isArray(message.paths))
+                            return "paths: array expected";
+                        for (var i = 0; i < message.paths.length; ++i)
+                            if (!$util.isString(message.paths[i]))
+                                return "paths: string[] expected";
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a FieldMask message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.protobuf.FieldMask} FieldMask
+                 */
+                FieldMask.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.protobuf.FieldMask)
+                        return object;
+                    var message = new $root.google.protobuf.FieldMask();
+                    if (object.paths) {
+                        if (!Array.isArray(object.paths))
+                            throw TypeError(".google.protobuf.FieldMask.paths: array expected");
+                        message.paths = [];
+                        for (var i = 0; i < object.paths.length; ++i)
+                            message.paths[i] = String(object.paths[i]);
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a FieldMask message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.protobuf.FieldMask
+                 * @static
+                 * @param {google.protobuf.FieldMask} message FieldMask
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                FieldMask.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.paths = [];
+                    if (message.paths && message.paths.length) {
+                        object.paths = [];
+                        for (var j = 0; j < message.paths.length; ++j)
+                            object.paths[j] = message.paths[j];
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this FieldMask to JSON.
+                 * @function toJSON
+                 * @memberof google.protobuf.FieldMask
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                FieldMask.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return FieldMask;
+            })();
+    
+            return protobuf;
+        })();
+    
+        google.rpc = (function() {
+    
+            /**
+             * Namespace rpc.
+             * @memberof google
+             * @namespace
+             */
+            var rpc = {};
+    
+            rpc.Status = (function() {
+    
+                /**
+                 * Properties of a Status.
+                 * @memberof google.rpc
+                 * @interface IStatus
+                 * @property {number|null} [code] Status code
+                 * @property {string|null} [message] Status message
+                 * @property {Array.<google.protobuf.IAny>|null} [details] Status details
+                 */
+    
+                /**
+                 * Constructs a new Status.
+                 * @memberof google.rpc
+                 * @classdesc Represents a Status.
+                 * @implements IStatus
+                 * @constructor
+                 * @param {google.rpc.IStatus=} [properties] Properties to set
+                 */
+                function Status(properties) {
+                    this.details = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * Status code.
+                 * @member {number} code
+                 * @memberof google.rpc.Status
+                 * @instance
+                 */
+                Status.prototype.code = 0;
+    
+                /**
+                 * Status message.
+                 * @member {string} message
+                 * @memberof google.rpc.Status
+                 * @instance
+                 */
+                Status.prototype.message = "";
+    
+                /**
+                 * Status details.
+                 * @member {Array.<google.protobuf.IAny>} details
+                 * @memberof google.rpc.Status
+                 * @instance
+                 */
+                Status.prototype.details = $util.emptyArray;
+    
+                /**
+                 * Creates a new Status instance using the specified properties.
+                 * @function create
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {google.rpc.IStatus=} [properties] Properties to set
+                 * @returns {google.rpc.Status} Status instance
+                 */
+                Status.create = function create(properties) {
+                    return new Status(properties);
+                };
+    
+                /**
+                 * Encodes the specified Status message. Does not implicitly {@link google.rpc.Status.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {google.rpc.IStatus} message Status message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Status.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.code != null && Object.hasOwnProperty.call(message, "code"))
+                        writer.uint32(/* id 1, wireType 0 =*/8).int32(message.code);
+                    if (message.message != null && Object.hasOwnProperty.call(message, "message"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.message);
+                    if (message.details != null && message.details.length)
+                        for (var i = 0; i < message.details.length; ++i)
+                            $root.google.protobuf.Any.encode(message.details[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified Status message, length delimited. Does not implicitly {@link google.rpc.Status.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {google.rpc.IStatus} message Status message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Status.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes a Status message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.rpc.Status} Status
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Status.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.rpc.Status();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.code = reader.int32();
+                            break;
+                        case 2:
+                            message.message = reader.string();
+                            break;
+                        case 3:
+                            if (!(message.details && message.details.length))
+                                message.details = [];
+                            message.details.push($root.google.protobuf.Any.decode(reader, reader.uint32()));
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes a Status message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.rpc.Status} Status
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Status.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies a Status message.
+                 * @function verify
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                Status.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.code != null && message.hasOwnProperty("code"))
+                        if (!$util.isInteger(message.code))
+                            return "code: integer expected";
+                    if (message.message != null && message.hasOwnProperty("message"))
+                        if (!$util.isString(message.message))
+                            return "message: string expected";
+                    if (message.details != null && message.hasOwnProperty("details")) {
+                        if (!Array.isArray(message.details))
+                            return "details: array expected";
+                        for (var i = 0; i < message.details.length; ++i) {
+                            var error = $root.google.protobuf.Any.verify(message.details[i]);
+                            if (error)
+                                return "details." + error;
+                        }
+                    }
+                    return null;
+                };
+    
+                /**
+                 * Creates a Status message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.rpc.Status} Status
+                 */
+                Status.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.rpc.Status)
+                        return object;
+                    var message = new $root.google.rpc.Status();
+                    if (object.code != null)
+                        message.code = object.code | 0;
+                    if (object.message != null)
+                        message.message = String(object.message);
+                    if (object.details) {
+                        if (!Array.isArray(object.details))
+                            throw TypeError(".google.rpc.Status.details: array expected");
+                        message.details = [];
+                        for (var i = 0; i < object.details.length; ++i) {
+                            if (typeof object.details[i] !== "object")
+                                throw TypeError(".google.rpc.Status.details: object expected");
+                            message.details[i] = $root.google.protobuf.Any.fromObject(object.details[i]);
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from a Status message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.rpc.Status
+                 * @static
+                 * @param {google.rpc.Status} message Status
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                Status.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.details = [];
+                    if (options.defaults) {
+                        object.code = 0;
+                        object.message = "";
+                    }
+                    if (message.code != null && message.hasOwnProperty("code"))
+                        object.code = message.code;
+                    if (message.message != null && message.hasOwnProperty("message"))
+                        object.message = message.message;
+                    if (message.details && message.details.length) {
+                        object.details = [];
+                        for (var j = 0; j < message.details.length; ++j)
+                            object.details[j] = $root.google.protobuf.Any.toObject(message.details[j], options);
+                    }
+                    return object;
+                };
+    
+                /**
+                 * Converts this Status to JSON.
+                 * @function toJSON
+                 * @memberof google.rpc.Status
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                Status.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return Status;
+            })();
+    
+            return rpc;
+        })();
+    
+        google.iam = (function() {
+    
+            /**
+             * Namespace iam.
+             * @memberof google
+             * @namespace
+             */
+            var iam = {};
+    
+            iam.v1 = (function() {
+    
+                /**
+                 * Namespace v1.
+                 * @memberof google.iam
+                 * @namespace
+                 */
+                var v1 = {};
+    
+                v1.IAMPolicy = (function() {
+    
+                    /**
+                     * Constructs a new IAMPolicy service.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a IAMPolicy
+                     * @extends $protobuf.rpc.Service
+                     * @constructor
+                     * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
+                     * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
+                     * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
+                     */
+                    function IAMPolicy(rpcImpl, requestDelimited, responseDelimited) {
+                        $protobuf.rpc.Service.call(this, rpcImpl, requestDelimited, responseDelimited);
+                    }
+    
+                    (IAMPolicy.prototype = Object.create($protobuf.rpc.Service.prototype)).constructor = IAMPolicy;
+    
+                    /**
+                     * Creates new IAMPolicy service using the specified rpc implementation.
+                     * @function create
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @static
+                     * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
+                     * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
+                     * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
+                     * @returns {IAMPolicy} RPC service. Useful where requests and/or responses are streamed.
+                     */
+                    IAMPolicy.create = function create(rpcImpl, requestDelimited, responseDelimited) {
+                        return new this(rpcImpl, requestDelimited, responseDelimited);
+                    };
+    
+                    /**
+                     * Callback as used by {@link google.iam.v1.IAMPolicy#setIamPolicy}.
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @typedef SetIamPolicyCallback
+                     * @type {function}
+                     * @param {Error|null} error Error, if any
+                     * @param {google.iam.v1.Policy} [response] Policy
+                     */
+    
+                    /**
+                     * Calls SetIamPolicy.
+                     * @function setIamPolicy
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @instance
+                     * @param {google.iam.v1.ISetIamPolicyRequest} request SetIamPolicyRequest message or plain object
+                     * @param {google.iam.v1.IAMPolicy.SetIamPolicyCallback} callback Node-style callback called with the error, if any, and Policy
+                     * @returns {undefined}
+                     * @variation 1
+                     */
+                    Object.defineProperty(IAMPolicy.prototype.setIamPolicy = function setIamPolicy(request, callback) {
+                        return this.rpcCall(setIamPolicy, $root.google.iam.v1.SetIamPolicyRequest, $root.google.iam.v1.Policy, request, callback);
+                    }, "name", { value: "SetIamPolicy" });
+    
+                    /**
+                     * Calls SetIamPolicy.
+                     * @function setIamPolicy
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @instance
+                     * @param {google.iam.v1.ISetIamPolicyRequest} request SetIamPolicyRequest message or plain object
+                     * @returns {Promise<google.iam.v1.Policy>} Promise
+                     * @variation 2
+                     */
+    
+                    /**
+                     * Callback as used by {@link google.iam.v1.IAMPolicy#getIamPolicy}.
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @typedef GetIamPolicyCallback
+                     * @type {function}
+                     * @param {Error|null} error Error, if any
+                     * @param {google.iam.v1.Policy} [response] Policy
+                     */
+    
+                    /**
+                     * Calls GetIamPolicy.
+                     * @function getIamPolicy
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @instance
+                     * @param {google.iam.v1.IGetIamPolicyRequest} request GetIamPolicyRequest message or plain object
+                     * @param {google.iam.v1.IAMPolicy.GetIamPolicyCallback} callback Node-style callback called with the error, if any, and Policy
+                     * @returns {undefined}
+                     * @variation 1
+                     */
+                    Object.defineProperty(IAMPolicy.prototype.getIamPolicy = function getIamPolicy(request, callback) {
+                        return this.rpcCall(getIamPolicy, $root.google.iam.v1.GetIamPolicyRequest, $root.google.iam.v1.Policy, request, callback);
+                    }, "name", { value: "GetIamPolicy" });
+    
+                    /**
+                     * Calls GetIamPolicy.
+                     * @function getIamPolicy
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @instance
+                     * @param {google.iam.v1.IGetIamPolicyRequest} request GetIamPolicyRequest message or plain object
+                     * @returns {Promise<google.iam.v1.Policy>} Promise
+                     * @variation 2
+                     */
+    
+                    /**
+                     * Callback as used by {@link google.iam.v1.IAMPolicy#testIamPermissions}.
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @typedef TestIamPermissionsCallback
+                     * @type {function}
+                     * @param {Error|null} error Error, if any
+                     * @param {google.iam.v1.TestIamPermissionsResponse} [response] TestIamPermissionsResponse
+                     */
+    
+                    /**
+                     * Calls TestIamPermissions.
+                     * @function testIamPermissions
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @instance
+                     * @param {google.iam.v1.ITestIamPermissionsRequest} request TestIamPermissionsRequest message or plain object
+                     * @param {google.iam.v1.IAMPolicy.TestIamPermissionsCallback} callback Node-style callback called with the error, if any, and TestIamPermissionsResponse
+                     * @returns {undefined}
+                     * @variation 1
+                     */
+                    Object.defineProperty(IAMPolicy.prototype.testIamPermissions = function testIamPermissions(request, callback) {
+                        return this.rpcCall(testIamPermissions, $root.google.iam.v1.TestIamPermissionsRequest, $root.google.iam.v1.TestIamPermissionsResponse, request, callback);
+                    }, "name", { value: "TestIamPermissions" });
+    
+                    /**
+                     * Calls TestIamPermissions.
+                     * @function testIamPermissions
+                     * @memberof google.iam.v1.IAMPolicy
+                     * @instance
+                     * @param {google.iam.v1.ITestIamPermissionsRequest} request TestIamPermissionsRequest message or plain object
+                     * @returns {Promise<google.iam.v1.TestIamPermissionsResponse>} Promise
+                     * @variation 2
+                     */
+    
+                    return IAMPolicy;
+                })();
+    
+                v1.SetIamPolicyRequest = (function() {
+    
+                    /**
+                     * Properties of a SetIamPolicyRequest.
+                     * @memberof google.iam.v1
+                     * @interface ISetIamPolicyRequest
+                     * @property {string|null} [resource] SetIamPolicyRequest resource
+                     * @property {google.iam.v1.IPolicy|null} [policy] SetIamPolicyRequest policy
+                     */
+    
+                    /**
+                     * Constructs a new SetIamPolicyRequest.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a SetIamPolicyRequest.
+                     * @implements ISetIamPolicyRequest
+                     * @constructor
+                     * @param {google.iam.v1.ISetIamPolicyRequest=} [properties] Properties to set
+                     */
+                    function SetIamPolicyRequest(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * SetIamPolicyRequest resource.
+                     * @member {string} resource
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @instance
+                     */
+                    SetIamPolicyRequest.prototype.resource = "";
+    
+                    /**
+                     * SetIamPolicyRequest policy.
+                     * @member {google.iam.v1.IPolicy|null|undefined} policy
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @instance
+                     */
+                    SetIamPolicyRequest.prototype.policy = null;
+    
+                    /**
+                     * Creates a new SetIamPolicyRequest instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.ISetIamPolicyRequest=} [properties] Properties to set
+                     * @returns {google.iam.v1.SetIamPolicyRequest} SetIamPolicyRequest instance
+                     */
+                    SetIamPolicyRequest.create = function create(properties) {
+                        return new SetIamPolicyRequest(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified SetIamPolicyRequest message. Does not implicitly {@link google.iam.v1.SetIamPolicyRequest.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.ISetIamPolicyRequest} message SetIamPolicyRequest message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    SetIamPolicyRequest.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.resource != null && Object.hasOwnProperty.call(message, "resource"))
+                            writer.uint32(/* id 1, wireType 2 =*/10).string(message.resource);
+                        if (message.policy != null && Object.hasOwnProperty.call(message, "policy"))
+                            $root.google.iam.v1.Policy.encode(message.policy, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified SetIamPolicyRequest message, length delimited. Does not implicitly {@link google.iam.v1.SetIamPolicyRequest.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.ISetIamPolicyRequest} message SetIamPolicyRequest message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    SetIamPolicyRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a SetIamPolicyRequest message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.SetIamPolicyRequest} SetIamPolicyRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    SetIamPolicyRequest.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.SetIamPolicyRequest();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.resource = reader.string();
+                                break;
+                            case 2:
+                                message.policy = $root.google.iam.v1.Policy.decode(reader, reader.uint32());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a SetIamPolicyRequest message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.SetIamPolicyRequest} SetIamPolicyRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    SetIamPolicyRequest.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a SetIamPolicyRequest message.
+                     * @function verify
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    SetIamPolicyRequest.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.resource != null && message.hasOwnProperty("resource"))
+                            if (!$util.isString(message.resource))
+                                return "resource: string expected";
+                        if (message.policy != null && message.hasOwnProperty("policy")) {
+                            var error = $root.google.iam.v1.Policy.verify(message.policy);
+                            if (error)
+                                return "policy." + error;
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a SetIamPolicyRequest message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.SetIamPolicyRequest} SetIamPolicyRequest
+                     */
+                    SetIamPolicyRequest.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.SetIamPolicyRequest)
+                            return object;
+                        var message = new $root.google.iam.v1.SetIamPolicyRequest();
+                        if (object.resource != null)
+                            message.resource = String(object.resource);
+                        if (object.policy != null) {
+                            if (typeof object.policy !== "object")
+                                throw TypeError(".google.iam.v1.SetIamPolicyRequest.policy: object expected");
+                            message.policy = $root.google.iam.v1.Policy.fromObject(object.policy);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a SetIamPolicyRequest message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.SetIamPolicyRequest} message SetIamPolicyRequest
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    SetIamPolicyRequest.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.resource = "";
+                            object.policy = null;
+                        }
+                        if (message.resource != null && message.hasOwnProperty("resource"))
+                            object.resource = message.resource;
+                        if (message.policy != null && message.hasOwnProperty("policy"))
+                            object.policy = $root.google.iam.v1.Policy.toObject(message.policy, options);
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this SetIamPolicyRequest to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.SetIamPolicyRequest
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    SetIamPolicyRequest.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return SetIamPolicyRequest;
+                })();
+    
+                v1.GetIamPolicyRequest = (function() {
+    
+                    /**
+                     * Properties of a GetIamPolicyRequest.
+                     * @memberof google.iam.v1
+                     * @interface IGetIamPolicyRequest
+                     * @property {string|null} [resource] GetIamPolicyRequest resource
+                     * @property {google.iam.v1.IGetPolicyOptions|null} [options] GetIamPolicyRequest options
+                     */
+    
+                    /**
+                     * Constructs a new GetIamPolicyRequest.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a GetIamPolicyRequest.
+                     * @implements IGetIamPolicyRequest
+                     * @constructor
+                     * @param {google.iam.v1.IGetIamPolicyRequest=} [properties] Properties to set
+                     */
+                    function GetIamPolicyRequest(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * GetIamPolicyRequest resource.
+                     * @member {string} resource
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @instance
+                     */
+                    GetIamPolicyRequest.prototype.resource = "";
+    
+                    /**
+                     * GetIamPolicyRequest options.
+                     * @member {google.iam.v1.IGetPolicyOptions|null|undefined} options
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @instance
+                     */
+                    GetIamPolicyRequest.prototype.options = null;
+    
+                    /**
+                     * Creates a new GetIamPolicyRequest instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.IGetIamPolicyRequest=} [properties] Properties to set
+                     * @returns {google.iam.v1.GetIamPolicyRequest} GetIamPolicyRequest instance
+                     */
+                    GetIamPolicyRequest.create = function create(properties) {
+                        return new GetIamPolicyRequest(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified GetIamPolicyRequest message. Does not implicitly {@link google.iam.v1.GetIamPolicyRequest.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.IGetIamPolicyRequest} message GetIamPolicyRequest message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    GetIamPolicyRequest.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.resource != null && Object.hasOwnProperty.call(message, "resource"))
+                            writer.uint32(/* id 1, wireType 2 =*/10).string(message.resource);
+                        if (message.options != null && Object.hasOwnProperty.call(message, "options"))
+                            $root.google.iam.v1.GetPolicyOptions.encode(message.options, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified GetIamPolicyRequest message, length delimited. Does not implicitly {@link google.iam.v1.GetIamPolicyRequest.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.IGetIamPolicyRequest} message GetIamPolicyRequest message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    GetIamPolicyRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a GetIamPolicyRequest message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.GetIamPolicyRequest} GetIamPolicyRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    GetIamPolicyRequest.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.GetIamPolicyRequest();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.resource = reader.string();
+                                break;
+                            case 2:
+                                message.options = $root.google.iam.v1.GetPolicyOptions.decode(reader, reader.uint32());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a GetIamPolicyRequest message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.GetIamPolicyRequest} GetIamPolicyRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    GetIamPolicyRequest.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a GetIamPolicyRequest message.
+                     * @function verify
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    GetIamPolicyRequest.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.resource != null && message.hasOwnProperty("resource"))
+                            if (!$util.isString(message.resource))
+                                return "resource: string expected";
+                        if (message.options != null && message.hasOwnProperty("options")) {
+                            var error = $root.google.iam.v1.GetPolicyOptions.verify(message.options);
+                            if (error)
+                                return "options." + error;
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a GetIamPolicyRequest message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.GetIamPolicyRequest} GetIamPolicyRequest
+                     */
+                    GetIamPolicyRequest.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.GetIamPolicyRequest)
+                            return object;
+                        var message = new $root.google.iam.v1.GetIamPolicyRequest();
+                        if (object.resource != null)
+                            message.resource = String(object.resource);
+                        if (object.options != null) {
+                            if (typeof object.options !== "object")
+                                throw TypeError(".google.iam.v1.GetIamPolicyRequest.options: object expected");
+                            message.options = $root.google.iam.v1.GetPolicyOptions.fromObject(object.options);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a GetIamPolicyRequest message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @static
+                     * @param {google.iam.v1.GetIamPolicyRequest} message GetIamPolicyRequest
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    GetIamPolicyRequest.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.resource = "";
+                            object.options = null;
+                        }
+                        if (message.resource != null && message.hasOwnProperty("resource"))
+                            object.resource = message.resource;
+                        if (message.options != null && message.hasOwnProperty("options"))
+                            object.options = $root.google.iam.v1.GetPolicyOptions.toObject(message.options, options);
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this GetIamPolicyRequest to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.GetIamPolicyRequest
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    GetIamPolicyRequest.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return GetIamPolicyRequest;
+                })();
+    
+                v1.TestIamPermissionsRequest = (function() {
+    
+                    /**
+                     * Properties of a TestIamPermissionsRequest.
+                     * @memberof google.iam.v1
+                     * @interface ITestIamPermissionsRequest
+                     * @property {string|null} [resource] TestIamPermissionsRequest resource
+                     * @property {Array.<string>|null} [permissions] TestIamPermissionsRequest permissions
+                     */
+    
+                    /**
+                     * Constructs a new TestIamPermissionsRequest.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a TestIamPermissionsRequest.
+                     * @implements ITestIamPermissionsRequest
+                     * @constructor
+                     * @param {google.iam.v1.ITestIamPermissionsRequest=} [properties] Properties to set
+                     */
+                    function TestIamPermissionsRequest(properties) {
+                        this.permissions = [];
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * TestIamPermissionsRequest resource.
+                     * @member {string} resource
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @instance
+                     */
+                    TestIamPermissionsRequest.prototype.resource = "";
+    
+                    /**
+                     * TestIamPermissionsRequest permissions.
+                     * @member {Array.<string>} permissions
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @instance
+                     */
+                    TestIamPermissionsRequest.prototype.permissions = $util.emptyArray;
+    
+                    /**
+                     * Creates a new TestIamPermissionsRequest instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {google.iam.v1.ITestIamPermissionsRequest=} [properties] Properties to set
+                     * @returns {google.iam.v1.TestIamPermissionsRequest} TestIamPermissionsRequest instance
+                     */
+                    TestIamPermissionsRequest.create = function create(properties) {
+                        return new TestIamPermissionsRequest(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified TestIamPermissionsRequest message. Does not implicitly {@link google.iam.v1.TestIamPermissionsRequest.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {google.iam.v1.ITestIamPermissionsRequest} message TestIamPermissionsRequest message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    TestIamPermissionsRequest.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.resource != null && Object.hasOwnProperty.call(message, "resource"))
+                            writer.uint32(/* id 1, wireType 2 =*/10).string(message.resource);
+                        if (message.permissions != null && message.permissions.length)
+                            for (var i = 0; i < message.permissions.length; ++i)
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.permissions[i]);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified TestIamPermissionsRequest message, length delimited. Does not implicitly {@link google.iam.v1.TestIamPermissionsRequest.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {google.iam.v1.ITestIamPermissionsRequest} message TestIamPermissionsRequest message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    TestIamPermissionsRequest.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a TestIamPermissionsRequest message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.TestIamPermissionsRequest} TestIamPermissionsRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    TestIamPermissionsRequest.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.TestIamPermissionsRequest();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.resource = reader.string();
+                                break;
+                            case 2:
+                                if (!(message.permissions && message.permissions.length))
+                                    message.permissions = [];
+                                message.permissions.push(reader.string());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a TestIamPermissionsRequest message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.TestIamPermissionsRequest} TestIamPermissionsRequest
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    TestIamPermissionsRequest.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a TestIamPermissionsRequest message.
+                     * @function verify
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    TestIamPermissionsRequest.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.resource != null && message.hasOwnProperty("resource"))
+                            if (!$util.isString(message.resource))
+                                return "resource: string expected";
+                        if (message.permissions != null && message.hasOwnProperty("permissions")) {
+                            if (!Array.isArray(message.permissions))
+                                return "permissions: array expected";
+                            for (var i = 0; i < message.permissions.length; ++i)
+                                if (!$util.isString(message.permissions[i]))
+                                    return "permissions: string[] expected";
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a TestIamPermissionsRequest message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.TestIamPermissionsRequest} TestIamPermissionsRequest
+                     */
+                    TestIamPermissionsRequest.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.TestIamPermissionsRequest)
+                            return object;
+                        var message = new $root.google.iam.v1.TestIamPermissionsRequest();
+                        if (object.resource != null)
+                            message.resource = String(object.resource);
+                        if (object.permissions) {
+                            if (!Array.isArray(object.permissions))
+                                throw TypeError(".google.iam.v1.TestIamPermissionsRequest.permissions: array expected");
+                            message.permissions = [];
+                            for (var i = 0; i < object.permissions.length; ++i)
+                                message.permissions[i] = String(object.permissions[i]);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a TestIamPermissionsRequest message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @static
+                     * @param {google.iam.v1.TestIamPermissionsRequest} message TestIamPermissionsRequest
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    TestIamPermissionsRequest.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.arrays || options.defaults)
+                            object.permissions = [];
+                        if (options.defaults)
+                            object.resource = "";
+                        if (message.resource != null && message.hasOwnProperty("resource"))
+                            object.resource = message.resource;
+                        if (message.permissions && message.permissions.length) {
+                            object.permissions = [];
+                            for (var j = 0; j < message.permissions.length; ++j)
+                                object.permissions[j] = message.permissions[j];
+                        }
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this TestIamPermissionsRequest to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.TestIamPermissionsRequest
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    TestIamPermissionsRequest.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return TestIamPermissionsRequest;
+                })();
+    
+                v1.TestIamPermissionsResponse = (function() {
+    
+                    /**
+                     * Properties of a TestIamPermissionsResponse.
+                     * @memberof google.iam.v1
+                     * @interface ITestIamPermissionsResponse
+                     * @property {Array.<string>|null} [permissions] TestIamPermissionsResponse permissions
+                     */
+    
+                    /**
+                     * Constructs a new TestIamPermissionsResponse.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a TestIamPermissionsResponse.
+                     * @implements ITestIamPermissionsResponse
+                     * @constructor
+                     * @param {google.iam.v1.ITestIamPermissionsResponse=} [properties] Properties to set
+                     */
+                    function TestIamPermissionsResponse(properties) {
+                        this.permissions = [];
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * TestIamPermissionsResponse permissions.
+                     * @member {Array.<string>} permissions
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @instance
+                     */
+                    TestIamPermissionsResponse.prototype.permissions = $util.emptyArray;
+    
+                    /**
+                     * Creates a new TestIamPermissionsResponse instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {google.iam.v1.ITestIamPermissionsResponse=} [properties] Properties to set
+                     * @returns {google.iam.v1.TestIamPermissionsResponse} TestIamPermissionsResponse instance
+                     */
+                    TestIamPermissionsResponse.create = function create(properties) {
+                        return new TestIamPermissionsResponse(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified TestIamPermissionsResponse message. Does not implicitly {@link google.iam.v1.TestIamPermissionsResponse.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {google.iam.v1.ITestIamPermissionsResponse} message TestIamPermissionsResponse message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    TestIamPermissionsResponse.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.permissions != null && message.permissions.length)
+                            for (var i = 0; i < message.permissions.length; ++i)
+                                writer.uint32(/* id 1, wireType 2 =*/10).string(message.permissions[i]);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified TestIamPermissionsResponse message, length delimited. Does not implicitly {@link google.iam.v1.TestIamPermissionsResponse.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {google.iam.v1.ITestIamPermissionsResponse} message TestIamPermissionsResponse message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    TestIamPermissionsResponse.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a TestIamPermissionsResponse message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.TestIamPermissionsResponse} TestIamPermissionsResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    TestIamPermissionsResponse.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.TestIamPermissionsResponse();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                if (!(message.permissions && message.permissions.length))
+                                    message.permissions = [];
+                                message.permissions.push(reader.string());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a TestIamPermissionsResponse message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.TestIamPermissionsResponse} TestIamPermissionsResponse
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    TestIamPermissionsResponse.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a TestIamPermissionsResponse message.
+                     * @function verify
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    TestIamPermissionsResponse.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.permissions != null && message.hasOwnProperty("permissions")) {
+                            if (!Array.isArray(message.permissions))
+                                return "permissions: array expected";
+                            for (var i = 0; i < message.permissions.length; ++i)
+                                if (!$util.isString(message.permissions[i]))
+                                    return "permissions: string[] expected";
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a TestIamPermissionsResponse message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.TestIamPermissionsResponse} TestIamPermissionsResponse
+                     */
+                    TestIamPermissionsResponse.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.TestIamPermissionsResponse)
+                            return object;
+                        var message = new $root.google.iam.v1.TestIamPermissionsResponse();
+                        if (object.permissions) {
+                            if (!Array.isArray(object.permissions))
+                                throw TypeError(".google.iam.v1.TestIamPermissionsResponse.permissions: array expected");
+                            message.permissions = [];
+                            for (var i = 0; i < object.permissions.length; ++i)
+                                message.permissions[i] = String(object.permissions[i]);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a TestIamPermissionsResponse message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @static
+                     * @param {google.iam.v1.TestIamPermissionsResponse} message TestIamPermissionsResponse
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    TestIamPermissionsResponse.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.arrays || options.defaults)
+                            object.permissions = [];
+                        if (message.permissions && message.permissions.length) {
+                            object.permissions = [];
+                            for (var j = 0; j < message.permissions.length; ++j)
+                                object.permissions[j] = message.permissions[j];
+                        }
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this TestIamPermissionsResponse to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.TestIamPermissionsResponse
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    TestIamPermissionsResponse.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return TestIamPermissionsResponse;
+                })();
+    
+                v1.GetPolicyOptions = (function() {
+    
+                    /**
+                     * Properties of a GetPolicyOptions.
+                     * @memberof google.iam.v1
+                     * @interface IGetPolicyOptions
+                     * @property {number|null} [requestedPolicyVersion] GetPolicyOptions requestedPolicyVersion
+                     */
+    
+                    /**
+                     * Constructs a new GetPolicyOptions.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a GetPolicyOptions.
+                     * @implements IGetPolicyOptions
+                     * @constructor
+                     * @param {google.iam.v1.IGetPolicyOptions=} [properties] Properties to set
+                     */
+                    function GetPolicyOptions(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * GetPolicyOptions requestedPolicyVersion.
+                     * @member {number} requestedPolicyVersion
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @instance
+                     */
+                    GetPolicyOptions.prototype.requestedPolicyVersion = 0;
+    
+                    /**
+                     * Creates a new GetPolicyOptions instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {google.iam.v1.IGetPolicyOptions=} [properties] Properties to set
+                     * @returns {google.iam.v1.GetPolicyOptions} GetPolicyOptions instance
+                     */
+                    GetPolicyOptions.create = function create(properties) {
+                        return new GetPolicyOptions(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified GetPolicyOptions message. Does not implicitly {@link google.iam.v1.GetPolicyOptions.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {google.iam.v1.IGetPolicyOptions} message GetPolicyOptions message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    GetPolicyOptions.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.requestedPolicyVersion != null && Object.hasOwnProperty.call(message, "requestedPolicyVersion"))
+                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.requestedPolicyVersion);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified GetPolicyOptions message, length delimited. Does not implicitly {@link google.iam.v1.GetPolicyOptions.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {google.iam.v1.IGetPolicyOptions} message GetPolicyOptions message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    GetPolicyOptions.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a GetPolicyOptions message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.GetPolicyOptions} GetPolicyOptions
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    GetPolicyOptions.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.GetPolicyOptions();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.requestedPolicyVersion = reader.int32();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a GetPolicyOptions message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.GetPolicyOptions} GetPolicyOptions
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    GetPolicyOptions.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a GetPolicyOptions message.
+                     * @function verify
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    GetPolicyOptions.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.requestedPolicyVersion != null && message.hasOwnProperty("requestedPolicyVersion"))
+                            if (!$util.isInteger(message.requestedPolicyVersion))
+                                return "requestedPolicyVersion: integer expected";
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a GetPolicyOptions message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.GetPolicyOptions} GetPolicyOptions
+                     */
+                    GetPolicyOptions.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.GetPolicyOptions)
+                            return object;
+                        var message = new $root.google.iam.v1.GetPolicyOptions();
+                        if (object.requestedPolicyVersion != null)
+                            message.requestedPolicyVersion = object.requestedPolicyVersion | 0;
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a GetPolicyOptions message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @static
+                     * @param {google.iam.v1.GetPolicyOptions} message GetPolicyOptions
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    GetPolicyOptions.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults)
+                            object.requestedPolicyVersion = 0;
+                        if (message.requestedPolicyVersion != null && message.hasOwnProperty("requestedPolicyVersion"))
+                            object.requestedPolicyVersion = message.requestedPolicyVersion;
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this GetPolicyOptions to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.GetPolicyOptions
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    GetPolicyOptions.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return GetPolicyOptions;
+                })();
+    
+                v1.Policy = (function() {
+    
+                    /**
+                     * Properties of a Policy.
+                     * @memberof google.iam.v1
+                     * @interface IPolicy
+                     * @property {number|null} [version] Policy version
+                     * @property {Array.<google.iam.v1.IBinding>|null} [bindings] Policy bindings
+                     * @property {Uint8Array|null} [etag] Policy etag
+                     */
+    
+                    /**
+                     * Constructs a new Policy.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a Policy.
+                     * @implements IPolicy
+                     * @constructor
+                     * @param {google.iam.v1.IPolicy=} [properties] Properties to set
+                     */
+                    function Policy(properties) {
+                        this.bindings = [];
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * Policy version.
+                     * @member {number} version
+                     * @memberof google.iam.v1.Policy
+                     * @instance
+                     */
+                    Policy.prototype.version = 0;
+    
+                    /**
+                     * Policy bindings.
+                     * @member {Array.<google.iam.v1.IBinding>} bindings
+                     * @memberof google.iam.v1.Policy
+                     * @instance
+                     */
+                    Policy.prototype.bindings = $util.emptyArray;
+    
+                    /**
+                     * Policy etag.
+                     * @member {Uint8Array} etag
+                     * @memberof google.iam.v1.Policy
+                     * @instance
+                     */
+                    Policy.prototype.etag = $util.newBuffer([]);
+    
+                    /**
+                     * Creates a new Policy instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {google.iam.v1.IPolicy=} [properties] Properties to set
+                     * @returns {google.iam.v1.Policy} Policy instance
+                     */
+                    Policy.create = function create(properties) {
+                        return new Policy(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified Policy message. Does not implicitly {@link google.iam.v1.Policy.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {google.iam.v1.IPolicy} message Policy message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Policy.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.version != null && Object.hasOwnProperty.call(message, "version"))
+                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.version);
+                        if (message.etag != null && Object.hasOwnProperty.call(message, "etag"))
+                            writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.etag);
+                        if (message.bindings != null && message.bindings.length)
+                            for (var i = 0; i < message.bindings.length; ++i)
+                                $root.google.iam.v1.Binding.encode(message.bindings[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified Policy message, length delimited. Does not implicitly {@link google.iam.v1.Policy.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {google.iam.v1.IPolicy} message Policy message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Policy.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a Policy message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.Policy} Policy
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Policy.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.Policy();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.version = reader.int32();
+                                break;
+                            case 4:
+                                if (!(message.bindings && message.bindings.length))
+                                    message.bindings = [];
+                                message.bindings.push($root.google.iam.v1.Binding.decode(reader, reader.uint32()));
+                                break;
+                            case 3:
+                                message.etag = reader.bytes();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a Policy message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.Policy} Policy
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Policy.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a Policy message.
+                     * @function verify
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    Policy.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.version != null && message.hasOwnProperty("version"))
+                            if (!$util.isInteger(message.version))
+                                return "version: integer expected";
+                        if (message.bindings != null && message.hasOwnProperty("bindings")) {
+                            if (!Array.isArray(message.bindings))
+                                return "bindings: array expected";
+                            for (var i = 0; i < message.bindings.length; ++i) {
+                                var error = $root.google.iam.v1.Binding.verify(message.bindings[i]);
+                                if (error)
+                                    return "bindings." + error;
+                            }
+                        }
+                        if (message.etag != null && message.hasOwnProperty("etag"))
+                            if (!(message.etag && typeof message.etag.length === "number" || $util.isString(message.etag)))
+                                return "etag: buffer expected";
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a Policy message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.Policy} Policy
+                     */
+                    Policy.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.Policy)
+                            return object;
+                        var message = new $root.google.iam.v1.Policy();
+                        if (object.version != null)
+                            message.version = object.version | 0;
+                        if (object.bindings) {
+                            if (!Array.isArray(object.bindings))
+                                throw TypeError(".google.iam.v1.Policy.bindings: array expected");
+                            message.bindings = [];
+                            for (var i = 0; i < object.bindings.length; ++i) {
+                                if (typeof object.bindings[i] !== "object")
+                                    throw TypeError(".google.iam.v1.Policy.bindings: object expected");
+                                message.bindings[i] = $root.google.iam.v1.Binding.fromObject(object.bindings[i]);
+                            }
+                        }
+                        if (object.etag != null)
+                            if (typeof object.etag === "string")
+                                $util.base64.decode(object.etag, message.etag = $util.newBuffer($util.base64.length(object.etag)), 0);
+                            else if (object.etag.length)
+                                message.etag = object.etag;
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a Policy message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.Policy
+                     * @static
+                     * @param {google.iam.v1.Policy} message Policy
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    Policy.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.arrays || options.defaults)
+                            object.bindings = [];
+                        if (options.defaults) {
+                            object.version = 0;
+                            if (options.bytes === String)
+                                object.etag = "";
+                            else {
+                                object.etag = [];
+                                if (options.bytes !== Array)
+                                    object.etag = $util.newBuffer(object.etag);
+                            }
+                        }
+                        if (message.version != null && message.hasOwnProperty("version"))
+                            object.version = message.version;
+                        if (message.etag != null && message.hasOwnProperty("etag"))
+                            object.etag = options.bytes === String ? $util.base64.encode(message.etag, 0, message.etag.length) : options.bytes === Array ? Array.prototype.slice.call(message.etag) : message.etag;
+                        if (message.bindings && message.bindings.length) {
+                            object.bindings = [];
+                            for (var j = 0; j < message.bindings.length; ++j)
+                                object.bindings[j] = $root.google.iam.v1.Binding.toObject(message.bindings[j], options);
+                        }
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this Policy to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.Policy
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    Policy.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return Policy;
+                })();
+    
+                v1.Binding = (function() {
+    
+                    /**
+                     * Properties of a Binding.
+                     * @memberof google.iam.v1
+                     * @interface IBinding
+                     * @property {string|null} [role] Binding role
+                     * @property {Array.<string>|null} [members] Binding members
+                     * @property {google.type.IExpr|null} [condition] Binding condition
+                     */
+    
+                    /**
+                     * Constructs a new Binding.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a Binding.
+                     * @implements IBinding
+                     * @constructor
+                     * @param {google.iam.v1.IBinding=} [properties] Properties to set
+                     */
+                    function Binding(properties) {
+                        this.members = [];
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * Binding role.
+                     * @member {string} role
+                     * @memberof google.iam.v1.Binding
+                     * @instance
+                     */
+                    Binding.prototype.role = "";
+    
+                    /**
+                     * Binding members.
+                     * @member {Array.<string>} members
+                     * @memberof google.iam.v1.Binding
+                     * @instance
+                     */
+                    Binding.prototype.members = $util.emptyArray;
+    
+                    /**
+                     * Binding condition.
+                     * @member {google.type.IExpr|null|undefined} condition
+                     * @memberof google.iam.v1.Binding
+                     * @instance
+                     */
+                    Binding.prototype.condition = null;
+    
+                    /**
+                     * Creates a new Binding instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {google.iam.v1.IBinding=} [properties] Properties to set
+                     * @returns {google.iam.v1.Binding} Binding instance
+                     */
+                    Binding.create = function create(properties) {
+                        return new Binding(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified Binding message. Does not implicitly {@link google.iam.v1.Binding.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {google.iam.v1.IBinding} message Binding message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Binding.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.role != null && Object.hasOwnProperty.call(message, "role"))
+                            writer.uint32(/* id 1, wireType 2 =*/10).string(message.role);
+                        if (message.members != null && message.members.length)
+                            for (var i = 0; i < message.members.length; ++i)
+                                writer.uint32(/* id 2, wireType 2 =*/18).string(message.members[i]);
+                        if (message.condition != null && Object.hasOwnProperty.call(message, "condition"))
+                            $root.google.type.Expr.encode(message.condition, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified Binding message, length delimited. Does not implicitly {@link google.iam.v1.Binding.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {google.iam.v1.IBinding} message Binding message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    Binding.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a Binding message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.Binding} Binding
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Binding.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.Binding();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.role = reader.string();
+                                break;
+                            case 2:
+                                if (!(message.members && message.members.length))
+                                    message.members = [];
+                                message.members.push(reader.string());
+                                break;
+                            case 3:
+                                message.condition = $root.google.type.Expr.decode(reader, reader.uint32());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a Binding message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.Binding} Binding
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    Binding.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a Binding message.
+                     * @function verify
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    Binding.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.role != null && message.hasOwnProperty("role"))
+                            if (!$util.isString(message.role))
+                                return "role: string expected";
+                        if (message.members != null && message.hasOwnProperty("members")) {
+                            if (!Array.isArray(message.members))
+                                return "members: array expected";
+                            for (var i = 0; i < message.members.length; ++i)
+                                if (!$util.isString(message.members[i]))
+                                    return "members: string[] expected";
+                        }
+                        if (message.condition != null && message.hasOwnProperty("condition")) {
+                            var error = $root.google.type.Expr.verify(message.condition);
+                            if (error)
+                                return "condition." + error;
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a Binding message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.Binding} Binding
+                     */
+                    Binding.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.Binding)
+                            return object;
+                        var message = new $root.google.iam.v1.Binding();
+                        if (object.role != null)
+                            message.role = String(object.role);
+                        if (object.members) {
+                            if (!Array.isArray(object.members))
+                                throw TypeError(".google.iam.v1.Binding.members: array expected");
+                            message.members = [];
+                            for (var i = 0; i < object.members.length; ++i)
+                                message.members[i] = String(object.members[i]);
+                        }
+                        if (object.condition != null) {
+                            if (typeof object.condition !== "object")
+                                throw TypeError(".google.iam.v1.Binding.condition: object expected");
+                            message.condition = $root.google.type.Expr.fromObject(object.condition);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a Binding message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.Binding
+                     * @static
+                     * @param {google.iam.v1.Binding} message Binding
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    Binding.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.arrays || options.defaults)
+                            object.members = [];
+                        if (options.defaults) {
+                            object.role = "";
+                            object.condition = null;
+                        }
+                        if (message.role != null && message.hasOwnProperty("role"))
+                            object.role = message.role;
+                        if (message.members && message.members.length) {
+                            object.members = [];
+                            for (var j = 0; j < message.members.length; ++j)
+                                object.members[j] = message.members[j];
+                        }
+                        if (message.condition != null && message.hasOwnProperty("condition"))
+                            object.condition = $root.google.type.Expr.toObject(message.condition, options);
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this Binding to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.Binding
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    Binding.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return Binding;
+                })();
+    
+                v1.PolicyDelta = (function() {
+    
+                    /**
+                     * Properties of a PolicyDelta.
+                     * @memberof google.iam.v1
+                     * @interface IPolicyDelta
+                     * @property {Array.<google.iam.v1.IBindingDelta>|null} [bindingDeltas] PolicyDelta bindingDeltas
+                     * @property {Array.<google.iam.v1.IAuditConfigDelta>|null} [auditConfigDeltas] PolicyDelta auditConfigDeltas
+                     */
+    
+                    /**
+                     * Constructs a new PolicyDelta.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a PolicyDelta.
+                     * @implements IPolicyDelta
+                     * @constructor
+                     * @param {google.iam.v1.IPolicyDelta=} [properties] Properties to set
+                     */
+                    function PolicyDelta(properties) {
+                        this.bindingDeltas = [];
+                        this.auditConfigDeltas = [];
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * PolicyDelta bindingDeltas.
+                     * @member {Array.<google.iam.v1.IBindingDelta>} bindingDeltas
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @instance
+                     */
+                    PolicyDelta.prototype.bindingDeltas = $util.emptyArray;
+    
+                    /**
+                     * PolicyDelta auditConfigDeltas.
+                     * @member {Array.<google.iam.v1.IAuditConfigDelta>} auditConfigDeltas
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @instance
+                     */
+                    PolicyDelta.prototype.auditConfigDeltas = $util.emptyArray;
+    
+                    /**
+                     * Creates a new PolicyDelta instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {google.iam.v1.IPolicyDelta=} [properties] Properties to set
+                     * @returns {google.iam.v1.PolicyDelta} PolicyDelta instance
+                     */
+                    PolicyDelta.create = function create(properties) {
+                        return new PolicyDelta(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified PolicyDelta message. Does not implicitly {@link google.iam.v1.PolicyDelta.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {google.iam.v1.IPolicyDelta} message PolicyDelta message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    PolicyDelta.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.bindingDeltas != null && message.bindingDeltas.length)
+                            for (var i = 0; i < message.bindingDeltas.length; ++i)
+                                $root.google.iam.v1.BindingDelta.encode(message.bindingDeltas[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+                        if (message.auditConfigDeltas != null && message.auditConfigDeltas.length)
+                            for (var i = 0; i < message.auditConfigDeltas.length; ++i)
+                                $root.google.iam.v1.AuditConfigDelta.encode(message.auditConfigDeltas[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified PolicyDelta message, length delimited. Does not implicitly {@link google.iam.v1.PolicyDelta.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {google.iam.v1.IPolicyDelta} message PolicyDelta message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    PolicyDelta.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a PolicyDelta message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.PolicyDelta} PolicyDelta
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    PolicyDelta.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.PolicyDelta();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                if (!(message.bindingDeltas && message.bindingDeltas.length))
+                                    message.bindingDeltas = [];
+                                message.bindingDeltas.push($root.google.iam.v1.BindingDelta.decode(reader, reader.uint32()));
+                                break;
+                            case 2:
+                                if (!(message.auditConfigDeltas && message.auditConfigDeltas.length))
+                                    message.auditConfigDeltas = [];
+                                message.auditConfigDeltas.push($root.google.iam.v1.AuditConfigDelta.decode(reader, reader.uint32()));
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a PolicyDelta message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.PolicyDelta} PolicyDelta
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    PolicyDelta.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a PolicyDelta message.
+                     * @function verify
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    PolicyDelta.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.bindingDeltas != null && message.hasOwnProperty("bindingDeltas")) {
+                            if (!Array.isArray(message.bindingDeltas))
+                                return "bindingDeltas: array expected";
+                            for (var i = 0; i < message.bindingDeltas.length; ++i) {
+                                var error = $root.google.iam.v1.BindingDelta.verify(message.bindingDeltas[i]);
+                                if (error)
+                                    return "bindingDeltas." + error;
+                            }
+                        }
+                        if (message.auditConfigDeltas != null && message.hasOwnProperty("auditConfigDeltas")) {
+                            if (!Array.isArray(message.auditConfigDeltas))
+                                return "auditConfigDeltas: array expected";
+                            for (var i = 0; i < message.auditConfigDeltas.length; ++i) {
+                                var error = $root.google.iam.v1.AuditConfigDelta.verify(message.auditConfigDeltas[i]);
+                                if (error)
+                                    return "auditConfigDeltas." + error;
+                            }
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a PolicyDelta message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.PolicyDelta} PolicyDelta
+                     */
+                    PolicyDelta.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.PolicyDelta)
+                            return object;
+                        var message = new $root.google.iam.v1.PolicyDelta();
+                        if (object.bindingDeltas) {
+                            if (!Array.isArray(object.bindingDeltas))
+                                throw TypeError(".google.iam.v1.PolicyDelta.bindingDeltas: array expected");
+                            message.bindingDeltas = [];
+                            for (var i = 0; i < object.bindingDeltas.length; ++i) {
+                                if (typeof object.bindingDeltas[i] !== "object")
+                                    throw TypeError(".google.iam.v1.PolicyDelta.bindingDeltas: object expected");
+                                message.bindingDeltas[i] = $root.google.iam.v1.BindingDelta.fromObject(object.bindingDeltas[i]);
+                            }
+                        }
+                        if (object.auditConfigDeltas) {
+                            if (!Array.isArray(object.auditConfigDeltas))
+                                throw TypeError(".google.iam.v1.PolicyDelta.auditConfigDeltas: array expected");
+                            message.auditConfigDeltas = [];
+                            for (var i = 0; i < object.auditConfigDeltas.length; ++i) {
+                                if (typeof object.auditConfigDeltas[i] !== "object")
+                                    throw TypeError(".google.iam.v1.PolicyDelta.auditConfigDeltas: object expected");
+                                message.auditConfigDeltas[i] = $root.google.iam.v1.AuditConfigDelta.fromObject(object.auditConfigDeltas[i]);
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a PolicyDelta message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @static
+                     * @param {google.iam.v1.PolicyDelta} message PolicyDelta
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    PolicyDelta.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.arrays || options.defaults) {
+                            object.bindingDeltas = [];
+                            object.auditConfigDeltas = [];
+                        }
+                        if (message.bindingDeltas && message.bindingDeltas.length) {
+                            object.bindingDeltas = [];
+                            for (var j = 0; j < message.bindingDeltas.length; ++j)
+                                object.bindingDeltas[j] = $root.google.iam.v1.BindingDelta.toObject(message.bindingDeltas[j], options);
+                        }
+                        if (message.auditConfigDeltas && message.auditConfigDeltas.length) {
+                            object.auditConfigDeltas = [];
+                            for (var j = 0; j < message.auditConfigDeltas.length; ++j)
+                                object.auditConfigDeltas[j] = $root.google.iam.v1.AuditConfigDelta.toObject(message.auditConfigDeltas[j], options);
+                        }
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this PolicyDelta to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.PolicyDelta
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    PolicyDelta.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    return PolicyDelta;
+                })();
+    
+                v1.BindingDelta = (function() {
+    
+                    /**
+                     * Properties of a BindingDelta.
+                     * @memberof google.iam.v1
+                     * @interface IBindingDelta
+                     * @property {google.iam.v1.BindingDelta.Action|null} [action] BindingDelta action
+                     * @property {string|null} [role] BindingDelta role
+                     * @property {string|null} [member] BindingDelta member
+                     * @property {google.type.IExpr|null} [condition] BindingDelta condition
+                     */
+    
+                    /**
+                     * Constructs a new BindingDelta.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents a BindingDelta.
+                     * @implements IBindingDelta
+                     * @constructor
+                     * @param {google.iam.v1.IBindingDelta=} [properties] Properties to set
+                     */
+                    function BindingDelta(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * BindingDelta action.
+                     * @member {google.iam.v1.BindingDelta.Action} action
+                     * @memberof google.iam.v1.BindingDelta
+                     * @instance
+                     */
+                    BindingDelta.prototype.action = 0;
+    
+                    /**
+                     * BindingDelta role.
+                     * @member {string} role
+                     * @memberof google.iam.v1.BindingDelta
+                     * @instance
+                     */
+                    BindingDelta.prototype.role = "";
+    
+                    /**
+                     * BindingDelta member.
+                     * @member {string} member
+                     * @memberof google.iam.v1.BindingDelta
+                     * @instance
+                     */
+                    BindingDelta.prototype.member = "";
+    
+                    /**
+                     * BindingDelta condition.
+                     * @member {google.type.IExpr|null|undefined} condition
+                     * @memberof google.iam.v1.BindingDelta
+                     * @instance
+                     */
+                    BindingDelta.prototype.condition = null;
+    
+                    /**
+                     * Creates a new BindingDelta instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {google.iam.v1.IBindingDelta=} [properties] Properties to set
+                     * @returns {google.iam.v1.BindingDelta} BindingDelta instance
+                     */
+                    BindingDelta.create = function create(properties) {
+                        return new BindingDelta(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified BindingDelta message. Does not implicitly {@link google.iam.v1.BindingDelta.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {google.iam.v1.IBindingDelta} message BindingDelta message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    BindingDelta.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.action != null && Object.hasOwnProperty.call(message, "action"))
+                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.action);
+                        if (message.role != null && Object.hasOwnProperty.call(message, "role"))
+                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.role);
+                        if (message.member != null && Object.hasOwnProperty.call(message, "member"))
+                            writer.uint32(/* id 3, wireType 2 =*/26).string(message.member);
+                        if (message.condition != null && Object.hasOwnProperty.call(message, "condition"))
+                            $root.google.type.Expr.encode(message.condition, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified BindingDelta message, length delimited. Does not implicitly {@link google.iam.v1.BindingDelta.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {google.iam.v1.IBindingDelta} message BindingDelta message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    BindingDelta.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes a BindingDelta message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.BindingDelta} BindingDelta
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    BindingDelta.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.BindingDelta();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.action = reader.int32();
+                                break;
+                            case 2:
+                                message.role = reader.string();
+                                break;
+                            case 3:
+                                message.member = reader.string();
+                                break;
+                            case 4:
+                                message.condition = $root.google.type.Expr.decode(reader, reader.uint32());
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes a BindingDelta message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.BindingDelta} BindingDelta
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    BindingDelta.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies a BindingDelta message.
+                     * @function verify
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    BindingDelta.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.action != null && message.hasOwnProperty("action"))
+                            switch (message.action) {
+                            default:
+                                return "action: enum value expected";
+                            case 0:
+                            case 1:
+                            case 2:
+                                break;
+                            }
+                        if (message.role != null && message.hasOwnProperty("role"))
+                            if (!$util.isString(message.role))
+                                return "role: string expected";
+                        if (message.member != null && message.hasOwnProperty("member"))
+                            if (!$util.isString(message.member))
+                                return "member: string expected";
+                        if (message.condition != null && message.hasOwnProperty("condition")) {
+                            var error = $root.google.type.Expr.verify(message.condition);
+                            if (error)
+                                return "condition." + error;
+                        }
+                        return null;
+                    };
+    
+                    /**
+                     * Creates a BindingDelta message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.BindingDelta} BindingDelta
+                     */
+                    BindingDelta.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.BindingDelta)
+                            return object;
+                        var message = new $root.google.iam.v1.BindingDelta();
+                        switch (object.action) {
+                        case "ACTION_UNSPECIFIED":
+                        case 0:
+                            message.action = 0;
+                            break;
+                        case "ADD":
+                        case 1:
+                            message.action = 1;
+                            break;
+                        case "REMOVE":
+                        case 2:
+                            message.action = 2;
+                            break;
+                        }
+                        if (object.role != null)
+                            message.role = String(object.role);
+                        if (object.member != null)
+                            message.member = String(object.member);
+                        if (object.condition != null) {
+                            if (typeof object.condition !== "object")
+                                throw TypeError(".google.iam.v1.BindingDelta.condition: object expected");
+                            message.condition = $root.google.type.Expr.fromObject(object.condition);
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from a BindingDelta message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.BindingDelta
+                     * @static
+                     * @param {google.iam.v1.BindingDelta} message BindingDelta
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    BindingDelta.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.action = options.enums === String ? "ACTION_UNSPECIFIED" : 0;
+                            object.role = "";
+                            object.member = "";
+                            object.condition = null;
+                        }
+                        if (message.action != null && message.hasOwnProperty("action"))
+                            object.action = options.enums === String ? $root.google.iam.v1.BindingDelta.Action[message.action] : message.action;
+                        if (message.role != null && message.hasOwnProperty("role"))
+                            object.role = message.role;
+                        if (message.member != null && message.hasOwnProperty("member"))
+                            object.member = message.member;
+                        if (message.condition != null && message.hasOwnProperty("condition"))
+                            object.condition = $root.google.type.Expr.toObject(message.condition, options);
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this BindingDelta to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.BindingDelta
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    BindingDelta.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    /**
+                     * Action enum.
+                     * @name google.iam.v1.BindingDelta.Action
+                     * @enum {number}
+                     * @property {number} ACTION_UNSPECIFIED=0 ACTION_UNSPECIFIED value
+                     * @property {number} ADD=1 ADD value
+                     * @property {number} REMOVE=2 REMOVE value
+                     */
+                    BindingDelta.Action = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "ACTION_UNSPECIFIED"] = 0;
+                        values[valuesById[1] = "ADD"] = 1;
+                        values[valuesById[2] = "REMOVE"] = 2;
+                        return values;
+                    })();
+    
+                    return BindingDelta;
+                })();
+    
+                v1.AuditConfigDelta = (function() {
+    
+                    /**
+                     * Properties of an AuditConfigDelta.
+                     * @memberof google.iam.v1
+                     * @interface IAuditConfigDelta
+                     * @property {google.iam.v1.AuditConfigDelta.Action|null} [action] AuditConfigDelta action
+                     * @property {string|null} [service] AuditConfigDelta service
+                     * @property {string|null} [exemptedMember] AuditConfigDelta exemptedMember
+                     * @property {string|null} [logType] AuditConfigDelta logType
+                     */
+    
+                    /**
+                     * Constructs a new AuditConfigDelta.
+                     * @memberof google.iam.v1
+                     * @classdesc Represents an AuditConfigDelta.
+                     * @implements IAuditConfigDelta
+                     * @constructor
+                     * @param {google.iam.v1.IAuditConfigDelta=} [properties] Properties to set
+                     */
+                    function AuditConfigDelta(properties) {
+                        if (properties)
+                            for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                                if (properties[keys[i]] != null)
+                                    this[keys[i]] = properties[keys[i]];
+                    }
+    
+                    /**
+                     * AuditConfigDelta action.
+                     * @member {google.iam.v1.AuditConfigDelta.Action} action
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @instance
+                     */
+                    AuditConfigDelta.prototype.action = 0;
+    
+                    /**
+                     * AuditConfigDelta service.
+                     * @member {string} service
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @instance
+                     */
+                    AuditConfigDelta.prototype.service = "";
+    
+                    /**
+                     * AuditConfigDelta exemptedMember.
+                     * @member {string} exemptedMember
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @instance
+                     */
+                    AuditConfigDelta.prototype.exemptedMember = "";
+    
+                    /**
+                     * AuditConfigDelta logType.
+                     * @member {string} logType
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @instance
+                     */
+                    AuditConfigDelta.prototype.logType = "";
+    
+                    /**
+                     * Creates a new AuditConfigDelta instance using the specified properties.
+                     * @function create
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {google.iam.v1.IAuditConfigDelta=} [properties] Properties to set
+                     * @returns {google.iam.v1.AuditConfigDelta} AuditConfigDelta instance
+                     */
+                    AuditConfigDelta.create = function create(properties) {
+                        return new AuditConfigDelta(properties);
+                    };
+    
+                    /**
+                     * Encodes the specified AuditConfigDelta message. Does not implicitly {@link google.iam.v1.AuditConfigDelta.verify|verify} messages.
+                     * @function encode
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {google.iam.v1.IAuditConfigDelta} message AuditConfigDelta message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    AuditConfigDelta.encode = function encode(message, writer) {
+                        if (!writer)
+                            writer = $Writer.create();
+                        if (message.action != null && Object.hasOwnProperty.call(message, "action"))
+                            writer.uint32(/* id 1, wireType 0 =*/8).int32(message.action);
+                        if (message.service != null && Object.hasOwnProperty.call(message, "service"))
+                            writer.uint32(/* id 2, wireType 2 =*/18).string(message.service);
+                        if (message.exemptedMember != null && Object.hasOwnProperty.call(message, "exemptedMember"))
+                            writer.uint32(/* id 3, wireType 2 =*/26).string(message.exemptedMember);
+                        if (message.logType != null && Object.hasOwnProperty.call(message, "logType"))
+                            writer.uint32(/* id 4, wireType 2 =*/34).string(message.logType);
+                        return writer;
+                    };
+    
+                    /**
+                     * Encodes the specified AuditConfigDelta message, length delimited. Does not implicitly {@link google.iam.v1.AuditConfigDelta.verify|verify} messages.
+                     * @function encodeDelimited
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {google.iam.v1.IAuditConfigDelta} message AuditConfigDelta message or plain object to encode
+                     * @param {$protobuf.Writer} [writer] Writer to encode to
+                     * @returns {$protobuf.Writer} Writer
+                     */
+                    AuditConfigDelta.encodeDelimited = function encodeDelimited(message, writer) {
+                        return this.encode(message, writer).ldelim();
+                    };
+    
+                    /**
+                     * Decodes an AuditConfigDelta message from the specified reader or buffer.
+                     * @function decode
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @param {number} [length] Message length if known beforehand
+                     * @returns {google.iam.v1.AuditConfigDelta} AuditConfigDelta
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    AuditConfigDelta.decode = function decode(reader, length) {
+                        if (!(reader instanceof $Reader))
+                            reader = $Reader.create(reader);
+                        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.iam.v1.AuditConfigDelta();
+                        while (reader.pos < end) {
+                            var tag = reader.uint32();
+                            switch (tag >>> 3) {
+                            case 1:
+                                message.action = reader.int32();
+                                break;
+                            case 2:
+                                message.service = reader.string();
+                                break;
+                            case 3:
+                                message.exemptedMember = reader.string();
+                                break;
+                            case 4:
+                                message.logType = reader.string();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                            }
+                        }
+                        return message;
+                    };
+    
+                    /**
+                     * Decodes an AuditConfigDelta message from the specified reader or buffer, length delimited.
+                     * @function decodeDelimited
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                     * @returns {google.iam.v1.AuditConfigDelta} AuditConfigDelta
+                     * @throws {Error} If the payload is not a reader or valid buffer
+                     * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                     */
+                    AuditConfigDelta.decodeDelimited = function decodeDelimited(reader) {
+                        if (!(reader instanceof $Reader))
+                            reader = new $Reader(reader);
+                        return this.decode(reader, reader.uint32());
+                    };
+    
+                    /**
+                     * Verifies an AuditConfigDelta message.
+                     * @function verify
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {Object.<string,*>} message Plain object to verify
+                     * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                     */
+                    AuditConfigDelta.verify = function verify(message) {
+                        if (typeof message !== "object" || message === null)
+                            return "object expected";
+                        if (message.action != null && message.hasOwnProperty("action"))
+                            switch (message.action) {
+                            default:
+                                return "action: enum value expected";
+                            case 0:
+                            case 1:
+                            case 2:
+                                break;
+                            }
+                        if (message.service != null && message.hasOwnProperty("service"))
+                            if (!$util.isString(message.service))
+                                return "service: string expected";
+                        if (message.exemptedMember != null && message.hasOwnProperty("exemptedMember"))
+                            if (!$util.isString(message.exemptedMember))
+                                return "exemptedMember: string expected";
+                        if (message.logType != null && message.hasOwnProperty("logType"))
+                            if (!$util.isString(message.logType))
+                                return "logType: string expected";
+                        return null;
+                    };
+    
+                    /**
+                     * Creates an AuditConfigDelta message from a plain object. Also converts values to their respective internal types.
+                     * @function fromObject
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {Object.<string,*>} object Plain object
+                     * @returns {google.iam.v1.AuditConfigDelta} AuditConfigDelta
+                     */
+                    AuditConfigDelta.fromObject = function fromObject(object) {
+                        if (object instanceof $root.google.iam.v1.AuditConfigDelta)
+                            return object;
+                        var message = new $root.google.iam.v1.AuditConfigDelta();
+                        switch (object.action) {
+                        case "ACTION_UNSPECIFIED":
+                        case 0:
+                            message.action = 0;
+                            break;
+                        case "ADD":
+                        case 1:
+                            message.action = 1;
+                            break;
+                        case "REMOVE":
+                        case 2:
+                            message.action = 2;
+                            break;
+                        }
+                        if (object.service != null)
+                            message.service = String(object.service);
+                        if (object.exemptedMember != null)
+                            message.exemptedMember = String(object.exemptedMember);
+                        if (object.logType != null)
+                            message.logType = String(object.logType);
+                        return message;
+                    };
+    
+                    /**
+                     * Creates a plain object from an AuditConfigDelta message. Also converts values to other types if specified.
+                     * @function toObject
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @static
+                     * @param {google.iam.v1.AuditConfigDelta} message AuditConfigDelta
+                     * @param {$protobuf.IConversionOptions} [options] Conversion options
+                     * @returns {Object.<string,*>} Plain object
+                     */
+                    AuditConfigDelta.toObject = function toObject(message, options) {
+                        if (!options)
+                            options = {};
+                        var object = {};
+                        if (options.defaults) {
+                            object.action = options.enums === String ? "ACTION_UNSPECIFIED" : 0;
+                            object.service = "";
+                            object.exemptedMember = "";
+                            object.logType = "";
+                        }
+                        if (message.action != null && message.hasOwnProperty("action"))
+                            object.action = options.enums === String ? $root.google.iam.v1.AuditConfigDelta.Action[message.action] : message.action;
+                        if (message.service != null && message.hasOwnProperty("service"))
+                            object.service = message.service;
+                        if (message.exemptedMember != null && message.hasOwnProperty("exemptedMember"))
+                            object.exemptedMember = message.exemptedMember;
+                        if (message.logType != null && message.hasOwnProperty("logType"))
+                            object.logType = message.logType;
+                        return object;
+                    };
+    
+                    /**
+                     * Converts this AuditConfigDelta to JSON.
+                     * @function toJSON
+                     * @memberof google.iam.v1.AuditConfigDelta
+                     * @instance
+                     * @returns {Object.<string,*>} JSON object
+                     */
+                    AuditConfigDelta.prototype.toJSON = function toJSON() {
+                        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                    };
+    
+                    /**
+                     * Action enum.
+                     * @name google.iam.v1.AuditConfigDelta.Action
+                     * @enum {number}
+                     * @property {number} ACTION_UNSPECIFIED=0 ACTION_UNSPECIFIED value
+                     * @property {number} ADD=1 ADD value
+                     * @property {number} REMOVE=2 REMOVE value
+                     */
+                    AuditConfigDelta.Action = (function() {
+                        var valuesById = {}, values = Object.create(valuesById);
+                        values[valuesById[0] = "ACTION_UNSPECIFIED"] = 0;
+                        values[valuesById[1] = "ADD"] = 1;
+                        values[valuesById[2] = "REMOVE"] = 2;
+                        return values;
+                    })();
+    
+                    return AuditConfigDelta;
+                })();
+    
+                return v1;
+            })();
+    
+            return iam;
+        })();
+    
+        google.type = (function() {
+    
+            /**
+             * Namespace type.
+             * @memberof google
+             * @namespace
+             */
+            var type = {};
+    
+            type.Expr = (function() {
+    
+                /**
+                 * Properties of an Expr.
+                 * @memberof google.type
+                 * @interface IExpr
+                 * @property {string|null} [expression] Expr expression
+                 * @property {string|null} [title] Expr title
+                 * @property {string|null} [description] Expr description
+                 * @property {string|null} [location] Expr location
+                 */
+    
+                /**
+                 * Constructs a new Expr.
+                 * @memberof google.type
+                 * @classdesc Represents an Expr.
+                 * @implements IExpr
+                 * @constructor
+                 * @param {google.type.IExpr=} [properties] Properties to set
+                 */
+                function Expr(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+    
+                /**
+                 * Expr expression.
+                 * @member {string} expression
+                 * @memberof google.type.Expr
+                 * @instance
+                 */
+                Expr.prototype.expression = "";
+    
+                /**
+                 * Expr title.
+                 * @member {string} title
+                 * @memberof google.type.Expr
+                 * @instance
+                 */
+                Expr.prototype.title = "";
+    
+                /**
+                 * Expr description.
+                 * @member {string} description
+                 * @memberof google.type.Expr
+                 * @instance
+                 */
+                Expr.prototype.description = "";
+    
+                /**
+                 * Expr location.
+                 * @member {string} location
+                 * @memberof google.type.Expr
+                 * @instance
+                 */
+                Expr.prototype.location = "";
+    
+                /**
+                 * Creates a new Expr instance using the specified properties.
+                 * @function create
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {google.type.IExpr=} [properties] Properties to set
+                 * @returns {google.type.Expr} Expr instance
+                 */
+                Expr.create = function create(properties) {
+                    return new Expr(properties);
+                };
+    
+                /**
+                 * Encodes the specified Expr message. Does not implicitly {@link google.type.Expr.verify|verify} messages.
+                 * @function encode
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {google.type.IExpr} message Expr message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Expr.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.expression != null && Object.hasOwnProperty.call(message, "expression"))
+                        writer.uint32(/* id 1, wireType 2 =*/10).string(message.expression);
+                    if (message.title != null && Object.hasOwnProperty.call(message, "title"))
+                        writer.uint32(/* id 2, wireType 2 =*/18).string(message.title);
+                    if (message.description != null && Object.hasOwnProperty.call(message, "description"))
+                        writer.uint32(/* id 3, wireType 2 =*/26).string(message.description);
+                    if (message.location != null && Object.hasOwnProperty.call(message, "location"))
+                        writer.uint32(/* id 4, wireType 2 =*/34).string(message.location);
+                    return writer;
+                };
+    
+                /**
+                 * Encodes the specified Expr message, length delimited. Does not implicitly {@link google.type.Expr.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {google.type.IExpr} message Expr message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                Expr.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+    
+                /**
+                 * Decodes an Expr message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {google.type.Expr} Expr
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Expr.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.google.type.Expr();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                        case 1:
+                            message.expression = reader.string();
+                            break;
+                        case 2:
+                            message.title = reader.string();
+                            break;
+                        case 3:
+                            message.description = reader.string();
+                            break;
+                        case 4:
+                            message.location = reader.string();
+                            break;
+                        default:
+                            reader.skipType(tag & 7);
+                            break;
+                        }
+                    }
+                    return message;
+                };
+    
+                /**
+                 * Decodes an Expr message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {google.type.Expr} Expr
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                Expr.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+    
+                /**
+                 * Verifies an Expr message.
+                 * @function verify
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                Expr.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.expression != null && message.hasOwnProperty("expression"))
+                        if (!$util.isString(message.expression))
+                            return "expression: string expected";
+                    if (message.title != null && message.hasOwnProperty("title"))
+                        if (!$util.isString(message.title))
+                            return "title: string expected";
+                    if (message.description != null && message.hasOwnProperty("description"))
+                        if (!$util.isString(message.description))
+                            return "description: string expected";
+                    if (message.location != null && message.hasOwnProperty("location"))
+                        if (!$util.isString(message.location))
+                            return "location: string expected";
+                    return null;
+                };
+    
+                /**
+                 * Creates an Expr message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {google.type.Expr} Expr
+                 */
+                Expr.fromObject = function fromObject(object) {
+                    if (object instanceof $root.google.type.Expr)
+                        return object;
+                    var message = new $root.google.type.Expr();
+                    if (object.expression != null)
+                        message.expression = String(object.expression);
+                    if (object.title != null)
+                        message.title = String(object.title);
+                    if (object.description != null)
+                        message.description = String(object.description);
+                    if (object.location != null)
+                        message.location = String(object.location);
+                    return message;
+                };
+    
+                /**
+                 * Creates a plain object from an Expr message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof google.type.Expr
+                 * @static
+                 * @param {google.type.Expr} message Expr
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                Expr.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.expression = "";
+                        object.title = "";
+                        object.description = "";
+                        object.location = "";
+                    }
+                    if (message.expression != null && message.hasOwnProperty("expression"))
+                        object.expression = message.expression;
+                    if (message.title != null && message.hasOwnProperty("title"))
+                        object.title = message.title;
+                    if (message.description != null && message.hasOwnProperty("description"))
+                        object.description = message.description;
+                    if (message.location != null && message.hasOwnProperty("location"))
+                        object.location = message.location;
+                    return object;
+                };
+    
+                /**
+                 * Converts this Expr to JSON.
+                 * @function toJSON
+                 * @memberof google.type.Expr
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                Expr.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+    
+                return Expr;
+            })();
+    
+            return type;
+        })();
+    
+        return google;
+    })();
+
+    return $root;
+});
diff --git a/protos/protos.json b/protos/protos.json
new file mode 100644
index 0000000000000000000000000000000000000000..9497779533cccfd0ef9f512773c381438704f8e5
--- /dev/null
+++ b/protos/protos.json
@@ -0,0 +1,2674 @@
+{
+  "nested": {
+    "google": {
+      "nested": {
+        "cloud": {
+          "nested": {
+            "iot": {
+              "nested": {
+                "v1": {
+                  "options": {
+                    "cc_enable_arenas": true,
+                    "go_package": "google.golang.org/genproto/googleapis/cloud/iot/v1;iot",
+                    "java_multiple_files": true,
+                    "java_outer_classname": "ResourcesProto",
+                    "java_package": "com.google.cloud.iot.v1"
+                  },
+                  "nested": {
+                    "DeviceManager": {
+                      "options": {
+                        "(google.api.default_host)": "cloudiot.googleapis.com",
+                        "(google.api.oauth_scopes)": "https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloudiot"
+                      },
+                      "methods": {
+                        "CreateDeviceRegistry": {
+                          "requestType": "CreateDeviceRegistryRequest",
+                          "responseType": "DeviceRegistry",
+                          "options": {
+                            "(google.api.http).post": "/v1/{parent=projects/*/locations/*}/registries",
+                            "(google.api.http).body": "device_registry",
+                            "(google.api.method_signature)": "parent,device_registry"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{parent=projects/*/locations/*}/registries",
+                                "body": "device_registry"
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "parent,device_registry"
+                            }
+                          ]
+                        },
+                        "GetDeviceRegistry": {
+                          "requestType": "GetDeviceRegistryRequest",
+                          "responseType": "DeviceRegistry",
+                          "options": {
+                            "(google.api.http).get": "/v1/{name=projects/*/locations/*/registries/*}",
+                            "(google.api.method_signature)": "name"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "get": "/v1/{name=projects/*/locations/*/registries/*}"
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name"
+                            }
+                          ]
+                        },
+                        "UpdateDeviceRegistry": {
+                          "requestType": "UpdateDeviceRegistryRequest",
+                          "responseType": "DeviceRegistry",
+                          "options": {
+                            "(google.api.http).patch": "/v1/{device_registry.name=projects/*/locations/*/registries/*}",
+                            "(google.api.http).body": "device_registry",
+                            "(google.api.method_signature)": "device_registry,update_mask"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "patch": "/v1/{device_registry.name=projects/*/locations/*/registries/*}",
+                                "body": "device_registry"
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "device_registry,update_mask"
+                            }
+                          ]
+                        },
+                        "DeleteDeviceRegistry": {
+                          "requestType": "DeleteDeviceRegistryRequest",
+                          "responseType": "google.protobuf.Empty",
+                          "options": {
+                            "(google.api.http).delete": "/v1/{name=projects/*/locations/*/registries/*}",
+                            "(google.api.method_signature)": "name"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "delete": "/v1/{name=projects/*/locations/*/registries/*}"
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name"
+                            }
+                          ]
+                        },
+                        "ListDeviceRegistries": {
+                          "requestType": "ListDeviceRegistriesRequest",
+                          "responseType": "ListDeviceRegistriesResponse",
+                          "options": {
+                            "(google.api.http).get": "/v1/{parent=projects/*/locations/*}/registries",
+                            "(google.api.method_signature)": "parent"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "get": "/v1/{parent=projects/*/locations/*}/registries"
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "parent"
+                            }
+                          ]
+                        },
+                        "CreateDevice": {
+                          "requestType": "CreateDeviceRequest",
+                          "responseType": "Device",
+                          "options": {
+                            "(google.api.http).post": "/v1/{parent=projects/*/locations/*/registries/*}/devices",
+                            "(google.api.http).body": "device",
+                            "(google.api.method_signature)": "parent,device"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{parent=projects/*/locations/*/registries/*}/devices",
+                                "body": "device"
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "parent,device"
+                            }
+                          ]
+                        },
+                        "GetDevice": {
+                          "requestType": "GetDeviceRequest",
+                          "responseType": "Device",
+                          "options": {
+                            "(google.api.http).get": "/v1/{name=projects/*/locations/*/registries/*/devices/*}",
+                            "(google.api.http).additional_bindings.get": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}",
+                            "(google.api.method_signature)": "name"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "get": "/v1/{name=projects/*/locations/*/registries/*/devices/*}",
+                                "additional_bindings": {
+                                  "get": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name"
+                            }
+                          ]
+                        },
+                        "UpdateDevice": {
+                          "requestType": "UpdateDeviceRequest",
+                          "responseType": "Device",
+                          "options": {
+                            "(google.api.http).patch": "/v1/{device.name=projects/*/locations/*/registries/*/devices/*}",
+                            "(google.api.http).body": "device",
+                            "(google.api.http).additional_bindings.patch": "/v1/{device.name=projects/*/locations/*/registries/*/groups/*/devices/*}",
+                            "(google.api.http).additional_bindings.body": "device",
+                            "(google.api.method_signature)": "device,update_mask"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "patch": "/v1/{device.name=projects/*/locations/*/registries/*/devices/*}",
+                                "body": "device",
+                                "additional_bindings": {
+                                  "patch": "/v1/{device.name=projects/*/locations/*/registries/*/groups/*/devices/*}",
+                                  "body": "device"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "device,update_mask"
+                            }
+                          ]
+                        },
+                        "DeleteDevice": {
+                          "requestType": "DeleteDeviceRequest",
+                          "responseType": "google.protobuf.Empty",
+                          "options": {
+                            "(google.api.http).delete": "/v1/{name=projects/*/locations/*/registries/*/devices/*}",
+                            "(google.api.method_signature)": "name"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "delete": "/v1/{name=projects/*/locations/*/registries/*/devices/*}"
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name"
+                            }
+                          ]
+                        },
+                        "ListDevices": {
+                          "requestType": "ListDevicesRequest",
+                          "responseType": "ListDevicesResponse",
+                          "options": {
+                            "(google.api.http).get": "/v1/{parent=projects/*/locations/*/registries/*}/devices",
+                            "(google.api.http).additional_bindings.get": "/v1/{parent=projects/*/locations/*/registries/*/groups/*}/devices",
+                            "(google.api.method_signature)": "parent"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "get": "/v1/{parent=projects/*/locations/*/registries/*}/devices",
+                                "additional_bindings": {
+                                  "get": "/v1/{parent=projects/*/locations/*/registries/*/groups/*}/devices"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "parent"
+                            }
+                          ]
+                        },
+                        "ModifyCloudToDeviceConfig": {
+                          "requestType": "ModifyCloudToDeviceConfigRequest",
+                          "responseType": "DeviceConfig",
+                          "options": {
+                            "(google.api.http).post": "/v1/{name=projects/*/locations/*/registries/*/devices/*}:modifyCloudToDeviceConfig",
+                            "(google.api.http).body": "*",
+                            "(google.api.http).additional_bindings.post": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}:modifyCloudToDeviceConfig",
+                            "(google.api.http).additional_bindings.body": "*",
+                            "(google.api.method_signature)": "name,binary_data"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{name=projects/*/locations/*/registries/*/devices/*}:modifyCloudToDeviceConfig",
+                                "body": "*",
+                                "additional_bindings": {
+                                  "post": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}:modifyCloudToDeviceConfig",
+                                  "body": "*"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name,binary_data"
+                            }
+                          ]
+                        },
+                        "ListDeviceConfigVersions": {
+                          "requestType": "ListDeviceConfigVersionsRequest",
+                          "responseType": "ListDeviceConfigVersionsResponse",
+                          "options": {
+                            "(google.api.http).get": "/v1/{name=projects/*/locations/*/registries/*/devices/*}/configVersions",
+                            "(google.api.http).additional_bindings.get": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}/configVersions",
+                            "(google.api.method_signature)": "name"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "get": "/v1/{name=projects/*/locations/*/registries/*/devices/*}/configVersions",
+                                "additional_bindings": {
+                                  "get": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}/configVersions"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name"
+                            }
+                          ]
+                        },
+                        "ListDeviceStates": {
+                          "requestType": "ListDeviceStatesRequest",
+                          "responseType": "ListDeviceStatesResponse",
+                          "options": {
+                            "(google.api.http).get": "/v1/{name=projects/*/locations/*/registries/*/devices/*}/states",
+                            "(google.api.http).additional_bindings.get": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}/states",
+                            "(google.api.method_signature)": "name"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "get": "/v1/{name=projects/*/locations/*/registries/*/devices/*}/states",
+                                "additional_bindings": {
+                                  "get": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}/states"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name"
+                            }
+                          ]
+                        },
+                        "SetIamPolicy": {
+                          "requestType": "google.iam.v1.SetIamPolicyRequest",
+                          "responseType": "google.iam.v1.Policy",
+                          "options": {
+                            "(google.api.http).post": "/v1/{resource=projects/*/locations/*/registries/*}:setIamPolicy",
+                            "(google.api.http).body": "*",
+                            "(google.api.http).additional_bindings.post": "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:setIamPolicy",
+                            "(google.api.http).additional_bindings.body": "*",
+                            "(google.api.method_signature)": "resource,policy"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{resource=projects/*/locations/*/registries/*}:setIamPolicy",
+                                "body": "*",
+                                "additional_bindings": {
+                                  "post": "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:setIamPolicy",
+                                  "body": "*"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "resource,policy"
+                            }
+                          ]
+                        },
+                        "GetIamPolicy": {
+                          "requestType": "google.iam.v1.GetIamPolicyRequest",
+                          "responseType": "google.iam.v1.Policy",
+                          "options": {
+                            "(google.api.http).post": "/v1/{resource=projects/*/locations/*/registries/*}:getIamPolicy",
+                            "(google.api.http).body": "*",
+                            "(google.api.http).additional_bindings.post": "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:getIamPolicy",
+                            "(google.api.http).additional_bindings.body": "*",
+                            "(google.api.method_signature)": "resource"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{resource=projects/*/locations/*/registries/*}:getIamPolicy",
+                                "body": "*",
+                                "additional_bindings": {
+                                  "post": "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:getIamPolicy",
+                                  "body": "*"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "resource"
+                            }
+                          ]
+                        },
+                        "TestIamPermissions": {
+                          "requestType": "google.iam.v1.TestIamPermissionsRequest",
+                          "responseType": "google.iam.v1.TestIamPermissionsResponse",
+                          "options": {
+                            "(google.api.http).post": "/v1/{resource=projects/*/locations/*/registries/*}:testIamPermissions",
+                            "(google.api.http).body": "*",
+                            "(google.api.http).additional_bindings.post": "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:testIamPermissions",
+                            "(google.api.http).additional_bindings.body": "*",
+                            "(google.api.method_signature)": "resource,permissions"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{resource=projects/*/locations/*/registries/*}:testIamPermissions",
+                                "body": "*",
+                                "additional_bindings": {
+                                  "post": "/v1/{resource=projects/*/locations/*/registries/*/groups/*}:testIamPermissions",
+                                  "body": "*"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "resource,permissions"
+                            }
+                          ]
+                        },
+                        "SendCommandToDevice": {
+                          "requestType": "SendCommandToDeviceRequest",
+                          "responseType": "SendCommandToDeviceResponse",
+                          "options": {
+                            "(google.api.http).post": "/v1/{name=projects/*/locations/*/registries/*/devices/*}:sendCommandToDevice",
+                            "(google.api.http).body": "*",
+                            "(google.api.http).additional_bindings.post": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}:sendCommandToDevice",
+                            "(google.api.http).additional_bindings.body": "*",
+                            "(google.api.method_signature)": "name,binary_data,subfolder"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{name=projects/*/locations/*/registries/*/devices/*}:sendCommandToDevice",
+                                "body": "*",
+                                "additional_bindings": {
+                                  "post": "/v1/{name=projects/*/locations/*/registries/*/groups/*/devices/*}:sendCommandToDevice",
+                                  "body": "*"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "name,binary_data"
+                            },
+                            {
+                              "(google.api.method_signature)": "name,binary_data,subfolder"
+                            }
+                          ]
+                        },
+                        "BindDeviceToGateway": {
+                          "requestType": "BindDeviceToGatewayRequest",
+                          "responseType": "BindDeviceToGatewayResponse",
+                          "options": {
+                            "(google.api.http).post": "/v1/{parent=projects/*/locations/*/registries/*}:bindDeviceToGateway",
+                            "(google.api.http).body": "*",
+                            "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/locations/*/registries/*/groups/*}:bindDeviceToGateway",
+                            "(google.api.http).additional_bindings.body": "*",
+                            "(google.api.method_signature)": "parent,gateway_id,device_id"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{parent=projects/*/locations/*/registries/*}:bindDeviceToGateway",
+                                "body": "*",
+                                "additional_bindings": {
+                                  "post": "/v1/{parent=projects/*/locations/*/registries/*/groups/*}:bindDeviceToGateway",
+                                  "body": "*"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "parent,gateway_id,device_id"
+                            }
+                          ]
+                        },
+                        "UnbindDeviceFromGateway": {
+                          "requestType": "UnbindDeviceFromGatewayRequest",
+                          "responseType": "UnbindDeviceFromGatewayResponse",
+                          "options": {
+                            "(google.api.http).post": "/v1/{parent=projects/*/locations/*/registries/*}:unbindDeviceFromGateway",
+                            "(google.api.http).body": "*",
+                            "(google.api.http).additional_bindings.post": "/v1/{parent=projects/*/locations/*/registries/*/groups/*}:unbindDeviceFromGateway",
+                            "(google.api.http).additional_bindings.body": "*",
+                            "(google.api.method_signature)": "parent,gateway_id,device_id"
+                          },
+                          "parsedOptions": [
+                            {
+                              "(google.api.http)": {
+                                "post": "/v1/{parent=projects/*/locations/*/registries/*}:unbindDeviceFromGateway",
+                                "body": "*",
+                                "additional_bindings": {
+                                  "post": "/v1/{parent=projects/*/locations/*/registries/*/groups/*}:unbindDeviceFromGateway",
+                                  "body": "*"
+                                }
+                              }
+                            },
+                            {
+                              "(google.api.method_signature)": "parent,gateway_id,device_id"
+                            }
+                          ]
+                        }
+                      }
+                    },
+                    "CreateDeviceRegistryRequest": {
+                      "fields": {
+                        "parent": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "locations.googleapis.com/Location"
+                          }
+                        },
+                        "deviceRegistry": {
+                          "type": "DeviceRegistry",
+                          "id": 2,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        }
+                      }
+                    },
+                    "GetDeviceRegistryRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Registry"
+                          }
+                        }
+                      }
+                    },
+                    "DeleteDeviceRegistryRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Registry"
+                          }
+                        }
+                      }
+                    },
+                    "UpdateDeviceRegistryRequest": {
+                      "fields": {
+                        "deviceRegistry": {
+                          "type": "DeviceRegistry",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        },
+                        "updateMask": {
+                          "type": "google.protobuf.FieldMask",
+                          "id": 2,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        }
+                      }
+                    },
+                    "ListDeviceRegistriesRequest": {
+                      "fields": {
+                        "parent": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "locations.googleapis.com/Location"
+                          }
+                        },
+                        "pageSize": {
+                          "type": "int32",
+                          "id": 2
+                        },
+                        "pageToken": {
+                          "type": "string",
+                          "id": 3
+                        }
+                      }
+                    },
+                    "ListDeviceRegistriesResponse": {
+                      "fields": {
+                        "deviceRegistries": {
+                          "rule": "repeated",
+                          "type": "DeviceRegistry",
+                          "id": 1
+                        },
+                        "nextPageToken": {
+                          "type": "string",
+                          "id": 2
+                        }
+                      }
+                    },
+                    "CreateDeviceRequest": {
+                      "fields": {
+                        "parent": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Registry"
+                          }
+                        },
+                        "device": {
+                          "type": "Device",
+                          "id": 2,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        }
+                      }
+                    },
+                    "GetDeviceRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Device"
+                          }
+                        },
+                        "fieldMask": {
+                          "type": "google.protobuf.FieldMask",
+                          "id": 2
+                        }
+                      }
+                    },
+                    "UpdateDeviceRequest": {
+                      "fields": {
+                        "device": {
+                          "type": "Device",
+                          "id": 2,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        },
+                        "updateMask": {
+                          "type": "google.protobuf.FieldMask",
+                          "id": 3,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        }
+                      }
+                    },
+                    "DeleteDeviceRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Device"
+                          }
+                        }
+                      }
+                    },
+                    "ListDevicesRequest": {
+                      "fields": {
+                        "parent": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Registry"
+                          }
+                        },
+                        "deviceNumIds": {
+                          "rule": "repeated",
+                          "type": "uint64",
+                          "id": 2
+                        },
+                        "deviceIds": {
+                          "rule": "repeated",
+                          "type": "string",
+                          "id": 3
+                        },
+                        "fieldMask": {
+                          "type": "google.protobuf.FieldMask",
+                          "id": 4
+                        },
+                        "gatewayListOptions": {
+                          "type": "GatewayListOptions",
+                          "id": 6
+                        },
+                        "pageSize": {
+                          "type": "int32",
+                          "id": 100
+                        },
+                        "pageToken": {
+                          "type": "string",
+                          "id": 101
+                        }
+                      }
+                    },
+                    "GatewayListOptions": {
+                      "oneofs": {
+                        "filter": {
+                          "oneof": [
+                            "gatewayType",
+                            "associationsGatewayId",
+                            "associationsDeviceId"
+                          ]
+                        }
+                      },
+                      "fields": {
+                        "gatewayType": {
+                          "type": "GatewayType",
+                          "id": 1
+                        },
+                        "associationsGatewayId": {
+                          "type": "string",
+                          "id": 2
+                        },
+                        "associationsDeviceId": {
+                          "type": "string",
+                          "id": 3
+                        }
+                      }
+                    },
+                    "ListDevicesResponse": {
+                      "fields": {
+                        "devices": {
+                          "rule": "repeated",
+                          "type": "Device",
+                          "id": 1
+                        },
+                        "nextPageToken": {
+                          "type": "string",
+                          "id": 2
+                        }
+                      }
+                    },
+                    "ModifyCloudToDeviceConfigRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Device"
+                          }
+                        },
+                        "versionToUpdate": {
+                          "type": "int64",
+                          "id": 2
+                        },
+                        "binaryData": {
+                          "type": "bytes",
+                          "id": 3,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        }
+                      }
+                    },
+                    "ListDeviceConfigVersionsRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Device"
+                          }
+                        },
+                        "numVersions": {
+                          "type": "int32",
+                          "id": 2
+                        }
+                      }
+                    },
+                    "ListDeviceConfigVersionsResponse": {
+                      "fields": {
+                        "deviceConfigs": {
+                          "rule": "repeated",
+                          "type": "DeviceConfig",
+                          "id": 1
+                        }
+                      }
+                    },
+                    "ListDeviceStatesRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Device"
+                          }
+                        },
+                        "numStates": {
+                          "type": "int32",
+                          "id": 2
+                        }
+                      }
+                    },
+                    "ListDeviceStatesResponse": {
+                      "fields": {
+                        "deviceStates": {
+                          "rule": "repeated",
+                          "type": "DeviceState",
+                          "id": 1
+                        }
+                      }
+                    },
+                    "SendCommandToDeviceRequest": {
+                      "fields": {
+                        "name": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Device"
+                          }
+                        },
+                        "binaryData": {
+                          "type": "bytes",
+                          "id": 2,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        },
+                        "subfolder": {
+                          "type": "string",
+                          "id": 3
+                        }
+                      }
+                    },
+                    "SendCommandToDeviceResponse": {
+                      "fields": {}
+                    },
+                    "BindDeviceToGatewayRequest": {
+                      "fields": {
+                        "parent": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Registry"
+                          }
+                        },
+                        "gatewayId": {
+                          "type": "string",
+                          "id": 2,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        },
+                        "deviceId": {
+                          "type": "string",
+                          "id": 3,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        }
+                      }
+                    },
+                    "BindDeviceToGatewayResponse": {
+                      "fields": {}
+                    },
+                    "UnbindDeviceFromGatewayRequest": {
+                      "fields": {
+                        "parent": {
+                          "type": "string",
+                          "id": 1,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED",
+                            "(google.api.resource_reference).type": "cloudiot.googleapis.com/Registry"
+                          }
+                        },
+                        "gatewayId": {
+                          "type": "string",
+                          "id": 2,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        },
+                        "deviceId": {
+                          "type": "string",
+                          "id": 3,
+                          "options": {
+                            "(google.api.field_behavior)": "REQUIRED"
+                          }
+                        }
+                      }
+                    },
+                    "UnbindDeviceFromGatewayResponse": {
+                      "fields": {}
+                    },
+                    "Device": {
+                      "options": {
+                        "(google.api.resource).type": "cloudiot.googleapis.com/Device",
+                        "(google.api.resource).pattern": "projects/{project}/locations/{location}/registries/{registry}/devices/{device}"
+                      },
+                      "fields": {
+                        "id": {
+                          "type": "string",
+                          "id": 1
+                        },
+                        "name": {
+                          "type": "string",
+                          "id": 2
+                        },
+                        "numId": {
+                          "type": "uint64",
+                          "id": 3
+                        },
+                        "credentials": {
+                          "rule": "repeated",
+                          "type": "DeviceCredential",
+                          "id": 12
+                        },
+                        "lastHeartbeatTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 7
+                        },
+                        "lastEventTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 8
+                        },
+                        "lastStateTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 20
+                        },
+                        "lastConfigAckTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 14
+                        },
+                        "lastConfigSendTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 18
+                        },
+                        "blocked": {
+                          "type": "bool",
+                          "id": 19
+                        },
+                        "lastErrorTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 10
+                        },
+                        "lastErrorStatus": {
+                          "type": "google.rpc.Status",
+                          "id": 11
+                        },
+                        "config": {
+                          "type": "DeviceConfig",
+                          "id": 13
+                        },
+                        "state": {
+                          "type": "DeviceState",
+                          "id": 16
+                        },
+                        "logLevel": {
+                          "type": "LogLevel",
+                          "id": 21
+                        },
+                        "metadata": {
+                          "keyType": "string",
+                          "type": "string",
+                          "id": 17
+                        },
+                        "gatewayConfig": {
+                          "type": "GatewayConfig",
+                          "id": 24
+                        }
+                      }
+                    },
+                    "GatewayConfig": {
+                      "fields": {
+                        "gatewayType": {
+                          "type": "GatewayType",
+                          "id": 1
+                        },
+                        "gatewayAuthMethod": {
+                          "type": "GatewayAuthMethod",
+                          "id": 2
+                        },
+                        "lastAccessedGatewayId": {
+                          "type": "string",
+                          "id": 3
+                        },
+                        "lastAccessedGatewayTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 4
+                        }
+                      }
+                    },
+                    "DeviceRegistry": {
+                      "options": {
+                        "(google.api.resource).type": "cloudiot.googleapis.com/Registry",
+                        "(google.api.resource).pattern": "projects/{project}/locations/{location}/registries/{registry}"
+                      },
+                      "fields": {
+                        "id": {
+                          "type": "string",
+                          "id": 1
+                        },
+                        "name": {
+                          "type": "string",
+                          "id": 2
+                        },
+                        "eventNotificationConfigs": {
+                          "rule": "repeated",
+                          "type": "EventNotificationConfig",
+                          "id": 10
+                        },
+                        "stateNotificationConfig": {
+                          "type": "StateNotificationConfig",
+                          "id": 7
+                        },
+                        "mqttConfig": {
+                          "type": "MqttConfig",
+                          "id": 4
+                        },
+                        "httpConfig": {
+                          "type": "HttpConfig",
+                          "id": 9
+                        },
+                        "logLevel": {
+                          "type": "LogLevel",
+                          "id": 11
+                        },
+                        "credentials": {
+                          "rule": "repeated",
+                          "type": "RegistryCredential",
+                          "id": 8
+                        }
+                      }
+                    },
+                    "MqttConfig": {
+                      "fields": {
+                        "mqttEnabledState": {
+                          "type": "MqttState",
+                          "id": 1
+                        }
+                      }
+                    },
+                    "MqttState": {
+                      "values": {
+                        "MQTT_STATE_UNSPECIFIED": 0,
+                        "MQTT_ENABLED": 1,
+                        "MQTT_DISABLED": 2
+                      }
+                    },
+                    "HttpConfig": {
+                      "fields": {
+                        "httpEnabledState": {
+                          "type": "HttpState",
+                          "id": 1
+                        }
+                      }
+                    },
+                    "HttpState": {
+                      "values": {
+                        "HTTP_STATE_UNSPECIFIED": 0,
+                        "HTTP_ENABLED": 1,
+                        "HTTP_DISABLED": 2
+                      }
+                    },
+                    "LogLevel": {
+                      "values": {
+                        "LOG_LEVEL_UNSPECIFIED": 0,
+                        "NONE": 10,
+                        "ERROR": 20,
+                        "INFO": 30,
+                        "DEBUG": 40
+                      }
+                    },
+                    "GatewayType": {
+                      "values": {
+                        "GATEWAY_TYPE_UNSPECIFIED": 0,
+                        "GATEWAY": 1,
+                        "NON_GATEWAY": 2
+                      }
+                    },
+                    "GatewayAuthMethod": {
+                      "values": {
+                        "GATEWAY_AUTH_METHOD_UNSPECIFIED": 0,
+                        "ASSOCIATION_ONLY": 1,
+                        "DEVICE_AUTH_TOKEN_ONLY": 2,
+                        "ASSOCIATION_AND_DEVICE_AUTH_TOKEN": 3
+                      }
+                    },
+                    "EventNotificationConfig": {
+                      "fields": {
+                        "subfolderMatches": {
+                          "type": "string",
+                          "id": 2
+                        },
+                        "pubsubTopicName": {
+                          "type": "string",
+                          "id": 1
+                        }
+                      }
+                    },
+                    "StateNotificationConfig": {
+                      "fields": {
+                        "pubsubTopicName": {
+                          "type": "string",
+                          "id": 1
+                        }
+                      }
+                    },
+                    "RegistryCredential": {
+                      "oneofs": {
+                        "credential": {
+                          "oneof": [
+                            "publicKeyCertificate"
+                          ]
+                        }
+                      },
+                      "fields": {
+                        "publicKeyCertificate": {
+                          "type": "PublicKeyCertificate",
+                          "id": 1
+                        }
+                      }
+                    },
+                    "X509CertificateDetails": {
+                      "fields": {
+                        "issuer": {
+                          "type": "string",
+                          "id": 1
+                        },
+                        "subject": {
+                          "type": "string",
+                          "id": 2
+                        },
+                        "startTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 3
+                        },
+                        "expiryTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 4
+                        },
+                        "signatureAlgorithm": {
+                          "type": "string",
+                          "id": 5
+                        },
+                        "publicKeyType": {
+                          "type": "string",
+                          "id": 6
+                        }
+                      }
+                    },
+                    "PublicKeyCertificate": {
+                      "fields": {
+                        "format": {
+                          "type": "PublicKeyCertificateFormat",
+                          "id": 1
+                        },
+                        "certificate": {
+                          "type": "string",
+                          "id": 2
+                        },
+                        "x509Details": {
+                          "type": "X509CertificateDetails",
+                          "id": 3
+                        }
+                      }
+                    },
+                    "PublicKeyCertificateFormat": {
+                      "values": {
+                        "UNSPECIFIED_PUBLIC_KEY_CERTIFICATE_FORMAT": 0,
+                        "X509_CERTIFICATE_PEM": 1
+                      }
+                    },
+                    "DeviceCredential": {
+                      "oneofs": {
+                        "credential": {
+                          "oneof": [
+                            "publicKey"
+                          ]
+                        }
+                      },
+                      "fields": {
+                        "publicKey": {
+                          "type": "PublicKeyCredential",
+                          "id": 2
+                        },
+                        "expirationTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 6
+                        }
+                      }
+                    },
+                    "PublicKeyCredential": {
+                      "fields": {
+                        "format": {
+                          "type": "PublicKeyFormat",
+                          "id": 1
+                        },
+                        "key": {
+                          "type": "string",
+                          "id": 2
+                        }
+                      }
+                    },
+                    "PublicKeyFormat": {
+                      "values": {
+                        "UNSPECIFIED_PUBLIC_KEY_FORMAT": 0,
+                        "RSA_PEM": 3,
+                        "RSA_X509_PEM": 1,
+                        "ES256_PEM": 2,
+                        "ES256_X509_PEM": 4
+                      }
+                    },
+                    "DeviceConfig": {
+                      "fields": {
+                        "version": {
+                          "type": "int64",
+                          "id": 1
+                        },
+                        "cloudUpdateTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 2
+                        },
+                        "deviceAckTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 3
+                        },
+                        "binaryData": {
+                          "type": "bytes",
+                          "id": 4
+                        }
+                      }
+                    },
+                    "DeviceState": {
+                      "fields": {
+                        "updateTime": {
+                          "type": "google.protobuf.Timestamp",
+                          "id": 1
+                        },
+                        "binaryData": {
+                          "type": "bytes",
+                          "id": 2
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        },
+        "api": {
+          "options": {
+            "go_package": "google.golang.org/genproto/googleapis/api/annotations;annotations",
+            "java_multiple_files": true,
+            "java_outer_classname": "ResourceProto",
+            "java_package": "com.google.api",
+            "objc_class_prefix": "GAPI",
+            "cc_enable_arenas": true
+          },
+          "nested": {
+            "http": {
+              "type": "HttpRule",
+              "id": 72295728,
+              "extend": "google.protobuf.MethodOptions"
+            },
+            "Http": {
+              "fields": {
+                "rules": {
+                  "rule": "repeated",
+                  "type": "HttpRule",
+                  "id": 1
+                },
+                "fullyDecodeReservedExpansion": {
+                  "type": "bool",
+                  "id": 2
+                }
+              }
+            },
+            "HttpRule": {
+              "oneofs": {
+                "pattern": {
+                  "oneof": [
+                    "get",
+                    "put",
+                    "post",
+                    "delete",
+                    "patch",
+                    "custom"
+                  ]
+                }
+              },
+              "fields": {
+                "selector": {
+                  "type": "string",
+                  "id": 1
+                },
+                "get": {
+                  "type": "string",
+                  "id": 2
+                },
+                "put": {
+                  "type": "string",
+                  "id": 3
+                },
+                "post": {
+                  "type": "string",
+                  "id": 4
+                },
+                "delete": {
+                  "type": "string",
+                  "id": 5
+                },
+                "patch": {
+                  "type": "string",
+                  "id": 6
+                },
+                "custom": {
+                  "type": "CustomHttpPattern",
+                  "id": 8
+                },
+                "body": {
+                  "type": "string",
+                  "id": 7
+                },
+                "responseBody": {
+                  "type": "string",
+                  "id": 12
+                },
+                "additionalBindings": {
+                  "rule": "repeated",
+                  "type": "HttpRule",
+                  "id": 11
+                }
+              }
+            },
+            "CustomHttpPattern": {
+              "fields": {
+                "kind": {
+                  "type": "string",
+                  "id": 1
+                },
+                "path": {
+                  "type": "string",
+                  "id": 2
+                }
+              }
+            },
+            "methodSignature": {
+              "rule": "repeated",
+              "type": "string",
+              "id": 1051,
+              "extend": "google.protobuf.MethodOptions"
+            },
+            "defaultHost": {
+              "type": "string",
+              "id": 1049,
+              "extend": "google.protobuf.ServiceOptions"
+            },
+            "oauthScopes": {
+              "type": "string",
+              "id": 1050,
+              "extend": "google.protobuf.ServiceOptions"
+            },
+            "fieldBehavior": {
+              "rule": "repeated",
+              "type": "google.api.FieldBehavior",
+              "id": 1052,
+              "extend": "google.protobuf.FieldOptions"
+            },
+            "FieldBehavior": {
+              "values": {
+                "FIELD_BEHAVIOR_UNSPECIFIED": 0,
+                "OPTIONAL": 1,
+                "REQUIRED": 2,
+                "OUTPUT_ONLY": 3,
+                "INPUT_ONLY": 4,
+                "IMMUTABLE": 5,
+                "UNORDERED_LIST": 6,
+                "NON_EMPTY_DEFAULT": 7
+              }
+            },
+            "resourceReference": {
+              "type": "google.api.ResourceReference",
+              "id": 1055,
+              "extend": "google.protobuf.FieldOptions"
+            },
+            "resourceDefinition": {
+              "rule": "repeated",
+              "type": "google.api.ResourceDescriptor",
+              "id": 1053,
+              "extend": "google.protobuf.FileOptions"
+            },
+            "resource": {
+              "type": "google.api.ResourceDescriptor",
+              "id": 1053,
+              "extend": "google.protobuf.MessageOptions"
+            },
+            "ResourceDescriptor": {
+              "fields": {
+                "type": {
+                  "type": "string",
+                  "id": 1
+                },
+                "pattern": {
+                  "rule": "repeated",
+                  "type": "string",
+                  "id": 2
+                },
+                "nameField": {
+                  "type": "string",
+                  "id": 3
+                },
+                "history": {
+                  "type": "History",
+                  "id": 4
+                },
+                "plural": {
+                  "type": "string",
+                  "id": 5
+                },
+                "singular": {
+                  "type": "string",
+                  "id": 6
+                },
+                "style": {
+                  "rule": "repeated",
+                  "type": "Style",
+                  "id": 10
+                }
+              },
+              "nested": {
+                "History": {
+                  "values": {
+                    "HISTORY_UNSPECIFIED": 0,
+                    "ORIGINALLY_SINGLE_PATTERN": 1,
+                    "FUTURE_MULTI_PATTERN": 2
+                  }
+                },
+                "Style": {
+                  "values": {
+                    "STYLE_UNSPECIFIED": 0,
+                    "DECLARATIVE_FRIENDLY": 1
+                  }
+                }
+              }
+            },
+            "ResourceReference": {
+              "fields": {
+                "type": {
+                  "type": "string",
+                  "id": 1
+                },
+                "childType": {
+                  "type": "string",
+                  "id": 2
+                }
+              }
+            }
+          }
+        },
+        "protobuf": {
+          "options": {
+            "go_package": "google.golang.org/protobuf/types/descriptorpb",
+            "java_package": "com.google.protobuf",
+            "java_outer_classname": "DescriptorProtos",
+            "csharp_namespace": "Google.Protobuf.Reflection",
+            "objc_class_prefix": "GPB",
+            "cc_enable_arenas": true,
+            "optimize_for": "SPEED"
+          },
+          "nested": {
+            "FileDescriptorSet": {
+              "fields": {
+                "file": {
+                  "rule": "repeated",
+                  "type": "FileDescriptorProto",
+                  "id": 1
+                }
+              }
+            },
+            "FileDescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "package": {
+                  "type": "string",
+                  "id": 2
+                },
+                "dependency": {
+                  "rule": "repeated",
+                  "type": "string",
+                  "id": 3
+                },
+                "publicDependency": {
+                  "rule": "repeated",
+                  "type": "int32",
+                  "id": 10,
+                  "options": {
+                    "packed": false
+                  }
+                },
+                "weakDependency": {
+                  "rule": "repeated",
+                  "type": "int32",
+                  "id": 11,
+                  "options": {
+                    "packed": false
+                  }
+                },
+                "messageType": {
+                  "rule": "repeated",
+                  "type": "DescriptorProto",
+                  "id": 4
+                },
+                "enumType": {
+                  "rule": "repeated",
+                  "type": "EnumDescriptorProto",
+                  "id": 5
+                },
+                "service": {
+                  "rule": "repeated",
+                  "type": "ServiceDescriptorProto",
+                  "id": 6
+                },
+                "extension": {
+                  "rule": "repeated",
+                  "type": "FieldDescriptorProto",
+                  "id": 7
+                },
+                "options": {
+                  "type": "FileOptions",
+                  "id": 8
+                },
+                "sourceCodeInfo": {
+                  "type": "SourceCodeInfo",
+                  "id": 9
+                },
+                "syntax": {
+                  "type": "string",
+                  "id": 12
+                }
+              }
+            },
+            "DescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "field": {
+                  "rule": "repeated",
+                  "type": "FieldDescriptorProto",
+                  "id": 2
+                },
+                "extension": {
+                  "rule": "repeated",
+                  "type": "FieldDescriptorProto",
+                  "id": 6
+                },
+                "nestedType": {
+                  "rule": "repeated",
+                  "type": "DescriptorProto",
+                  "id": 3
+                },
+                "enumType": {
+                  "rule": "repeated",
+                  "type": "EnumDescriptorProto",
+                  "id": 4
+                },
+                "extensionRange": {
+                  "rule": "repeated",
+                  "type": "ExtensionRange",
+                  "id": 5
+                },
+                "oneofDecl": {
+                  "rule": "repeated",
+                  "type": "OneofDescriptorProto",
+                  "id": 8
+                },
+                "options": {
+                  "type": "MessageOptions",
+                  "id": 7
+                },
+                "reservedRange": {
+                  "rule": "repeated",
+                  "type": "ReservedRange",
+                  "id": 9
+                },
+                "reservedName": {
+                  "rule": "repeated",
+                  "type": "string",
+                  "id": 10
+                }
+              },
+              "nested": {
+                "ExtensionRange": {
+                  "fields": {
+                    "start": {
+                      "type": "int32",
+                      "id": 1
+                    },
+                    "end": {
+                      "type": "int32",
+                      "id": 2
+                    },
+                    "options": {
+                      "type": "ExtensionRangeOptions",
+                      "id": 3
+                    }
+                  }
+                },
+                "ReservedRange": {
+                  "fields": {
+                    "start": {
+                      "type": "int32",
+                      "id": 1
+                    },
+                    "end": {
+                      "type": "int32",
+                      "id": 2
+                    }
+                  }
+                }
+              }
+            },
+            "ExtensionRangeOptions": {
+              "fields": {
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ]
+            },
+            "FieldDescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "number": {
+                  "type": "int32",
+                  "id": 3
+                },
+                "label": {
+                  "type": "Label",
+                  "id": 4
+                },
+                "type": {
+                  "type": "Type",
+                  "id": 5
+                },
+                "typeName": {
+                  "type": "string",
+                  "id": 6
+                },
+                "extendee": {
+                  "type": "string",
+                  "id": 2
+                },
+                "defaultValue": {
+                  "type": "string",
+                  "id": 7
+                },
+                "oneofIndex": {
+                  "type": "int32",
+                  "id": 9
+                },
+                "jsonName": {
+                  "type": "string",
+                  "id": 10
+                },
+                "options": {
+                  "type": "FieldOptions",
+                  "id": 8
+                },
+                "proto3Optional": {
+                  "type": "bool",
+                  "id": 17
+                }
+              },
+              "nested": {
+                "Type": {
+                  "values": {
+                    "TYPE_DOUBLE": 1,
+                    "TYPE_FLOAT": 2,
+                    "TYPE_INT64": 3,
+                    "TYPE_UINT64": 4,
+                    "TYPE_INT32": 5,
+                    "TYPE_FIXED64": 6,
+                    "TYPE_FIXED32": 7,
+                    "TYPE_BOOL": 8,
+                    "TYPE_STRING": 9,
+                    "TYPE_GROUP": 10,
+                    "TYPE_MESSAGE": 11,
+                    "TYPE_BYTES": 12,
+                    "TYPE_UINT32": 13,
+                    "TYPE_ENUM": 14,
+                    "TYPE_SFIXED32": 15,
+                    "TYPE_SFIXED64": 16,
+                    "TYPE_SINT32": 17,
+                    "TYPE_SINT64": 18
+                  }
+                },
+                "Label": {
+                  "values": {
+                    "LABEL_OPTIONAL": 1,
+                    "LABEL_REQUIRED": 2,
+                    "LABEL_REPEATED": 3
+                  }
+                }
+              }
+            },
+            "OneofDescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "options": {
+                  "type": "OneofOptions",
+                  "id": 2
+                }
+              }
+            },
+            "EnumDescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "value": {
+                  "rule": "repeated",
+                  "type": "EnumValueDescriptorProto",
+                  "id": 2
+                },
+                "options": {
+                  "type": "EnumOptions",
+                  "id": 3
+                },
+                "reservedRange": {
+                  "rule": "repeated",
+                  "type": "EnumReservedRange",
+                  "id": 4
+                },
+                "reservedName": {
+                  "rule": "repeated",
+                  "type": "string",
+                  "id": 5
+                }
+              },
+              "nested": {
+                "EnumReservedRange": {
+                  "fields": {
+                    "start": {
+                      "type": "int32",
+                      "id": 1
+                    },
+                    "end": {
+                      "type": "int32",
+                      "id": 2
+                    }
+                  }
+                }
+              }
+            },
+            "EnumValueDescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "number": {
+                  "type": "int32",
+                  "id": 2
+                },
+                "options": {
+                  "type": "EnumValueOptions",
+                  "id": 3
+                }
+              }
+            },
+            "ServiceDescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "method": {
+                  "rule": "repeated",
+                  "type": "MethodDescriptorProto",
+                  "id": 2
+                },
+                "options": {
+                  "type": "ServiceOptions",
+                  "id": 3
+                }
+              }
+            },
+            "MethodDescriptorProto": {
+              "fields": {
+                "name": {
+                  "type": "string",
+                  "id": 1
+                },
+                "inputType": {
+                  "type": "string",
+                  "id": 2
+                },
+                "outputType": {
+                  "type": "string",
+                  "id": 3
+                },
+                "options": {
+                  "type": "MethodOptions",
+                  "id": 4
+                },
+                "clientStreaming": {
+                  "type": "bool",
+                  "id": 5,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "serverStreaming": {
+                  "type": "bool",
+                  "id": 6,
+                  "options": {
+                    "default": false
+                  }
+                }
+              }
+            },
+            "FileOptions": {
+              "fields": {
+                "javaPackage": {
+                  "type": "string",
+                  "id": 1
+                },
+                "javaOuterClassname": {
+                  "type": "string",
+                  "id": 8
+                },
+                "javaMultipleFiles": {
+                  "type": "bool",
+                  "id": 10,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "javaGenerateEqualsAndHash": {
+                  "type": "bool",
+                  "id": 20,
+                  "options": {
+                    "deprecated": true
+                  }
+                },
+                "javaStringCheckUtf8": {
+                  "type": "bool",
+                  "id": 27,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "optimizeFor": {
+                  "type": "OptimizeMode",
+                  "id": 9,
+                  "options": {
+                    "default": "SPEED"
+                  }
+                },
+                "goPackage": {
+                  "type": "string",
+                  "id": 11
+                },
+                "ccGenericServices": {
+                  "type": "bool",
+                  "id": 16,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "javaGenericServices": {
+                  "type": "bool",
+                  "id": 17,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "pyGenericServices": {
+                  "type": "bool",
+                  "id": 18,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "phpGenericServices": {
+                  "type": "bool",
+                  "id": 42,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "deprecated": {
+                  "type": "bool",
+                  "id": 23,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "ccEnableArenas": {
+                  "type": "bool",
+                  "id": 31,
+                  "options": {
+                    "default": true
+                  }
+                },
+                "objcClassPrefix": {
+                  "type": "string",
+                  "id": 36
+                },
+                "csharpNamespace": {
+                  "type": "string",
+                  "id": 37
+                },
+                "swiftPrefix": {
+                  "type": "string",
+                  "id": 39
+                },
+                "phpClassPrefix": {
+                  "type": "string",
+                  "id": 40
+                },
+                "phpNamespace": {
+                  "type": "string",
+                  "id": 41
+                },
+                "phpMetadataNamespace": {
+                  "type": "string",
+                  "id": 44
+                },
+                "rubyPackage": {
+                  "type": "string",
+                  "id": 45
+                },
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ],
+              "reserved": [
+                [
+                  38,
+                  38
+                ]
+              ],
+              "nested": {
+                "OptimizeMode": {
+                  "values": {
+                    "SPEED": 1,
+                    "CODE_SIZE": 2,
+                    "LITE_RUNTIME": 3
+                  }
+                }
+              }
+            },
+            "MessageOptions": {
+              "fields": {
+                "messageSetWireFormat": {
+                  "type": "bool",
+                  "id": 1,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "noStandardDescriptorAccessor": {
+                  "type": "bool",
+                  "id": 2,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "deprecated": {
+                  "type": "bool",
+                  "id": 3,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "mapEntry": {
+                  "type": "bool",
+                  "id": 7
+                },
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ],
+              "reserved": [
+                [
+                  4,
+                  4
+                ],
+                [
+                  5,
+                  5
+                ],
+                [
+                  6,
+                  6
+                ],
+                [
+                  8,
+                  8
+                ],
+                [
+                  9,
+                  9
+                ]
+              ]
+            },
+            "FieldOptions": {
+              "fields": {
+                "ctype": {
+                  "type": "CType",
+                  "id": 1,
+                  "options": {
+                    "default": "STRING"
+                  }
+                },
+                "packed": {
+                  "type": "bool",
+                  "id": 2
+                },
+                "jstype": {
+                  "type": "JSType",
+                  "id": 6,
+                  "options": {
+                    "default": "JS_NORMAL"
+                  }
+                },
+                "lazy": {
+                  "type": "bool",
+                  "id": 5,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "deprecated": {
+                  "type": "bool",
+                  "id": 3,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "weak": {
+                  "type": "bool",
+                  "id": 10,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ],
+              "reserved": [
+                [
+                  4,
+                  4
+                ]
+              ],
+              "nested": {
+                "CType": {
+                  "values": {
+                    "STRING": 0,
+                    "CORD": 1,
+                    "STRING_PIECE": 2
+                  }
+                },
+                "JSType": {
+                  "values": {
+                    "JS_NORMAL": 0,
+                    "JS_STRING": 1,
+                    "JS_NUMBER": 2
+                  }
+                }
+              }
+            },
+            "OneofOptions": {
+              "fields": {
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ]
+            },
+            "EnumOptions": {
+              "fields": {
+                "allowAlias": {
+                  "type": "bool",
+                  "id": 2
+                },
+                "deprecated": {
+                  "type": "bool",
+                  "id": 3,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ],
+              "reserved": [
+                [
+                  5,
+                  5
+                ]
+              ]
+            },
+            "EnumValueOptions": {
+              "fields": {
+                "deprecated": {
+                  "type": "bool",
+                  "id": 1,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ]
+            },
+            "ServiceOptions": {
+              "fields": {
+                "deprecated": {
+                  "type": "bool",
+                  "id": 33,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ]
+            },
+            "MethodOptions": {
+              "fields": {
+                "deprecated": {
+                  "type": "bool",
+                  "id": 33,
+                  "options": {
+                    "default": false
+                  }
+                },
+                "idempotencyLevel": {
+                  "type": "IdempotencyLevel",
+                  "id": 34,
+                  "options": {
+                    "default": "IDEMPOTENCY_UNKNOWN"
+                  }
+                },
+                "uninterpretedOption": {
+                  "rule": "repeated",
+                  "type": "UninterpretedOption",
+                  "id": 999
+                }
+              },
+              "extensions": [
+                [
+                  1000,
+                  536870911
+                ]
+              ],
+              "nested": {
+                "IdempotencyLevel": {
+                  "values": {
+                    "IDEMPOTENCY_UNKNOWN": 0,
+                    "NO_SIDE_EFFECTS": 1,
+                    "IDEMPOTENT": 2
+                  }
+                }
+              }
+            },
+            "UninterpretedOption": {
+              "fields": {
+                "name": {
+                  "rule": "repeated",
+                  "type": "NamePart",
+                  "id": 2
+                },
+                "identifierValue": {
+                  "type": "string",
+                  "id": 3
+                },
+                "positiveIntValue": {
+                  "type": "uint64",
+                  "id": 4
+                },
+                "negativeIntValue": {
+                  "type": "int64",
+                  "id": 5
+                },
+                "doubleValue": {
+                  "type": "double",
+                  "id": 6
+                },
+                "stringValue": {
+                  "type": "bytes",
+                  "id": 7
+                },
+                "aggregateValue": {
+                  "type": "string",
+                  "id": 8
+                }
+              },
+              "nested": {
+                "NamePart": {
+                  "fields": {
+                    "namePart": {
+                      "rule": "required",
+                      "type": "string",
+                      "id": 1
+                    },
+                    "isExtension": {
+                      "rule": "required",
+                      "type": "bool",
+                      "id": 2
+                    }
+                  }
+                }
+              }
+            },
+            "SourceCodeInfo": {
+              "fields": {
+                "location": {
+                  "rule": "repeated",
+                  "type": "Location",
+                  "id": 1
+                }
+              },
+              "nested": {
+                "Location": {
+                  "fields": {
+                    "path": {
+                      "rule": "repeated",
+                      "type": "int32",
+                      "id": 1
+                    },
+                    "span": {
+                      "rule": "repeated",
+                      "type": "int32",
+                      "id": 2
+                    },
+                    "leadingComments": {
+                      "type": "string",
+                      "id": 3
+                    },
+                    "trailingComments": {
+                      "type": "string",
+                      "id": 4
+                    },
+                    "leadingDetachedComments": {
+                      "rule": "repeated",
+                      "type": "string",
+                      "id": 6
+                    }
+                  }
+                }
+              }
+            },
+            "GeneratedCodeInfo": {
+              "fields": {
+                "annotation": {
+                  "rule": "repeated",
+                  "type": "Annotation",
+                  "id": 1
+                }
+              },
+              "nested": {
+                "Annotation": {
+                  "fields": {
+                    "path": {
+                      "rule": "repeated",
+                      "type": "int32",
+                      "id": 1
+                    },
+                    "sourceFile": {
+                      "type": "string",
+                      "id": 2
+                    },
+                    "begin": {
+                      "type": "int32",
+                      "id": 3
+                    },
+                    "end": {
+                      "type": "int32",
+                      "id": 4
+                    }
+                  }
+                }
+              }
+            },
+            "Timestamp": {
+              "fields": {
+                "seconds": {
+                  "type": "int64",
+                  "id": 1
+                },
+                "nanos": {
+                  "type": "int32",
+                  "id": 2
+                }
+              }
+            },
+            "Any": {
+              "fields": {
+                "type_url": {
+                  "type": "string",
+                  "id": 1
+                },
+                "value": {
+                  "type": "bytes",
+                  "id": 2
+                }
+              }
+            },
+            "Empty": {
+              "fields": {}
+            },
+            "FieldMask": {
+              "fields": {
+                "paths": {
+                  "rule": "repeated",
+                  "type": "string",
+                  "id": 1
+                }
+              }
+            }
+          }
+        },
+        "rpc": {
+          "options": {
+            "cc_enable_arenas": true,
+            "go_package": "google.golang.org/genproto/googleapis/rpc/status;status",
+            "java_multiple_files": true,
+            "java_outer_classname": "StatusProto",
+            "java_package": "com.google.rpc",
+            "objc_class_prefix": "RPC"
+          },
+          "nested": {
+            "Status": {
+              "fields": {
+                "code": {
+                  "type": "int32",
+                  "id": 1
+                },
+                "message": {
+                  "type": "string",
+                  "id": 2
+                },
+                "details": {
+                  "rule": "repeated",
+                  "type": "google.protobuf.Any",
+                  "id": 3
+                }
+              }
+            }
+          }
+        },
+        "iam": {
+          "nested": {
+            "v1": {
+              "options": {
+                "cc_enable_arenas": true,
+                "csharp_namespace": "Google.Cloud.Iam.V1",
+                "go_package": "google.golang.org/genproto/googleapis/iam/v1;iam",
+                "java_multiple_files": true,
+                "java_outer_classname": "PolicyProto",
+                "java_package": "com.google.iam.v1",
+                "php_namespace": "Google\\Cloud\\Iam\\V1"
+              },
+              "nested": {
+                "IAMPolicy": {
+                  "options": {
+                    "(google.api.default_host)": "iam-meta-api.googleapis.com"
+                  },
+                  "methods": {
+                    "SetIamPolicy": {
+                      "requestType": "SetIamPolicyRequest",
+                      "responseType": "Policy",
+                      "options": {
+                        "(google.api.http).post": "/v1/{resource=**}:setIamPolicy",
+                        "(google.api.http).body": "*"
+                      },
+                      "parsedOptions": [
+                        {
+                          "(google.api.http)": {
+                            "post": "/v1/{resource=**}:setIamPolicy",
+                            "body": "*"
+                          }
+                        }
+                      ]
+                    },
+                    "GetIamPolicy": {
+                      "requestType": "GetIamPolicyRequest",
+                      "responseType": "Policy",
+                      "options": {
+                        "(google.api.http).post": "/v1/{resource=**}:getIamPolicy",
+                        "(google.api.http).body": "*"
+                      },
+                      "parsedOptions": [
+                        {
+                          "(google.api.http)": {
+                            "post": "/v1/{resource=**}:getIamPolicy",
+                            "body": "*"
+                          }
+                        }
+                      ]
+                    },
+                    "TestIamPermissions": {
+                      "requestType": "TestIamPermissionsRequest",
+                      "responseType": "TestIamPermissionsResponse",
+                      "options": {
+                        "(google.api.http).post": "/v1/{resource=**}:testIamPermissions",
+                        "(google.api.http).body": "*"
+                      },
+                      "parsedOptions": [
+                        {
+                          "(google.api.http)": {
+                            "post": "/v1/{resource=**}:testIamPermissions",
+                            "body": "*"
+                          }
+                        }
+                      ]
+                    }
+                  }
+                },
+                "SetIamPolicyRequest": {
+                  "fields": {
+                    "resource": {
+                      "type": "string",
+                      "id": 1,
+                      "options": {
+                        "(google.api.field_behavior)": "REQUIRED",
+                        "(google.api.resource_reference).type": "*"
+                      }
+                    },
+                    "policy": {
+                      "type": "Policy",
+                      "id": 2,
+                      "options": {
+                        "(google.api.field_behavior)": "REQUIRED"
+                      }
+                    }
+                  }
+                },
+                "GetIamPolicyRequest": {
+                  "fields": {
+                    "resource": {
+                      "type": "string",
+                      "id": 1,
+                      "options": {
+                        "(google.api.field_behavior)": "REQUIRED",
+                        "(google.api.resource_reference).type": "*"
+                      }
+                    },
+                    "options": {
+                      "type": "GetPolicyOptions",
+                      "id": 2
+                    }
+                  }
+                },
+                "TestIamPermissionsRequest": {
+                  "fields": {
+                    "resource": {
+                      "type": "string",
+                      "id": 1,
+                      "options": {
+                        "(google.api.field_behavior)": "REQUIRED",
+                        "(google.api.resource_reference).type": "*"
+                      }
+                    },
+                    "permissions": {
+                      "rule": "repeated",
+                      "type": "string",
+                      "id": 2,
+                      "options": {
+                        "(google.api.field_behavior)": "REQUIRED"
+                      }
+                    }
+                  }
+                },
+                "TestIamPermissionsResponse": {
+                  "fields": {
+                    "permissions": {
+                      "rule": "repeated",
+                      "type": "string",
+                      "id": 1
+                    }
+                  }
+                },
+                "GetPolicyOptions": {
+                  "fields": {
+                    "requestedPolicyVersion": {
+                      "type": "int32",
+                      "id": 1
+                    }
+                  }
+                },
+                "Policy": {
+                  "fields": {
+                    "version": {
+                      "type": "int32",
+                      "id": 1
+                    },
+                    "bindings": {
+                      "rule": "repeated",
+                      "type": "Binding",
+                      "id": 4
+                    },
+                    "etag": {
+                      "type": "bytes",
+                      "id": 3
+                    }
+                  }
+                },
+                "Binding": {
+                  "fields": {
+                    "role": {
+                      "type": "string",
+                      "id": 1
+                    },
+                    "members": {
+                      "rule": "repeated",
+                      "type": "string",
+                      "id": 2
+                    },
+                    "condition": {
+                      "type": "google.type.Expr",
+                      "id": 3
+                    }
+                  }
+                },
+                "PolicyDelta": {
+                  "fields": {
+                    "bindingDeltas": {
+                      "rule": "repeated",
+                      "type": "BindingDelta",
+                      "id": 1
+                    },
+                    "auditConfigDeltas": {
+                      "rule": "repeated",
+                      "type": "AuditConfigDelta",
+                      "id": 2
+                    }
+                  }
+                },
+                "BindingDelta": {
+                  "fields": {
+                    "action": {
+                      "type": "Action",
+                      "id": 1
+                    },
+                    "role": {
+                      "type": "string",
+                      "id": 2
+                    },
+                    "member": {
+                      "type": "string",
+                      "id": 3
+                    },
+                    "condition": {
+                      "type": "google.type.Expr",
+                      "id": 4
+                    }
+                  },
+                  "nested": {
+                    "Action": {
+                      "values": {
+                        "ACTION_UNSPECIFIED": 0,
+                        "ADD": 1,
+                        "REMOVE": 2
+                      }
+                    }
+                  }
+                },
+                "AuditConfigDelta": {
+                  "fields": {
+                    "action": {
+                      "type": "Action",
+                      "id": 1
+                    },
+                    "service": {
+                      "type": "string",
+                      "id": 2
+                    },
+                    "exemptedMember": {
+                      "type": "string",
+                      "id": 3
+                    },
+                    "logType": {
+                      "type": "string",
+                      "id": 4
+                    }
+                  },
+                  "nested": {
+                    "Action": {
+                      "values": {
+                        "ACTION_UNSPECIFIED": 0,
+                        "ADD": 1,
+                        "REMOVE": 2
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        },
+        "type": {
+          "options": {
+            "go_package": "google.golang.org/genproto/googleapis/type/expr;expr",
+            "java_multiple_files": true,
+            "java_outer_classname": "ExprProto",
+            "java_package": "com.google.type",
+            "objc_class_prefix": "GTP"
+          },
+          "nested": {
+            "Expr": {
+              "fields": {
+                "expression": {
+                  "type": "string",
+                  "id": 1
+                },
+                "title": {
+                  "type": "string",
+                  "id": 2
+                },
+                "description": {
+                  "type": "string",
+                  "id": 3
+                },
+                "location": {
+                  "type": "string",
+                  "id": 4
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000000000000000000000000000000000000..26428fcfce2ce0ca5c1657de55a2d2af47a86154
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,20 @@
+{
+  "extends": [
+    "config:base",
+    "docker:disable",
+    ":disableDependencyDashboard"
+  ],
+  "pinVersions": false,
+  "rebaseStalePrs": true,
+  "schedule": [
+    "after 9am and before 3pm"
+  ],
+  "gitAuthor": null,
+  "packageRules": [
+    {
+      "extends": "packages:linters",
+      "groupName": "linters"
+    }
+  ],
+  "ignoreDeps": ["typescript"]
+}
diff --git a/samples/.eslintrc.yml b/samples/.eslintrc.yml
new file mode 100644
index 0000000000000000000000000000000000000000..282535f55f6a1004719983b7f7fac43423aee5f3
--- /dev/null
+++ b/samples/.eslintrc.yml
@@ -0,0 +1,3 @@
+---
+rules:
+  no-console: off
diff --git a/samples/README.md b/samples/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..00ce1e112c27631297fe507e507acd699871bbc7
--- /dev/null
+++ b/samples/README.md
@@ -0,0 +1,52 @@
+[//]: # "This README.md file is auto-generated, all changes to this file will be lost."
+[//]: # "To regenerate it, use `python -m synthtool`."
+<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
+
+# [Google Cloud Internet of Things (IoT) Core: Node.js Samples](https://github.com/googleapis/nodejs-iot)
+
+[![Open in Cloud Shell][shell_img]][shell_link]
+
+> Node.js idiomatic client for [Cloud IoT Core][product-docs].
+
+[Google Cloud Internet of Things (IoT) Core](https://cloud.google.com/iot/docs) is a fully managed service for securely connecting and managing IoT devices, from a few to millions. Ingest data from connected devices and build rich applications that integrate with the other big data services of Google Cloud Platform.
+
+## Table of Contents
+
+* [Before you begin](#before-you-begin)
+* [Samples](#samples)
+  * [Quickstart](#quickstart)
+
+## Before you begin
+
+Before running the samples, make sure you've followed the steps outlined in
+[Using the client library](https://github.com/googleapis/nodejs-iot#using-the-client-library).
+
+`cd samples`
+
+`npm install`
+
+`cd ..`
+
+## Samples
+
+
+
+### Quickstart
+
+View the [source code](https://github.com/googleapis/nodejs-iot/blob/main/samples/quickstart.js).
+
+[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-iot&page=editor&open_in_editor=samples/quickstart.js,samples/README.md)
+
+__Usage:__
+
+
+`node samples/quickstart.js`
+
+
+
+
+
+
+[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png
+[shell_link]: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-iot&page=editor&open_in_editor=samples/README.md
+[product-docs]: https://cloud.google.com/iot
diff --git a/samples/access_token_example/.gitignore b/samples/access_token_example/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..59ec5ff4a2061548386f38316be104ca30deba0f
--- /dev/null
+++ b/samples/access_token_example/.gitignore
@@ -0,0 +1 @@
+resources/*
diff --git a/samples/access_token_example/README.md b/samples/access_token_example/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7f226d3a001156d92fcdc6f22522018410ec4fea
--- /dev/null
+++ b/samples/access_token_example/README.md
@@ -0,0 +1,35 @@
+<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
+
+# Google Cloud IoT Core NodeJS Device Federated Authentication example
+
+This sample app demonstrates the capabilites of Google Cloud IoT Core device federated authentication feature.
+
+Devices authenticated to Cloud IoT Core can use the [Token Service](https://cloud.google.com/iot/alpha/docs/reference/cloudiottoken/rest) federated authentication to request [OAuth 2.0 access tokens](https://developers.google.com/identity/protocols/oauth2) in exchange for their [Cloud IoT Core JWTs](https://cloud.google.com/iot/docs/how-tos/credentials/jwts).
+
+The OAuth 2.0 credentials can be used to call different [Google Cloud APIs](https://developers.google.com/identity/protocols/oauth2/scopes) with fine-grained permissions and access control using [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation).
+
+For more information, see https://cloud.google.com/iot/alpha/docs/how-tos/federated_auth
+
+# Setup
+
+Run the following command to install the library dependencies for NodeJS:
+
+    npm install
+
+# Running the sample
+
+    Commands:
+      generateAccessToken                                 Generates OAuth 2.0 Google Access Token.
+      exchangeDeviceAccessTokenToServiceAccountToken      Exchanges device access token to service account access token.
+      publishPubSubMessage                                Publishes a message to Cloud Pub/Sub topic.
+      downloadCloudStorageFile                            Downloads a file from Cloud Storage bucket.
+      sendCommandToIoTDevice                              Sends a command to an IoT device.
+
+    Examples:
+      node access_token.js generateAccessToken --cloudRegion=us-central1 --projectId=my-project my-registry my-device https://www.googleapis.com/auth/cloud-platform RS256 ../resources/rsa_private.pem
+      node access_token.js publishPubSubMessage --cloudRegion=us-central1 --projectId=my-project my-registry my-device RS256 ../resources/rsa_private.pem my-pubsub-topic
+      node access_token.js downloadCloudStorageFile --cloudRegion=us-central1 --projectId=my-project my-registry my-device RS256 ../resources/rsa_private.pem my-storage-bucket ../resources/logo.png
+      node access_token.js sendCommandToIoTDevice --cloudRegion=us-central1 --projectId=my-project my-registry my-device RS256 ../resources/rsa_private.pem my-service-account@my-project.iam.gserviceaccount.com
+      node access_token.js exchangeDeviceAccessTokenToServiceAccountToken device-access-token my-service-account@my-project.iam.gserviceaccount.com
+
+For more information, see https://cloud.google.com/iot-core/docs
diff --git a/samples/access_token_example/access_token.js b/samples/access_token_example/access_token.js
new file mode 100644
index 0000000000000000000000000000000000000000..990525f1b08664be660c50af36eaaaf4e2abd480
--- /dev/null
+++ b/samples/access_token_example/access_token.js
@@ -0,0 +1,502 @@
+// Copyright 2021 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 assert = require('assert');
+const {readFileSync} = require('fs');
+const {createJwt} = require('./common');
+const {request} = require('gaxios');
+
+// Generate device access token
+const generateAccessToken = async (
+  cloudRegion,
+  projectId,
+  registryId,
+  deviceId,
+  scope,
+  algorithm,
+  privateKeyFile
+) => {
+  // [START iot_generate_access_token]
+  // cloudRegion = 'us-central1'
+  // projectId = 'YOUR_PROJECT_ID'
+  // registryId = 'your-registry-id'
+  // deviceId = 'your-device-id'
+  // scope = 'scope1 scope2' // See the full list of scopes \
+  //     at: https://developers.google.com/identity/protocols/oauth2/scopes
+  // algorithm = 'RS256'
+  // privateKeyFile = 'path/to/private_key.pem'
+
+  // Generate IoT device JWT. See https://cloud.google.com/iot/docs/how-tos/credentials/jwts
+  const jwtToken = createJwt(projectId, privateKeyFile, algorithm);
+
+  // Generate OAuth 2.0 access token. See https://developers.google.com/identity/protocols/oauth2
+  const headers = {authorization: `Bearer ${jwtToken}`};
+  try {
+    const resourcePath = `projects/${projectId}/locations/${cloudRegion}/registries/${registryId}/devices/${deviceId}`;
+    const requestUrl = `https://cloudiottoken.googleapis.com/v1beta1/${resourcePath}:generateAccessToken`;
+    const options = {
+      url: requestUrl,
+      method: 'POST',
+      headers: headers,
+      data: {
+        device: resourcePath,
+        scope: scope,
+      },
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    };
+    const response = await request(options);
+    const accessToken = response.data['access_token'];
+    console.log('Device access token: ' + accessToken);
+    return accessToken;
+  } catch (err) {
+    console.error('Received error: ', err);
+  }
+  // [END iot_generate_access_token]
+};
+
+const publishPubSubMessage = async (
+  cloudRegion,
+  projectId,
+  registryId,
+  deviceId,
+  algorithm,
+  privateKeyFile,
+  topicId
+) => {
+  // [START iot_access_token_pubsub]
+  // cloudRegion = 'us-central1'
+  // projectId = 'YOUR_PROJECT_ID'
+  // registryId = 'your-registry-id'
+  // deviceId = 'your-device-id'
+  // algorithm = 'RS256'
+  // privateKeyFile = 'path/to/private_key.pem'
+  // topicId = 'pubsub-topic-id'
+  const scope = 'https://www.googleapis.com/auth/pubsub';
+
+  // Generate device access token
+  const access_token = await generateAccessToken(
+    cloudRegion,
+    projectId,
+    registryId,
+    deviceId,
+    scope,
+    algorithm,
+    privateKeyFile
+  );
+
+  const headers = {authorization: `Bearer ${access_token}`};
+  try {
+    // Create Pub/Sub topic
+    const createPubsubRequestUrl = `https://pubsub.googleapis.com/v1/projects/${projectId}/topics/${topicId}`;
+    const createPubsubOptions = {
+      url: createPubsubRequestUrl,
+      method: 'PUT',
+      headers: headers,
+      data: {},
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    };
+    const createResponse = await request(createPubsubOptions);
+    assert.strictEqual(createResponse.status, 200);
+    console.log('Successfully created Pub/Sub topic: ' + topicId + '.');
+
+    // Publish message to Pub/Sub topic
+    const publishPayload = {
+      messages: [
+        {
+          attributes: {
+            test: 'VALUE',
+          },
+          data: Buffer.from('MESSAGE_DATA').toString('base64'),
+        },
+      ],
+    };
+    const publishPubsubRequestUrl = `https://pubsub.googleapis.com/v1/projects/${projectId}/topics/${topicId}:publish`;
+    const publishPubsubOptions = {
+      url: publishPubsubRequestUrl,
+      method: 'POST',
+      headers: headers,
+      data: publishPayload,
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    };
+    const publishResponse = await request(publishPubsubOptions);
+    assert.strictEqual(publishResponse.status, 200);
+    console.log(
+      'Pub/Sub message has been successfully published to ' +
+        topicId +
+        ': ' +
+        JSON.stringify(publishResponse.data) +
+        '.'
+    );
+
+    // Delete Pub/Sub topic
+    const deletePubsubRequestPath = `https://pubsub.googleapis.com/v1/projects/${projectId}/topics/${topicId}`;
+    const deletePubsubOptions = {
+      url: deletePubsubRequestPath,
+      method: 'DELETE',
+      headers: headers,
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    };
+    const deleteResponse = await request(deletePubsubOptions);
+    assert.strictEqual(deleteResponse.status, 200);
+    console.log('Successfully deleted Pub/Sub topic: ' + topicId + '.');
+  } catch (error) {
+    console.log('Error received: ', JSON.stringify(error));
+  }
+  // [END iot_access_token_pubsub]
+};
+
+const downloadCloudStorageFile = async (
+  cloudRegion,
+  projectId,
+  registryId,
+  deviceId,
+  algorithm,
+  privateKeyFile,
+  bucketName,
+  dataPath
+) => {
+  // [START iot_access_token_gcs]
+  // cloudRegion = 'us-central1'
+  // projectId = 'YOUR_PROJECT_ID'
+  // registryId = 'your-registry-id'
+  // deviceId = 'your-device-id'
+  // algorithm = 'RS256'
+  // privateKeyFile = 'path/to/private_key.pem'
+  // bucketName = 'name-of-gcs-bucket'
+  // dataPath = 'path/to/file/to/be/uploaded.png'
+  const scope = 'https://www.googleapis.com/auth/devstorage.full_control';
+
+  // Generate device access token
+  const access_token = await generateAccessToken(
+    cloudRegion,
+    projectId,
+    registryId,
+    deviceId,
+    scope,
+    algorithm,
+    privateKeyFile
+  );
+
+  const headers = {authorization: `Bearer ${access_token}`};
+  try {
+    // Create GCS bucket
+    const createGcsPayload = {
+      name: bucketName,
+      location: cloudRegion,
+      storageClass: 'STANDARD',
+      iamConfiguration: {
+        uniformBucketLevelAccess: {enabled: true},
+      },
+    };
+    const createGcsRequestUrl = `https://storage.googleapis.com/storage/v1/b?project=${projectId}`;
+    const createGcsOptions = {
+      url: createGcsRequestUrl,
+      method: 'POST',
+      headers: headers,
+      data: Buffer.from(JSON.stringify(createGcsPayload)),
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    };
+    const createResponse = await request(createGcsOptions);
+    assert.strictEqual(createResponse.status, 200);
+    console.log('Successfully created Storage bucket: ' + bucketName + '.');
+
+    // Upload Data to GCS bucket
+    const dataName = 'testFile.ext';
+    const binaryData = readFileSync(dataPath);
+    const uploadGcsRequestUrl = `https://storage.googleapis.com/upload/storage/v1/b/${bucketName}/o?uploadType=media&name=${dataName}`;
+    const uploadGcsOptions = {
+      url: uploadGcsRequestUrl,
+      method: 'POST',
+      headers: headers,
+      data: binaryData,
+      'cache-control': 'no-cache',
+    };
+    const uploadResponse = await request(uploadGcsOptions);
+    assert.strictEqual(uploadResponse.status, 200);
+    console.log(
+      'Successfully uploaded ' +
+        dataPath +
+        ' as ' +
+        dataName +
+        ' to bucket ' +
+        bucketName +
+        '.'
+    );
+
+    // Download Data from GCS bucket
+    const downloadGcsRequestUrl = `https://storage.googleapis.com/storage/v1/b/${bucketName}/o/${dataName}?alt=media`;
+    const downloadGcsOptions = {
+      url: downloadGcsRequestUrl,
+      method: 'GET',
+      headers: headers,
+      'cache-control': 'no-cache',
+    };
+    const downloadResponse = await request(downloadGcsOptions);
+    assert.strictEqual(downloadResponse.status, 200);
+    console.log(
+      'Successfully downloaded ' + dataName + ' from bucket ' + bucketName + '.'
+    );
+
+    // Delete Data from GCS Bucket.
+    const deleteDataGcsRequestUrl = `https://storage.googleapis.com/storage/v1/b/${bucketName}/o/${dataName}`;
+    const deleteDataGcsOptions = {
+      url: deleteDataGcsRequestUrl,
+      method: 'DELETE',
+      headers: headers,
+      'cache-control': 'no-cache',
+    };
+    const deleteDataResponse = await request(deleteDataGcsOptions);
+    assert.strictEqual(deleteDataResponse.status, 204);
+    console.log(
+      'Successfully deleted ' + dataName + ' from bucket ' + bucketName + '.'
+    );
+
+    // Delete GCS bucket
+    const deleteGcsRequestUrl = `https://storage.googleapis.com/storage/v1/b/${createResponse.data.name}`;
+    const deleteGcsOptions = {
+      url: deleteGcsRequestUrl,
+      method: 'DELETE',
+      headers: headers,
+      'cache-control': 'no-cache',
+    };
+    const deleteResp = await request(deleteGcsOptions);
+    assert.strictEqual(deleteResp.status, 204);
+    console.log('Successfully deleted bucket: ' + bucketName + '.');
+  } catch (error) {
+    console.log('Error received: ', JSON.stringify(error));
+  }
+  // [END iot_access_token_gcs]
+};
+
+const exchangeDeviceAccessTokenToServiceAccountToken = async (
+  deviceAccessToken,
+  serviceAccountEmail
+) => {
+  // [START iot_access_token_service_account_token]
+  // deviceAccessToken = 'device-access-token'
+  // serviceAccountEmail  = 'your-service-account@your-project.iam.gserviceaccount.com'
+  const scope = 'https://www.googleapis.com/auth/cloud-platform';
+  const headers = {authorization: `Bearer ${deviceAccessToken}`};
+  try {
+    const exchangePayload = {
+      scope: [scope],
+    };
+    const exchangeRequestUrl = `https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${serviceAccountEmail}:generateAccessToken`;
+    const exchangeOptions = {
+      url: exchangeRequestUrl,
+      method: 'POST',
+      headers: headers,
+      data: JSON.stringify(exchangePayload),
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    };
+    const exchangeResponse = await request(exchangeOptions);
+    assert.strictEqual(exchangeResponse.status, 200);
+    assert.ok(exchangeResponse.data && exchangeResponse.data.accessToken);
+    console.log(
+      'Service account access token: ' + exchangeResponse.data.accessToken
+    );
+    return exchangeResponse.data.accessToken;
+  } catch (error) {
+    console.log('Error received: ', JSON.stringify(error));
+  }
+  // [END iot_access_token_service_account_token]
+};
+
+const sendCommandToIoTDevice = async (
+  cloudRegion,
+  projectId,
+  registryId,
+  deviceId,
+  algorithm,
+  privateKeyFile,
+  serviceAccountEmail,
+  commandTobeSentToDevice
+) => {
+  // [START iot_access_token_iot_send_command]
+  // cloudRegion = 'us-central1'
+  // projectId = 'YOUR_PROJECT_ID'
+  // registryId = 'your-registry-id'
+  // deviceId = 'your-device-id'
+  // algorithm = 'RS256'
+  // privateKeyFile = 'path/to/private_key.pem'
+  // serviceAccountEmail  = 'your-service-account@your-project.iam.gserviceaccount.com'
+  // commandTobeSentToDevice = 'command-to-device'
+  const scope = 'https://www.googleapis.com/auth/cloud-platform';
+
+  // Generate device access token
+  const access_token = await generateAccessToken(
+    cloudRegion,
+    projectId,
+    registryId,
+    deviceId,
+    scope,
+    algorithm,
+    privateKeyFile
+  );
+  try {
+    // Exchange GCP access token to a service account access token
+    const serviceAccountAccessToken =
+      await exchangeDeviceAccessTokenToServiceAccountToken(
+        access_token,
+        serviceAccountEmail
+      );
+
+    // Send command to IoT Device
+    const commandPayload = {
+      binaryData: Buffer.from(commandTobeSentToDevice).toString('base64'),
+    };
+    const commandRequesturl = `https://cloudiot.googleapis.com/v1/projects/${projectId}/locations/${cloudRegion}/registries/${registryId}/devices/${deviceId}:sendCommandToDevice`;
+    const commandOptions = {
+      url: commandRequesturl,
+      method: 'POST',
+      headers: {authorization: `Bearer ${serviceAccountAccessToken}`},
+      data: JSON.stringify(commandPayload),
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    };
+    const commandResponse = await request(commandOptions);
+    assert.strictEqual(commandResponse.status, 200);
+    console.log(
+      'Successfully sent command ' + commandTobeSentToDevice + ' to device.'
+    );
+  } catch (error) {
+    console.log('Error received: ', JSON.stringify(error));
+  }
+  // [END iot_access_token_iot_send_command]
+};
+
+require(`yargs`) // eslint-disable-line
+  .demand(1)
+  .options({
+    cloudRegion: {
+      alias: 'c',
+      default: 'us-central1',
+      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',
+    },
+  })
+  .command(
+    'generateAccessToken <registryId> <deviceId> <scope> <algorithm> <privateKeyPath>',
+    'Generate OAuth 2.0 Google Access Token.',
+    {},
+    async opts => {
+      await generateAccessToken(
+        opts.cloudRegion,
+        opts.projectId,
+        opts.registryId,
+        opts.deviceId,
+        opts.scope,
+        opts.algorithm,
+        opts.privateKeyPath
+      );
+    }
+  )
+  .command(
+    'publishPubSubMessage <registryId> <deviceId> <algorithm> <privateKeyPath> <topicName>',
+    'Publish a message to a Cloud Pub/Sub topic.',
+    {},
+    async opts => {
+      await publishPubSubMessage(
+        opts.cloudRegion,
+        opts.projectId,
+        opts.registryId,
+        opts.deviceId,
+        opts.algorithm,
+        opts.privateKeyPath,
+        opts.topicName
+      );
+    }
+  )
+  .command(
+    'downloadCloudStorageFile <registryId> <deviceId> <algorithm> <privateKeyPath> <bucketName> <dataPath>',
+    'Download a file from Cloud Storage bucket.',
+    {},
+    async opts => {
+      await downloadCloudStorageFile(
+        opts.cloudRegion,
+        opts.projectId,
+        opts.registryId,
+        opts.deviceId,
+        opts.algorithm,
+        opts.privateKeyPath,
+        opts.bucketName,
+        opts.dataPath
+      );
+    }
+  )
+  .command(
+    'sendCommandToIoTDevice <registryId> <deviceId> <algorithm> <privateKeyPath> <serviceAccountEmail> <commandToBeSent>',
+    'Send a command to an IoT device',
+    {},
+    async opts => {
+      await sendCommandToIoTDevice(
+        opts.cloudRegion,
+        opts.projectId,
+        opts.registryId,
+        opts.deviceId,
+        opts.algorithm,
+        opts.privateKeyPath,
+        opts.serviceAccountEmail,
+        opts.commandToBeSent
+      );
+    }
+  )
+  .command(
+    'exchangeDeviceAccessTokenToServiceAccountToken <deviceAccessToken> <serviceAccountEmail>',
+    'Exchanges device access token to service account access token.',
+    {},
+    async opts => {
+      await exchangeDeviceAccessTokenToServiceAccountToken(
+        opts.deviceAccessToken,
+        opts.serviceAccountEmail
+      );
+    }
+  )
+  .example(
+    'node $0 generateAccessToken my-registry my-device https://www.googleapis.com/auth/cloud-platform RS256 ./rsa_cert.pem'
+  )
+  .example(
+    'node $0 publishPubSubMessage my-registry my-device RS256 ../resources/rsa_private.pem my-pubsub-topic'
+  )
+  .example(
+    'node $0 downloadCloudStorageFile my-registry my-device RS256 ../resources/rsa_private.pem my-storage-bucket ../resources/logo.png'
+  )
+  .example(
+    'node $0 sendCommandToIoTDevice my-registry my-device RS256 ../resources/rsa_private.pem my-service-account@my-project.iam.gserviceaccount.com DEVICE_COMMAND'
+  )
+  .example(
+    'node $0 exchangeDeviceAccessTokenToServiceAccountToken device-access-token my-service-account@my-project.iam.gserviceaccount.com'
+  )
+  .wrap(120)
+  .recommendCommands()
+  .epilogue(
+    'For more information, see https://cloud.google.com/iot/alpha/docs/how-tos/federated_auth'
+  )
+  .help()
+  .strict().argv;
diff --git a/samples/access_token_example/common.js b/samples/access_token_example/common.js
new file mode 100644
index 0000000000000000000000000000000000000000..1d346c22f293972c379a724d815366aecbf12aee
--- /dev/null
+++ b/samples/access_token_example/common.js
@@ -0,0 +1,31 @@
+// Copyright 2021 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.
+
+const {readFileSync} = require('fs');
+const jwt = require('jsonwebtoken');
+
+const createJwt = (projectId, privateKeyFile, algorithm) => {
+  // projectId = 'YOUR_PROJECT_ID'
+  // privateKeyFile = 'path/to/private_key.pem'
+  // algorithm = 'RS256'
+  const jwtPayload = {
+    iat: parseInt(Date.now() / 1000),
+    exp: parseInt(Date.now() / 1000) + 20 * 60, // 20 minutes
+    aud: projectId,
+  };
+  const privateKey = readFileSync(privateKeyFile);
+  return jwt.sign(jwtPayload, privateKey, {algorithm: algorithm});
+};
+
+module.exports = {createJwt};
diff --git a/samples/access_token_example/package.json b/samples/access_token_example/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..10c85bec68b7349933e0e7c00b406afe4c2a3d1d
--- /dev/null
+++ b/samples/access_token_example/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "nodejs-docs-samples-iot-access-token",
+  "version": "0.0.1",
+  "description": "Example of Cloud IoT device federated authentication",
+  "main": "access_token.js",
+  "license": "Apache-2.0",
+  "author": "Google LLC",
+  "files": [
+    "*.js"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/googleapis/nodejs-iot.git"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "test": "mocha --timeout=600000"
+  },
+  "dependencies": {
+    "@google-cloud/iot": "^2.0.0",
+    "@google-cloud/pubsub": "^3.0.0",
+    "@google-cloud/storage": "^6.0.0",
+    "yargs": "^16.0.0",
+    "jsonwebtoken": "^8.5.1",
+    "gaxios": "^4.3.0",
+    "mqtt": "^4.0.0"
+  },
+  "devDependencies": {
+    "mocha": "^8.1.1",
+    "uuid": "^8.0.0"
+  }
+}
diff --git a/samples/access_token_example/test/access_token.test.js b/samples/access_token_example/test/access_token.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..a1f0a0de5775fe9c77c01715b5e202c4644cb907
--- /dev/null
+++ b/samples/access_token_example/test/access_token.test.js
@@ -0,0 +1,191 @@
+// Copyright 2021 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 assert = require('assert');
+const {createJwt} = require('../common');
+const mqtt = require('mqtt');
+const {readFileSync} = require('fs');
+const iot = require('@google-cloud/iot');
+const path = require('path');
+const {PubSub} = require('@google-cloud/pubsub');
+const uuid = require('uuid');
+const cp = require('child_process');
+const cwd = path.join(__dirname, '..');
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+const {after, before, it} = require('mocha');
+
+const deviceId = 'test-node-device';
+const topicName = `nodejs-docs-samples-test-iot-${uuid.v4()}`;
+const testTopicName = `nodejs-docs-samples-test-pubsub-iot-${uuid.v4()}`;
+const registryName = `nodejs-test-registry-iot-${uuid.v4()}`;
+const bucketName = `nodejs-test-bucket-iot-${uuid.v4()}`;
+const region = 'us-central1';
+const projectId =
+  process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
+const rsaPublicCert = '../resources/rsa_cert.pem'; // process.env.NODEJS_IOT_RSA_PUBLIC_CERT;
+const rsaPrivateKey = '../resources/rsa_private.pem'; //process.env.NODEJS_IOT_RSA_PRIVATE_KEY;
+const iotClient = new iot.v1.DeviceManagerClient();
+const pubSubClient = new PubSub({projectId});
+
+const cmd = 'node access_token.js';
+
+before(async () => {
+  assert(
+    process.env.GCLOUD_PROJECT,
+    'Must set GCLOUD_PROJECT environment variable!'
+  );
+  assert(
+    process.env.GOOGLE_APPLICATION_CREDENTIALS,
+    'Must set GOOGLE_APPLICATION_CREDENTIALS environment variable!'
+  );
+  // Create a Pub/Sub topic to be used for testing
+  const [topic] = await pubSubClient.createTopic(topicName);
+  console.log(`Topic ${topic.name} created.`);
+
+  // Creates a registry to be used for tests.
+  const createRegistryRequest = {
+    parent: iotClient.locationPath(projectId, region),
+    deviceRegistry: {
+      id: registryName,
+      eventNotificationConfigs: [
+        {
+          pubsubTopicName: topic.name,
+        },
+      ],
+    },
+  };
+
+  await iotClient.createDeviceRegistry(createRegistryRequest);
+
+  console.log(`Created registry: ${registryName}`);
+  async function createDevice() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, region, registryName);
+    const device = {
+      id: deviceId,
+      credentials: [
+        {
+          publicKey: {
+            format: 'RSA_X509_PEM',
+            key: readFileSync(rsaPublicCert).toString(),
+          },
+        },
+      ],
+    };
+
+    const request = {
+      parent: regPath,
+      device,
+    };
+
+    const [response] = await iotClient.createDevice(request);
+    console.log('Created device', response);
+  }
+
+  await createDevice();
+  console.log(`Created Device: ${deviceId}`);
+});
+
+after(async () => {
+  // Delete Pub/Sub topic
+  await pubSubClient.topic(topicName).delete();
+  console.log(`Topic ${topicName} deleted.`);
+  const devPath = iotClient.devicePath(
+    projectId,
+    region,
+    registryName,
+    deviceId
+  );
+
+  await iotClient.deleteDevice({name: devPath});
+
+  console.log(`Device ${deviceId} deleted.`);
+
+  const registryPath = iotClient.registryPath(projectId, region, registryName);
+  await iotClient.deleteDeviceRegistry({
+    name: registryPath,
+  });
+  console.log('Deleted test registry.');
+});
+
+it('Generate device access token, use access token to create pubsub topic, push message to pubsub topic', async () => {
+  await execSync(
+    `${cmd} publishPubSubMessage  ${registryName} ${deviceId} RS256 ${rsaPrivateKey} ${testTopicName}`,
+    cwd
+  );
+});
+
+it('Generate device access token, use access token to create GCS bucket, upload a file to bucket, download file from bucket', async () => {
+  const dataPath = '../resources/logo.png';
+  await execSync(
+    `${cmd} downloadCloudStorageFile  ${registryName} ${deviceId} RS256 ${rsaPrivateKey} ${bucketName} ${dataPath}`,
+    cwd
+  );
+});
+
+it('Generate device access token, exchange device access token for service account access token, use service account access token to send cloud iot device command', async () => {
+  const serviceAccountEmail =
+    'cloud-iot-test@long-door-651.iam.gserviceaccount.com';
+  const commandTobeSentToDevice = 'OPEN_DOOR';
+  // Create device MQTT client and connect to cloud iot mqtt bridge.
+  const mqttBridgeHostname = 'mqtt.googleapis.com';
+  const mqttBridgePort = 8883;
+  const mqttTlsCert = '../resources/roots.pem';
+
+  // The mqttClientId is a unique string that identifies this device. For Google
+  // Cloud IoT Core, it must be in the format below.
+  const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryName}/devices/${deviceId}`;
+
+  // With Google Cloud IoT Core, the username field is ignored, however it must be
+  // non-empty. The password field is used to transmit a JWT to authorize the
+  // device. The "mqtts" protocol causes the library to connect using SSL, which
+  // is required for Cloud IoT Core.
+  const connectionArgs = {
+    host: mqttBridgeHostname,
+    port: mqttBridgePort,
+    clientId: mqttClientId,
+    username: 'unused',
+    password: createJwt(projectId, rsaPrivateKey, 'RS256'),
+    protocol: 'mqtts',
+    secureProtocol: 'TLSv1_2_method',
+    ca: [readFileSync(mqttTlsCert)],
+  };
+  const client = mqtt.connect(connectionArgs);
+  // Subscribe to the /devices/{device-id}/config topic to receive config updates.
+  client.subscribe(`/devices/${deviceId}/config`, {qos: 1});
+  // Subscribe to the /devices/{device-id}/commands/# topic to receive all
+  // commands.
+  client.subscribe(`/devices/${deviceId}/commands/#`, {qos: 0});
+  client.on('connect', () => {
+    console.log('Device Connected Successfully.');
+  });
+  client.on('message', (topic, message) => {
+    if (topic.startsWith(`/devices/${deviceId}/commands`)) {
+      assert.strictEqual(
+        Buffer.from(message, 'base64').toString('ascii'),
+        commandTobeSentToDevice
+      );
+    }
+  });
+
+  // Send command to device
+  await execSync(
+    `${cmd} sendCommandToIoTDevice  ${registryName} ${deviceId} RS256 ${rsaPrivateKey} ${serviceAccountEmail} ${commandTobeSentToDevice}`,
+    cwd
+  );
+  // Disconnect mqtt client.
+  client.end();
+});
diff --git a/samples/generated/v1/device_manager.bind_device_to_gateway.js b/samples/generated/v1/device_manager.bind_device_to_gateway.js
new file mode 100644
index 0000000000000000000000000000000000000000..e5d0348f48d2c0beafdde791a7a3c6a287831f52
--- /dev/null
+++ b/samples/generated/v1/device_manager.bind_device_to_gateway.js
@@ -0,0 +1,72 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(parent, gatewayId, deviceId) {
+  // [START cloudiot_v1_generated_DeviceManager_BindDeviceToGateway_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the registry. For example,
+   *  `projects/example-project/locations/us-central1/registries/my-registry`.
+   */
+  // const parent = 'abc123'
+  /**
+   *  Required. The value of `gateway_id` can be either the device numeric ID or the
+   *  user-defined device identifier.
+   */
+  // const gatewayId = 'abc123'
+  /**
+   *  Required. The device to associate with the specified gateway. The value of
+   *  `device_id` can be either the device numeric ID or the user-defined device
+   *  identifier.
+   */
+  // const deviceId = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callBindDeviceToGateway() {
+    // Construct request
+    const request = {
+      parent,
+      gatewayId,
+      deviceId,
+    };
+
+    // Run request
+    const response = await iotClient.bindDeviceToGateway(request);
+    console.log(response);
+  }
+
+  callBindDeviceToGateway();
+  // [END cloudiot_v1_generated_DeviceManager_BindDeviceToGateway_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.create_device.js b/samples/generated/v1/device_manager.create_device.js
new file mode 100644
index 0000000000000000000000000000000000000000..d38142b0f4633719bc30362e2464c6f5bf645f77
--- /dev/null
+++ b/samples/generated/v1/device_manager.create_device.js
@@ -0,0 +1,67 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(parent, device) {
+  // [START cloudiot_v1_generated_DeviceManager_CreateDevice_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device registry where this device should be created.
+   *  For example,
+   *  `projects/example-project/locations/us-central1/registries/my-registry`.
+   */
+  // const parent = 'abc123'
+  /**
+   *  Required. The device registration details. The field `name` must be empty. The server
+   *  generates `name` from the device registry `id` and the
+   *  `parent` field.
+   */
+  // const device = {}
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callCreateDevice() {
+    // Construct request
+    const request = {
+      parent,
+      device,
+    };
+
+    // Run request
+    const response = await iotClient.createDevice(request);
+    console.log(response);
+  }
+
+  callCreateDevice();
+  // [END cloudiot_v1_generated_DeviceManager_CreateDevice_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.create_device_registry.js b/samples/generated/v1/device_manager.create_device_registry.js
new file mode 100644
index 0000000000000000000000000000000000000000..6248800bb40fd631479e3876d9a61b16368961ac
--- /dev/null
+++ b/samples/generated/v1/device_manager.create_device_registry.js
@@ -0,0 +1,66 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(parent, deviceRegistry) {
+  // [START cloudiot_v1_generated_DeviceManager_CreateDeviceRegistry_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The project and cloud region where this device registry must be created.
+   *  For example, `projects/example-project/locations/us-central1`.
+   */
+  // const parent = 'abc123'
+  /**
+   *  Required. The device registry. The field `name` must be empty. The server will
+   *  generate that field from the device registry `id` provided and the
+   *  `parent` field.
+   */
+  // const deviceRegistry = {}
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callCreateDeviceRegistry() {
+    // Construct request
+    const request = {
+      parent,
+      deviceRegistry,
+    };
+
+    // Run request
+    const response = await iotClient.createDeviceRegistry(request);
+    console.log(response);
+  }
+
+  callCreateDeviceRegistry();
+  // [END cloudiot_v1_generated_DeviceManager_CreateDeviceRegistry_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.delete_device.js b/samples/generated/v1/device_manager.delete_device.js
new file mode 100644
index 0000000000000000000000000000000000000000..ab1999e2b6742a97eec16cb77098ba427aa8a476
--- /dev/null
+++ b/samples/generated/v1/device_manager.delete_device.js
@@ -0,0 +1,60 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name) {
+  // [START cloudiot_v1_generated_DeviceManager_DeleteDevice_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device. For example,
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   */
+  // const name = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callDeleteDevice() {
+    // Construct request
+    const request = {
+      name,
+    };
+
+    // Run request
+    const response = await iotClient.deleteDevice(request);
+    console.log(response);
+  }
+
+  callDeleteDevice();
+  // [END cloudiot_v1_generated_DeviceManager_DeleteDevice_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.delete_device_registry.js b/samples/generated/v1/device_manager.delete_device_registry.js
new file mode 100644
index 0000000000000000000000000000000000000000..663be451d24469df4fde27b35aef5919669545a8
--- /dev/null
+++ b/samples/generated/v1/device_manager.delete_device_registry.js
@@ -0,0 +1,59 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name) {
+  // [START cloudiot_v1_generated_DeviceManager_DeleteDeviceRegistry_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device registry. For example,
+   *  `projects/example-project/locations/us-central1/registries/my-registry`.
+   */
+  // const name = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callDeleteDeviceRegistry() {
+    // Construct request
+    const request = {
+      name,
+    };
+
+    // Run request
+    const response = await iotClient.deleteDeviceRegistry(request);
+    console.log(response);
+  }
+
+  callDeleteDeviceRegistry();
+  // [END cloudiot_v1_generated_DeviceManager_DeleteDeviceRegistry_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.get_device.js b/samples/generated/v1/device_manager.get_device.js
new file mode 100644
index 0000000000000000000000000000000000000000..db5022fb8febd9aae47a03932149127d955b6262
--- /dev/null
+++ b/samples/generated/v1/device_manager.get_device.js
@@ -0,0 +1,66 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name) {
+  // [START cloudiot_v1_generated_DeviceManager_GetDevice_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device. For example,
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   */
+  // const name = 'abc123'
+  /**
+   *  The fields of the `Device` resource to be returned in the response. If the
+   *  field mask is unset or empty, all fields are returned. Fields have to be
+   *  provided in snake_case format, for example: `last_heartbeat_time`.
+   */
+  // const fieldMask = {}
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callGetDevice() {
+    // Construct request
+    const request = {
+      name,
+    };
+
+    // Run request
+    const response = await iotClient.getDevice(request);
+    console.log(response);
+  }
+
+  callGetDevice();
+  // [END cloudiot_v1_generated_DeviceManager_GetDevice_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.get_device_registry.js b/samples/generated/v1/device_manager.get_device_registry.js
new file mode 100644
index 0000000000000000000000000000000000000000..7cbb7241bc3b03091e8345d8a575e58a812bb4e7
--- /dev/null
+++ b/samples/generated/v1/device_manager.get_device_registry.js
@@ -0,0 +1,59 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name) {
+  // [START cloudiot_v1_generated_DeviceManager_GetDeviceRegistry_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device registry. For example,
+   *  `projects/example-project/locations/us-central1/registries/my-registry`.
+   */
+  // const name = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callGetDeviceRegistry() {
+    // Construct request
+    const request = {
+      name,
+    };
+
+    // Run request
+    const response = await iotClient.getDeviceRegistry(request);
+    console.log(response);
+  }
+
+  callGetDeviceRegistry();
+  // [END cloudiot_v1_generated_DeviceManager_GetDeviceRegistry_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.get_iam_policy.js b/samples/generated/v1/device_manager.get_iam_policy.js
new file mode 100644
index 0000000000000000000000000000000000000000..039b394116332407baa1c94672bbb970d2c57230
--- /dev/null
+++ b/samples/generated/v1/device_manager.get_iam_policy.js
@@ -0,0 +1,64 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(resource) {
+  // [START cloudiot_v1_generated_DeviceManager_GetIamPolicy_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  REQUIRED: The resource for which the policy is being requested.
+   *  See the operation documentation for the appropriate value for this field.
+   */
+  // const resource = 'abc123'
+  /**
+   *  OPTIONAL: A `GetPolicyOptions` object for specifying options to
+   *  `GetIamPolicy`.
+   */
+  // const options = {}
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callGetIamPolicy() {
+    // Construct request
+    const request = {
+      resource,
+    };
+
+    // Run request
+    const response = await iotClient.getIamPolicy(request);
+    console.log(response);
+  }
+
+  callGetIamPolicy();
+  // [END cloudiot_v1_generated_DeviceManager_GetIamPolicy_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.list_device_config_versions.js b/samples/generated/v1/device_manager.list_device_config_versions.js
new file mode 100644
index 0000000000000000000000000000000000000000..be6a024d4c97ab7296a1ef63f2ea13df9af9c86e
--- /dev/null
+++ b/samples/generated/v1/device_manager.list_device_config_versions.js
@@ -0,0 +1,66 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name) {
+  // [START cloudiot_v1_generated_DeviceManager_ListDeviceConfigVersions_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device. For example,
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   */
+  // const name = 'abc123'
+  /**
+   *  The number of versions to list. Versions are listed in decreasing order of
+   *  the version number. The maximum number of versions retained is 10. If this
+   *  value is zero, it will return all the versions available.
+   */
+  // const numVersions = 1234
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callListDeviceConfigVersions() {
+    // Construct request
+    const request = {
+      name,
+    };
+
+    // Run request
+    const response = await iotClient.listDeviceConfigVersions(request);
+    console.log(response);
+  }
+
+  callListDeviceConfigVersions();
+  // [END cloudiot_v1_generated_DeviceManager_ListDeviceConfigVersions_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.list_device_registries.js b/samples/generated/v1/device_manager.list_device_registries.js
new file mode 100644
index 0000000000000000000000000000000000000000..d7853e34aa2d02fe5cd3b4d9a5d6180785356a0b
--- /dev/null
+++ b/samples/generated/v1/device_manager.list_device_registries.js
@@ -0,0 +1,74 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(parent) {
+  // [START cloudiot_v1_generated_DeviceManager_ListDeviceRegistries_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The project and cloud region path. For example,
+   *  `projects/example-project/locations/us-central1`.
+   */
+  // const parent = 'abc123'
+  /**
+   *  The maximum number of registries to return in the response. If this value
+   *  is zero, the service will select a default size. A call may return fewer
+   *  objects than requested. A non-empty `next_page_token` in the response
+   *  indicates that more data is available.
+   */
+  // const pageSize = 1234
+  /**
+   *  The value returned by the last `ListDeviceRegistriesResponse`; indicates
+   *  that this is a continuation of a prior `ListDeviceRegistries` call and
+   *  the system should return the next page of data.
+   */
+  // const pageToken = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callListDeviceRegistries() {
+    // Construct request
+    const request = {
+      parent,
+    };
+
+    // Run request
+    const iterable = await iotClient.listDeviceRegistriesAsync(request);
+    for await (const response of iterable) {
+        console.log(response);
+    }
+  }
+
+  callListDeviceRegistries();
+  // [END cloudiot_v1_generated_DeviceManager_ListDeviceRegistries_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.list_device_states.js b/samples/generated/v1/device_manager.list_device_states.js
new file mode 100644
index 0000000000000000000000000000000000000000..d9c8519d01db3bdc92ffab92d6bde599d0e27e8c
--- /dev/null
+++ b/samples/generated/v1/device_manager.list_device_states.js
@@ -0,0 +1,66 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name) {
+  // [START cloudiot_v1_generated_DeviceManager_ListDeviceStates_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device. For example,
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   */
+  // const name = 'abc123'
+  /**
+   *  The number of states to list. States are listed in descending order of
+   *  update time. The maximum number of states retained is 10. If this
+   *  value is zero, it will return all the states available.
+   */
+  // const numStates = 1234
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callListDeviceStates() {
+    // Construct request
+    const request = {
+      name,
+    };
+
+    // Run request
+    const response = await iotClient.listDeviceStates(request);
+    console.log(response);
+  }
+
+  callListDeviceStates();
+  // [END cloudiot_v1_generated_DeviceManager_ListDeviceStates_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.list_devices.js b/samples/generated/v1/device_manager.list_devices.js
new file mode 100644
index 0000000000000000000000000000000000000000..7e33937aaa9d38366444fdeb24f9882ec96b6c68
--- /dev/null
+++ b/samples/generated/v1/device_manager.list_devices.js
@@ -0,0 +1,95 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(parent) {
+  // [START cloudiot_v1_generated_DeviceManager_ListDevices_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The device registry path. Required. For example,
+   *  `projects/my-project/locations/us-central1/registries/my-registry`.
+   */
+  // const parent = 'abc123'
+  /**
+   *  A list of device numeric IDs. If empty, this field is ignored. Maximum
+   *  IDs: 10,000.
+   */
+  // const deviceNumIds = 1234
+  /**
+   *  A list of device string IDs. For example, `['device0', 'device12']`.
+   *  If empty, this field is ignored. Maximum IDs: 10,000
+   */
+  // const deviceIds = 'abc123'
+  /**
+   *  The fields of the `Device` resource to be returned in the response. The
+   *  fields `id` and `num_id` are always returned, along with any
+   *  other fields specified in snake_case format, for example:
+   *  `last_heartbeat_time`.
+   */
+  // const fieldMask = {}
+  /**
+   *  Options related to gateways.
+   */
+  // const gatewayListOptions = {}
+  /**
+   *  The maximum number of devices to return in the response. If this value
+   *  is zero, the service will select a default size. A call may return fewer
+   *  objects than requested. A non-empty `next_page_token` in the response
+   *  indicates that more data is available.
+   */
+  // const pageSize = 1234
+  /**
+   *  The value returned by the last `ListDevicesResponse`; indicates
+   *  that this is a continuation of a prior `ListDevices` call and
+   *  the system should return the next page of data.
+   */
+  // const pageToken = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callListDevices() {
+    // Construct request
+    const request = {
+      parent,
+    };
+
+    // Run request
+    const iterable = await iotClient.listDevicesAsync(request);
+    for await (const response of iterable) {
+        console.log(response);
+    }
+  }
+
+  callListDevices();
+  // [END cloudiot_v1_generated_DeviceManager_ListDevices_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.modify_cloud_to_device_config.js b/samples/generated/v1/device_manager.modify_cloud_to_device_config.js
new file mode 100644
index 0000000000000000000000000000000000000000..9e415682954ab39f916b7e0174083287680c1365
--- /dev/null
+++ b/samples/generated/v1/device_manager.modify_cloud_to_device_config.js
@@ -0,0 +1,73 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name, binaryData) {
+  // [START cloudiot_v1_generated_DeviceManager_ModifyCloudToDeviceConfig_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device. For example,
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   */
+  // const name = 'abc123'
+  /**
+   *  The version number to update. If this value is zero, it will not check the
+   *  version number of the server and will always update the current version;
+   *  otherwise, this update will fail if the version number found on the server
+   *  does not match this version number. This is used to support multiple
+   *  simultaneous updates without losing data.
+   */
+  // const versionToUpdate = 1234
+  /**
+   *  Required. The configuration data for the device.
+   */
+  // const binaryData = 'Buffer.from('string')'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callModifyCloudToDeviceConfig() {
+    // Construct request
+    const request = {
+      name,
+      binaryData,
+    };
+
+    // Run request
+    const response = await iotClient.modifyCloudToDeviceConfig(request);
+    console.log(response);
+  }
+
+  callModifyCloudToDeviceConfig();
+  // [END cloudiot_v1_generated_DeviceManager_ModifyCloudToDeviceConfig_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.send_command_to_device.js b/samples/generated/v1/device_manager.send_command_to_device.js
new file mode 100644
index 0000000000000000000000000000000000000000..df3997168a9d78d3914aaf6298c6b03f749db13a
--- /dev/null
+++ b/samples/generated/v1/device_manager.send_command_to_device.js
@@ -0,0 +1,73 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(name, binaryData) {
+  // [START cloudiot_v1_generated_DeviceManager_SendCommandToDevice_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the device. For example,
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   */
+  // const name = 'abc123'
+  /**
+   *  Required. The command data to send to the device.
+   */
+  // const binaryData = 'Buffer.from('string')'
+  /**
+   *  Optional subfolder for the command. If empty, the command will be delivered
+   *  to the /devices/{device-id}/commands topic, otherwise it will be delivered
+   *  to the /devices/{device-id}/commands/{subfolder} topic. Multi-level
+   *  subfolders are allowed. This field must not have more than 256 characters,
+   *  and must not contain any MQTT wildcards ("+" or "#") or null characters.
+   */
+  // const subfolder = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callSendCommandToDevice() {
+    // Construct request
+    const request = {
+      name,
+      binaryData,
+    };
+
+    // Run request
+    const response = await iotClient.sendCommandToDevice(request);
+    console.log(response);
+  }
+
+  callSendCommandToDevice();
+  // [END cloudiot_v1_generated_DeviceManager_SendCommandToDevice_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.set_iam_policy.js b/samples/generated/v1/device_manager.set_iam_policy.js
new file mode 100644
index 0000000000000000000000000000000000000000..05ba74e37042f4345c2b184adf8c00bdd56e151b
--- /dev/null
+++ b/samples/generated/v1/device_manager.set_iam_policy.js
@@ -0,0 +1,74 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(resource, policy) {
+  // [START cloudiot_v1_generated_DeviceManager_SetIamPolicy_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  REQUIRED: The resource for which the policy is being specified.
+   *  See the operation documentation for the appropriate value for this field.
+   */
+  // const resource = 'abc123'
+  /**
+   *  REQUIRED: The complete policy to be applied to the `resource`. The size of
+   *  the policy is limited to a few 10s of KB. An empty policy is a
+   *  valid policy but certain Cloud Platform services (such as Projects)
+   *  might reject them.
+   */
+  // const policy = {}
+  /**
+   *  OPTIONAL: A FieldMask specifying which fields of the policy to modify. Only
+   *  the fields in the mask will be modified. If no mask is provided, the
+   *  following default mask is used:
+   *  `paths: "bindings, etag"`
+   */
+  // const updateMask = {}
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callSetIamPolicy() {
+    // Construct request
+    const request = {
+      resource,
+      policy,
+    };
+
+    // Run request
+    const response = await iotClient.setIamPolicy(request);
+    console.log(response);
+  }
+
+  callSetIamPolicy();
+  // [END cloudiot_v1_generated_DeviceManager_SetIamPolicy_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.test_iam_permissions.js b/samples/generated/v1/device_manager.test_iam_permissions.js
new file mode 100644
index 0000000000000000000000000000000000000000..81f299d385f6f7ccc3fb6278617ecc175aba81db
--- /dev/null
+++ b/samples/generated/v1/device_manager.test_iam_permissions.js
@@ -0,0 +1,67 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(resource, permissions) {
+  // [START cloudiot_v1_generated_DeviceManager_TestIamPermissions_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  REQUIRED: The resource for which the policy detail is being requested.
+   *  See the operation documentation for the appropriate value for this field.
+   */
+  // const resource = 'abc123'
+  /**
+   *  The set of permissions to check for the `resource`. Permissions with
+   *  wildcards (such as '*' or 'storage.*') are not allowed. For more
+   *  information see
+   *  IAM Overview (https://cloud.google.com/iam/docs/overview#permissions).
+   */
+  // const permissions = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callTestIamPermissions() {
+    // Construct request
+    const request = {
+      resource,
+      permissions,
+    };
+
+    // Run request
+    const response = await iotClient.testIamPermissions(request);
+    console.log(response);
+  }
+
+  callTestIamPermissions();
+  // [END cloudiot_v1_generated_DeviceManager_TestIamPermissions_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.unbind_device_from_gateway.js b/samples/generated/v1/device_manager.unbind_device_from_gateway.js
new file mode 100644
index 0000000000000000000000000000000000000000..37fb81b5d888a9fac79ae7ba0f9810a4f9c8b061
--- /dev/null
+++ b/samples/generated/v1/device_manager.unbind_device_from_gateway.js
@@ -0,0 +1,72 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(parent, gatewayId, deviceId) {
+  // [START cloudiot_v1_generated_DeviceManager_UnbindDeviceFromGateway_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The name of the registry. For example,
+   *  `projects/example-project/locations/us-central1/registries/my-registry`.
+   */
+  // const parent = 'abc123'
+  /**
+   *  Required. The value of `gateway_id` can be either the device numeric ID or the
+   *  user-defined device identifier.
+   */
+  // const gatewayId = 'abc123'
+  /**
+   *  Required. The device to disassociate from the specified gateway. The value of
+   *  `device_id` can be either the device numeric ID or the user-defined device
+   *  identifier.
+   */
+  // const deviceId = 'abc123'
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callUnbindDeviceFromGateway() {
+    // Construct request
+    const request = {
+      parent,
+      gatewayId,
+      deviceId,
+    };
+
+    // Run request
+    const response = await iotClient.unbindDeviceFromGateway(request);
+    console.log(response);
+  }
+
+  callUnbindDeviceFromGateway();
+  // [END cloudiot_v1_generated_DeviceManager_UnbindDeviceFromGateway_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.update_device.js b/samples/generated/v1/device_manager.update_device.js
new file mode 100644
index 0000000000000000000000000000000000000000..f2c217889f9dfe486a6b0233aeef48ac372baaeb
--- /dev/null
+++ b/samples/generated/v1/device_manager.update_device.js
@@ -0,0 +1,69 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(device, updateMask) {
+  // [START cloudiot_v1_generated_DeviceManager_UpdateDevice_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The new values for the device. The `id` and `num_id` fields must
+   *  be empty, and the field `name` must specify the name path. For example,
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/device0`or
+   *  `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   */
+  // const device = {}
+  /**
+   *  Required. Only updates the `device` fields indicated by this mask.
+   *  The field mask must not be empty, and it must not contain fields that
+   *  are immutable or only set by the server.
+   *  Mutable top-level fields: `credentials`, `blocked`, and `metadata`
+   */
+  // const updateMask = {}
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callUpdateDevice() {
+    // Construct request
+    const request = {
+      device,
+      updateMask,
+    };
+
+    // Run request
+    const response = await iotClient.updateDevice(request);
+    console.log(response);
+  }
+
+  callUpdateDevice();
+  // [END cloudiot_v1_generated_DeviceManager_UpdateDevice_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/device_manager.update_device_registry.js b/samples/generated/v1/device_manager.update_device_registry.js
new file mode 100644
index 0000000000000000000000000000000000000000..c3a34b16258859ee1a7e6cd059cea867fd82bc45
--- /dev/null
+++ b/samples/generated/v1/device_manager.update_device_registry.js
@@ -0,0 +1,69 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+
+
+'use strict';
+
+function main(deviceRegistry, updateMask) {
+  // [START cloudiot_v1_generated_DeviceManager_UpdateDeviceRegistry_async]
+  /**
+   * TODO(developer): Uncomment these variables before running the sample.
+   */
+  /**
+   *  Required. The new values for the device registry. The `id` field must be empty, and
+   *  the `name` field must indicate the path of the resource. For example,
+   *  `projects/example-project/locations/us-central1/registries/my-registry`.
+   */
+  // const deviceRegistry = {}
+  /**
+   *  Required. Only updates the `device_registry` fields indicated by this mask.
+   *  The field mask must not be empty, and it must not contain fields that
+   *  are immutable or only set by the server.
+   *  Mutable top-level fields: `event_notification_config`, `http_config`,
+   *  `mqtt_config`, and `state_notification_config`.
+   */
+  // const updateMask = {}
+
+  // Imports the Iot library
+  const {DeviceManagerClient} = require('@google-cloud/iot').v1;
+
+  // Instantiates a client
+  const iotClient = new DeviceManagerClient();
+
+  async function callUpdateDeviceRegistry() {
+    // Construct request
+    const request = {
+      deviceRegistry,
+      updateMask,
+    };
+
+    // Run request
+    const response = await iotClient.updateDeviceRegistry(request);
+    console.log(response);
+  }
+
+  callUpdateDeviceRegistry();
+  // [END cloudiot_v1_generated_DeviceManager_UpdateDeviceRegistry_async]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/generated/v1/snippet_metadata.google.cloud.iot.v1.json b/samples/generated/v1/snippet_metadata.google.cloud.iot.v1.json
new file mode 100644
index 0000000000000000000000000000000000000000..13c5a252b4810dafb805c419644b751565075a70
--- /dev/null
+++ b/samples/generated/v1/snippet_metadata.google.cloud.iot.v1.json
@@ -0,0 +1,883 @@
+{
+    "clientLibrary": {
+        "name": "nodejs-iot",
+        "version": "3.1.0",
+        "language": "TYPESCRIPT",
+        "apis": [
+            {
+                "id": "google.cloud.iot.v1",
+                "version": "v1"
+            }
+        ]
+    },
+    "snippets": [
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_CreateDeviceRegistry_async",
+            "title": "iot createDeviceRegistry Sample",
+            "origin": "API_DEFINITION",
+            "description": " Creates a device registry that contains devices.",
+            "canonical": true,
+            "file": "device_manager.create_device_registry.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 58,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "CreateDeviceRegistry",
+                "fullName": "google.cloud.iot.v1.DeviceManager.CreateDeviceRegistry",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "parent",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "device_registry",
+                        "type": ".google.cloud.iot.v1.DeviceRegistry"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.DeviceRegistry",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "CreateDeviceRegistry",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.CreateDeviceRegistry",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_GetDeviceRegistry_async",
+            "title": "iot getDeviceRegistry Sample",
+            "origin": "API_DEFINITION",
+            "description": " Gets a device registry configuration.",
+            "canonical": true,
+            "file": "device_manager.get_device_registry.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 51,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "GetDeviceRegistry",
+                "fullName": "google.cloud.iot.v1.DeviceManager.GetDeviceRegistry",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.DeviceRegistry",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "GetDeviceRegistry",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.GetDeviceRegistry",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_UpdateDeviceRegistry_async",
+            "title": "iot updateDeviceRegistry Sample",
+            "origin": "API_DEFINITION",
+            "description": " Updates a device registry configuration.",
+            "canonical": true,
+            "file": "device_manager.update_device_registry.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 61,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "UpdateDeviceRegistry",
+                "fullName": "google.cloud.iot.v1.DeviceManager.UpdateDeviceRegistry",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "device_registry",
+                        "type": ".google.cloud.iot.v1.DeviceRegistry"
+                    },
+                    {
+                        "name": "update_mask",
+                        "type": ".google.protobuf.FieldMask"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.DeviceRegistry",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "UpdateDeviceRegistry",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.UpdateDeviceRegistry",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_DeleteDeviceRegistry_async",
+            "title": "iot deleteDeviceRegistry Sample",
+            "origin": "API_DEFINITION",
+            "description": " Deletes a device registry configuration.",
+            "canonical": true,
+            "file": "device_manager.delete_device_registry.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 51,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "DeleteDeviceRegistry",
+                "fullName": "google.cloud.iot.v1.DeviceManager.DeleteDeviceRegistry",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.protobuf.Empty",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "DeleteDeviceRegistry",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.DeleteDeviceRegistry",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_ListDeviceRegistries_async",
+            "title": "iot listDeviceRegistries Sample",
+            "origin": "API_DEFINITION",
+            "description": " Lists device registries.",
+            "canonical": true,
+            "file": "device_manager.list_device_registries.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 66,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "ListDeviceRegistries",
+                "fullName": "google.cloud.iot.v1.DeviceManager.ListDeviceRegistries",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "parent",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "page_size",
+                        "type": "TYPE_INT32"
+                    },
+                    {
+                        "name": "page_token",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.ListDeviceRegistriesResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "ListDeviceRegistries",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.ListDeviceRegistries",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_CreateDevice_async",
+            "title": "iot createDevice Sample",
+            "origin": "API_DEFINITION",
+            "description": " Creates a device in a device registry.",
+            "canonical": true,
+            "file": "device_manager.create_device.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 59,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "CreateDevice",
+                "fullName": "google.cloud.iot.v1.DeviceManager.CreateDevice",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "parent",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "device",
+                        "type": ".google.cloud.iot.v1.Device"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.Device",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "CreateDevice",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.CreateDevice",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_GetDevice_async",
+            "title": "iot getDevice Sample",
+            "origin": "API_DEFINITION",
+            "description": " Gets details about a device.",
+            "canonical": true,
+            "file": "device_manager.get_device.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 58,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "GetDevice",
+                "fullName": "google.cloud.iot.v1.DeviceManager.GetDevice",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "field_mask",
+                        "type": ".google.protobuf.FieldMask"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.Device",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "GetDevice",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.GetDevice",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_UpdateDevice_async",
+            "title": "iot updateDevice Sample",
+            "origin": "API_DEFINITION",
+            "description": " Updates a device.",
+            "canonical": true,
+            "file": "device_manager.update_device.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 61,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "UpdateDevice",
+                "fullName": "google.cloud.iot.v1.DeviceManager.UpdateDevice",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "device",
+                        "type": ".google.cloud.iot.v1.Device"
+                    },
+                    {
+                        "name": "update_mask",
+                        "type": ".google.protobuf.FieldMask"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.Device",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "UpdateDevice",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.UpdateDevice",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_DeleteDevice_async",
+            "title": "iot deleteDevice Sample",
+            "origin": "API_DEFINITION",
+            "description": " Deletes a device.",
+            "canonical": true,
+            "file": "device_manager.delete_device.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 52,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "DeleteDevice",
+                "fullName": "google.cloud.iot.v1.DeviceManager.DeleteDevice",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.protobuf.Empty",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "DeleteDevice",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.DeleteDevice",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_ListDevices_async",
+            "title": "iot listDevices Sample",
+            "origin": "API_DEFINITION",
+            "description": " List devices in a device registry.",
+            "canonical": true,
+            "file": "device_manager.list_devices.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 87,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "ListDevices",
+                "fullName": "google.cloud.iot.v1.DeviceManager.ListDevices",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "parent",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "device_num_ids",
+                        "type": "TYPE_UINT64[]"
+                    },
+                    {
+                        "name": "device_ids",
+                        "type": "TYPE_STRING[]"
+                    },
+                    {
+                        "name": "field_mask",
+                        "type": ".google.protobuf.FieldMask"
+                    },
+                    {
+                        "name": "gateway_list_options",
+                        "type": ".google.cloud.iot.v1.GatewayListOptions"
+                    },
+                    {
+                        "name": "page_size",
+                        "type": "TYPE_INT32"
+                    },
+                    {
+                        "name": "page_token",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.ListDevicesResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "ListDevices",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.ListDevices",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_ModifyCloudToDeviceConfig_async",
+            "title": "iot modifyCloudToDeviceConfig Sample",
+            "origin": "API_DEFINITION",
+            "description": " Modifies the configuration for the device, which is eventually sent from the Cloud IoT Core servers. Returns the modified configuration version and its metadata.",
+            "canonical": true,
+            "file": "device_manager.modify_cloud_to_device_config.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 65,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "ModifyCloudToDeviceConfig",
+                "fullName": "google.cloud.iot.v1.DeviceManager.ModifyCloudToDeviceConfig",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "version_to_update",
+                        "type": "TYPE_INT64"
+                    },
+                    {
+                        "name": "binary_data",
+                        "type": "TYPE_BYTES"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.DeviceConfig",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "ModifyCloudToDeviceConfig",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.ModifyCloudToDeviceConfig",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_ListDeviceConfigVersions_async",
+            "title": "iot listDeviceConfigVersions Sample",
+            "origin": "API_DEFINITION",
+            "description": " Lists the last few versions of the device configuration in descending order (i.e.: newest first).",
+            "canonical": true,
+            "file": "device_manager.list_device_config_versions.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 58,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "ListDeviceConfigVersions",
+                "fullName": "google.cloud.iot.v1.DeviceManager.ListDeviceConfigVersions",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "num_versions",
+                        "type": "TYPE_INT32"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.ListDeviceConfigVersionsResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "ListDeviceConfigVersions",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.ListDeviceConfigVersions",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_ListDeviceStates_async",
+            "title": "iot listDeviceStates Sample",
+            "origin": "API_DEFINITION",
+            "description": " Lists the last few versions of the device state in descending order (i.e.: newest first).",
+            "canonical": true,
+            "file": "device_manager.list_device_states.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 58,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "ListDeviceStates",
+                "fullName": "google.cloud.iot.v1.DeviceManager.ListDeviceStates",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "num_states",
+                        "type": "TYPE_INT32"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.ListDeviceStatesResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "ListDeviceStates",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.ListDeviceStates",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_SetIamPolicy_async",
+            "title": "iot setIamPolicy Sample",
+            "origin": "API_DEFINITION",
+            "description": " Sets the access control policy on the specified resource. Replaces any existing policy.",
+            "canonical": true,
+            "file": "device_manager.set_iam_policy.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 66,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "SetIamPolicy",
+                "fullName": "google.cloud.iot.v1.DeviceManager.SetIamPolicy",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "resource",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "policy",
+                        "type": ".google.iam.v1.Policy"
+                    },
+                    {
+                        "name": "update_mask",
+                        "type": ".google.protobuf.FieldMask"
+                    }
+                ],
+                "resultType": ".google.iam.v1.Policy",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "SetIamPolicy",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.SetIamPolicy",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_GetIamPolicy_async",
+            "title": "iot getIamPolicy Sample",
+            "origin": "API_DEFINITION",
+            "description": " Gets the access control policy for a resource. Returns an empty policy if the resource exists and does not have a policy set.",
+            "canonical": true,
+            "file": "device_manager.get_iam_policy.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 56,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "GetIamPolicy",
+                "fullName": "google.cloud.iot.v1.DeviceManager.GetIamPolicy",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "resource",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "options",
+                        "type": ".google.iam.v1.GetPolicyOptions"
+                    }
+                ],
+                "resultType": ".google.iam.v1.Policy",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "GetIamPolicy",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.GetIamPolicy",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_TestIamPermissions_async",
+            "title": "iot testIamPermissions Sample",
+            "origin": "API_DEFINITION",
+            "description": " Returns permissions that a caller has on the specified resource. If the resource does not exist, this will return an empty set of permissions, not a NOT_FOUND error.",
+            "canonical": true,
+            "file": "device_manager.test_iam_permissions.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 59,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "TestIamPermissions",
+                "fullName": "google.cloud.iot.v1.DeviceManager.TestIamPermissions",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "resource",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "permissions",
+                        "type": "TYPE_STRING[]"
+                    }
+                ],
+                "resultType": ".google.iam.v1.TestIamPermissionsResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "TestIamPermissions",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.TestIamPermissions",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_SendCommandToDevice_async",
+            "title": "iot sendCommandToDevice Sample",
+            "origin": "API_DEFINITION",
+            "description": " Sends a command to the specified device. In order for a device to be able to receive commands, it must: 1) be connected to Cloud IoT Core using the MQTT protocol, and 2) be subscribed to the group of MQTT topics specified by    /devices/{device-id}/commands/#. This subscription will receive commands    at the top-level topic /devices/{device-id}/commands as well as commands    for subfolders, like /devices/{device-id}/commands/subfolder.    Note that subscribing to specific subfolders is not supported. If the command could not be delivered to the device, this method will return an error; in particular, if the device is not subscribed, this method will return FAILED_PRECONDITION. Otherwise, this method will return OK. If the subscription is QoS 1, at least once delivery will be guaranteed; for QoS 0, no acknowledgment will be expected from the device.",
+            "canonical": true,
+            "file": "device_manager.send_command_to_device.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 65,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "SendCommandToDevice",
+                "fullName": "google.cloud.iot.v1.DeviceManager.SendCommandToDevice",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "name",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "binary_data",
+                        "type": "TYPE_BYTES"
+                    },
+                    {
+                        "name": "subfolder",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.SendCommandToDeviceResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "SendCommandToDevice",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.SendCommandToDevice",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_BindDeviceToGateway_async",
+            "title": "iot bindDeviceToGateway Sample",
+            "origin": "API_DEFINITION",
+            "description": " Associates the device with the gateway.",
+            "canonical": true,
+            "file": "device_manager.bind_device_to_gateway.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 64,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "BindDeviceToGateway",
+                "fullName": "google.cloud.iot.v1.DeviceManager.BindDeviceToGateway",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "parent",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "gateway_id",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "device_id",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.BindDeviceToGatewayResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "BindDeviceToGateway",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.BindDeviceToGateway",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        },
+        {
+            "regionTag": "cloudiot_v1_generated_DeviceManager_UnbindDeviceFromGateway_async",
+            "title": "iot unbindDeviceFromGateway Sample",
+            "origin": "API_DEFINITION",
+            "description": " Deletes the association between the device and the gateway.",
+            "canonical": true,
+            "file": "device_manager.unbind_device_from_gateway.js",
+            "language": "JAVASCRIPT",
+            "segments": [
+                {
+                    "start": 25,
+                    "end": 64,
+                    "type": "FULL"
+                }
+            ],
+            "clientMethod": {
+                "shortName": "UnbindDeviceFromGateway",
+                "fullName": "google.cloud.iot.v1.DeviceManager.UnbindDeviceFromGateway",
+                "async": true,
+                "parameters": [
+                    {
+                        "name": "parent",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "gateway_id",
+                        "type": "TYPE_STRING"
+                    },
+                    {
+                        "name": "device_id",
+                        "type": "TYPE_STRING"
+                    }
+                ],
+                "resultType": ".google.cloud.iot.v1.UnbindDeviceFromGatewayResponse",
+                "client": {
+                    "shortName": "DeviceManagerClient",
+                    "fullName": "google.cloud.iot.v1.DeviceManagerClient"
+                },
+                "method": {
+                    "shortName": "UnbindDeviceFromGateway",
+                    "fullName": "google.cloud.iot.v1.DeviceManager.UnbindDeviceFromGateway",
+                    "service": {
+                        "shortName": "DeviceManager",
+                        "fullName": "google.cloud.iot.v1.DeviceManager"
+                    }
+                }
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/samples/http_example/README.md b/samples/http_example/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0d1763f1b56628341106cf9b2c70fb8b7874c1e2
--- /dev/null
+++ b/samples/http_example/README.md
@@ -0,0 +1,64 @@
+<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
+
+# Google Cloud IoT Core NodeJS HTTP example
+
+This sample app publishes messages to [Google Cloud Pub/Sub](pubsub) or updates
+device states using the HTTP bridge provided as part of Google Cloud IoT Core.
+
+Note that before you can run this sample, you must register a device as
+described in the parent README.
+
+[pubsub]: https://cloud.google.com/pubsub/docs
+# Setup
+
+Run the following command to install the library dependencies for NodeJS:
+
+    npm install
+
+# Running the sample
+
+The following command summarizes the sample usage:
+
+Usage: cloudiot_http_example_nodejs [options]
+
+Example Google Cloud IoT Core HTTP device connection code.
+
+Options:
+
+    -h, --help                       output usage information
+    --projectId <projectId>          GCP cloud project name.
+    --registryId <registryId>        Cloud IoT Core registry id.
+    --deviceId <deviceId>            Cloud IoT Core device id.
+    --privateKeyFile <key_file>      Path to private key file.
+    --algorithm <algorithm>          Encryption algorithm to generate the JWT.
+                                     Either RS256 (RSA) or ES256 (Eliptic Curve)
+    --cloudRegion [region]           GCP cloud region (e.g. us-central1, europe-west1)
+    --numMessages [num]              Number of messages to publish.
+    --tokenExpMins [num]             Minutes to JWT token expiration.
+    --httpBridgeAddress [address]    HTTP bridge address.
+    --messageType [events|state]     The message type to publish.
+
+For example, if your project ID is `blue-jet-123`, your region is
+asia-east1, and you have generated your credentials using the shell script
+provided in the parent folder, you can run the sample as:
+
+    node cloudiot_http_example.js \
+        --cloudRegion=asia-east1 \
+        --projectId=blue-jet-123 \
+        --registryId=my-registry \
+        --deviceId=my-node-device \
+        --privateKeyFile=../rsa_private.pem \
+        --algorithm=RS256
+
+# Reading Cloud Pub/Sub messages written by the sample client
+
+1.  Create a subscription to your topic.
+
+    gcloud beta pubsub subscriptions create \
+    projects/your-project-id/subscriptions/my-subscription \
+    --topic device-events
+
+2.  Read messages published to the topic
+
+    gcloud beta pubsub subscriptions pull --auto-ack \
+    projects/my-iot-project/subscriptions/my-subscription
diff --git a/samples/http_example/cloudiot_http_example.js b/samples/http_example/cloudiot_http_example.js
new file mode 100644
index 0000000000000000000000000000000000000000..f86f9bf5d7477561310ea5a2a382d8a7998a529b
--- /dev/null
+++ b/samples/http_example/cloudiot_http_example.js
@@ -0,0 +1,234 @@
+// Copyright 2020 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';
+// [START iot_http_includes]
+const fs = require('fs');
+const jwt = require('jsonwebtoken');
+const {request} = require('gaxios');
+// [END iot_http_includes]
+
+// Create a Cloud IoT Core JWT for the given project ID, signed with the given
+// private key.
+// [START iot_http_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_http_jwt]
+
+console.log('Google Cloud IoT Core HTTP example.');
+const {argv} = require('yargs')
+  .options({
+    projectId: {
+      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',
+    },
+    cloudRegion: {
+      default: 'us-central1',
+      description: 'GCP cloud region.',
+      requiresArg: true,
+      type: 'string',
+    },
+    registryId: {
+      description: 'Cloud IoT registry ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    deviceId: {
+      description: 'Cloud IoT device ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    privateKeyFile: {
+      description: 'Path to private key file.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    algorithm: {
+      description: 'Encryption algorithm to generate the RSA or EC JWT.',
+      requiresArg: true,
+      demandOption: true,
+      choices: ['RS256', 'ES256'],
+      type: 'string',
+    },
+    numMessages: {
+      default: 100,
+      description: 'Number of messages to publish.',
+      requiresArg: true,
+      type: 'number',
+    },
+    tokenExpMins: {
+      default: 20,
+      description: 'Minutes to JWT token expiration.',
+      requiresArg: true,
+      type: 'number',
+    },
+    httpBridgeAddress: {
+      default: 'cloudiotdevice.googleapis.com',
+      description: 'HTTP bridge address.',
+      requiresArg: true,
+      type: 'string',
+    },
+    messageType: {
+      default: 'events',
+      description: 'Message type to publish.',
+      requiresArg: true,
+      choices: ['events', 'state'],
+      type: 'string',
+    },
+  })
+  .example(
+    'node $0 cloudiot_http_example.js --projectId=blue-jet-123 --registryId=my-registry --deviceId=my-node-device --privateKeyFile=../rsaPrivate.pem --algorithm=RS256'
+  )
+  .wrap(120)
+  .recommendCommands()
+  .epilogue('For more information, see https://cloud.google.com/iot-core/docs')
+  .help()
+  .strict();
+
+// [START iot_http_variables]
+// A unique string that identifies this device. For Google Cloud IoT Core, it
+// must be in the format below.
+
+let iatTime = parseInt(Date.now() / 1000);
+const authToken = createJwt(
+  argv.projectId,
+  argv.privateKeyFile,
+  argv.algorithm
+);
+const devicePath = `projects/${argv.projectId}/locations/${argv.cloudRegion}/registries/${argv.registryId}/devices/${argv.deviceId}`;
+
+// The request path, set accordingly depending on the message type.
+const pathSuffix =
+  argv.messageType === 'events' ? ':publishEvent' : ':setState';
+const urlBase = `https://${argv.httpBridgeAddress}/v1/${devicePath}`;
+const url = `${urlBase}${pathSuffix}`;
+// [END iot_http_variables]
+
+// Publish numMessages message asynchronously, starting from message
+// messageCount. Telemetry events are published at a rate of 1 per second and
+// states at a rate of 1 every 2 seconds.
+// [START iot_http_publish]
+const publishAsync = async (authToken, messageCount, numMessages) => {
+  const payload = `${argv.registryId}/${argv.deviceId}-payload-${messageCount}`;
+  console.log('Publishing message:', payload);
+  const binaryData = Buffer.from(payload).toString('base64');
+  const postData =
+    argv.messageType === 'events'
+      ? {
+          binary_data: binaryData,
+        }
+      : {
+          state: {
+            binary_data: binaryData,
+          },
+        };
+
+  const options = {
+    url: url,
+    headers: {
+      authorization: `Bearer ${authToken}`,
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    },
+    data: postData,
+    method: 'POST',
+    retry: true,
+  };
+
+  // Send events for high-frequency updates, update state only occasionally.
+  const delayMs = argv.messageType === 'events' ? 1000 : 2000;
+  console.log(JSON.stringify(request));
+  try {
+    await request(options);
+    console.log('Message sent.');
+  } catch (err) {
+    console.error('Received error: ', err);
+    if (err.response && err.response.data && err.response.data.error) {
+      console.error(
+        `Received error: ${JSON.stringify(err.response.data.error)}`
+      );
+    }
+  }
+  if (messageCount < numMessages) {
+    // If we have published fewer than numMessage messages, publish payload
+    // messageCount + 1.
+    setTimeout(() => {
+      const secsFromIssue = parseInt(Date.now() / 1000) - iatTime;
+      if (secsFromIssue > argv.tokenExpMins * 60) {
+        iatTime = parseInt(Date.now() / 1000);
+        console.log(`\tRefreshing token after ${secsFromIssue} seconds.`);
+        authToken = createJwt(
+          argv.projectId,
+          argv.privateKeyFile,
+          argv.algorithm
+        );
+      }
+
+      publishAsync(authToken, messageCount + 1, numMessages);
+    }, delayMs);
+  }
+};
+// [END iot_http_publish]
+
+// [START iot_http_getconfig]
+const getConfig = async (authToken, version) => {
+  console.log(`Getting config from URL: ${urlBase}`);
+
+  const options = {
+    url: `${urlBase}/config?local_version=${version}`,
+    headers: {
+      authorization: `Bearer ${authToken}`,
+      'content-type': 'application/json',
+      'cache-control': 'no-cache',
+    },
+    retry: true,
+  };
+  try {
+    const res = await request(options);
+    console.log('Received config', JSON.stringify(res.data));
+  } catch (err) {
+    console.error('Received error: ', err);
+    if (err.response && err.response.data && err.response.data.error) {
+      console.error(
+        `Received error: ${JSON.stringify(err.response.data.error)}`
+      );
+    }
+  }
+};
+// [END iot_http_getconfig]
+
+// [START iot_run_http]
+
+// Print latest configuration
+getConfig(authToken, 0);
+
+// Publish messages.
+publishAsync(authToken, 1, argv.numMessages);
+// [END iot_run_http]
diff --git a/samples/http_example/package.json b/samples/http_example/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..942a9895b0651be427c91f440576ce507c28d033
--- /dev/null
+++ b/samples/http_example/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "nodejs-docs-samples-iot-http-example",
+  "version": "0.0.1",
+  "description": "HTTP Example for Google Cloud IoT Core using NodeJS.",
+  "license": "Apache-2.0",
+  "author": "Google Inc.",
+  "main": "cloudiot_http_example_nodejs.js",
+  "files": [
+    "*.js"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/googleapis/nodejs-iot.git"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "test": "mocha --timeout=60000"
+  },
+  "dependencies": {
+    "gaxios": "^4.0.0",
+    "jsonwebtoken": "^8.5.0",
+    "yargs": "^16.0.0"
+  },
+  "devDependencies": {
+    "@google-cloud/pubsub": "^3.0.0",
+    "mocha": "^8.1.1",
+    "uuid": "^8.0.0"
+  }
+}
diff --git a/samples/http_example/test/cloudiot_http_example.test.js b/samples/http_example/test/cloudiot_http_example.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..a606c216933497cc64489238cf75bc7da6aa88d3
--- /dev/null
+++ b/samples/http_example/test/cloudiot_http_example.test.js
@@ -0,0 +1,114 @@
+// Copyright 2020 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 {PubSub} = require('@google-cloud/pubsub');
+const assert = require('assert');
+const cp = require('child_process');
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+const uuid = require('uuid');
+const {after, before, it} = require('mocha');
+
+const deviceId = 'test-node-device';
+const topicName = `nodejs-docs-samples-test-iot-${uuid.v4()}`;
+const registryName = `nodejs-test-registry-iot-${uuid.v4()}`;
+const helper = 'node ../manager/manager.js';
+const cmd = `node cloudiot_http_example.js --registryId="${registryName}" --deviceId="${deviceId}" `;
+const installDeps = 'npm install';
+
+assert.ok(execSync(installDeps, '../manager'));
+before(async () => {
+  assert(
+    process.env.GCLOUD_PROJECT,
+    'Must set GCLOUD_PROJECT environment variable!'
+  );
+  assert(
+    process.env.GOOGLE_APPLICATION_CREDENTIALS,
+    'Must set GOOGLE_APPLICATION_CREDENTIALS environment variable!'
+  );
+  const pubsub = new PubSub();
+  const [topic] = await pubsub.createTopic(topicName);
+  console.log(`Topic ${topic.name} created.`);
+});
+
+after(async () => {
+  const pubsub = new PubSub();
+  const topic = pubsub.topic(topicName);
+  await topic.delete();
+  console.log(`Topic ${topic.name} deleted.`);
+});
+
+it('should receive configuration message', async () => {
+  const localDevice = 'test-rsa-device';
+  const localRegName = `${registryName}-rsa256config`;
+
+  await execSync(`${helper} setupIotTopic ${topicName}`);
+  await execSync(`${helper} createRegistry ${localRegName} ${topicName}`);
+  await execSync(
+    `${helper} createRsa256Device ${localDevice} ${localRegName} ../resources/rsa_cert.pem`
+  );
+  const output = await execSync(
+    `${cmd} --messageType=events --numMessages=1 --privateKeyFile=../resources/rsa_private.pem --algorithm=RS256`
+  );
+
+  assert.strictEqual(new RegExp(/Getting config/).test(output), true);
+
+  // Check / cleanup
+  await execSync(`${helper} getDeviceState ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteDevice ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteRegistry ${localRegName}`);
+});
+
+it('should send event message', async () => {
+  const localDevice = 'test-rsa-device';
+  const localRegName = `${registryName}-rsa256`;
+
+  await execSync(`${helper} setupIotTopic ${topicName}`);
+  await execSync(`${helper} createRegistry ${localRegName} ${topicName}`);
+  await execSync(
+    `${helper} createRsa256Device ${localDevice} ${localRegName} ../resources/rsa_cert.pem`
+  );
+
+  const output = await execSync(
+    `${cmd} --messageType=events --numMessages=1 --privateKeyFile=../resources/rsa_private.pem --algorithm=RS256`
+  );
+
+  assert.strictEqual(new RegExp(/Publishing message/).test(output), true);
+
+  // Check / cleanup
+  await execSync(`${helper} getDeviceState ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteDevice ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteRegistry ${localRegName}`);
+});
+
+it('should send state message', async () => {
+  const localDevice = 'test-rsa-device';
+  const localRegName = `${registryName}-rsa256`;
+  await execSync(`${helper} setupIotTopic ${topicName}`);
+  await execSync(`${helper} createRegistry ${localRegName} ${topicName}`);
+  await execSync(
+    `${helper} createRsa256Device ${localDevice} ${localRegName} ../resources/rsa_cert.pem`
+  );
+
+  const output = await execSync(
+    `${cmd} --messageType=state --numMessages=1 --privateKeyFile=../resources/rsa_private.pem --algorithm=RS256`
+  );
+  assert.strictEqual(new RegExp(/Publishing message/).test(output), true);
+
+  // Check / cleanup
+  await execSync(`${helper} getDeviceState ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteDevice ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteRegistry ${localRegName}`);
+});
diff --git a/samples/manager/.gitignore b/samples/manager/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..59ec5ff4a2061548386f38316be104ca30deba0f
--- /dev/null
+++ b/samples/manager/.gitignore
@@ -0,0 +1 @@
+resources/*
diff --git a/samples/manager/README.md b/samples/manager/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3e70973e4b75b7c2688ba028af77c696a25fb8be
--- /dev/null
+++ b/samples/manager/README.md
@@ -0,0 +1,61 @@
+<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
+
+# Google Cloud IoT Core NodeJS Device Management example
+
+This sample app demonstrates device management for Google Cloud IoT Core.
+
+Note that before you run this sample, you must configure a Google Cloud PubSub
+topic for Cloud IoT as described in the parent README.
+
+# Setup
+
+Run the following command to install the library dependencies for NodeJS:
+
+    npm install
+
+# Running the sample
+
+    Commands:
+      createRsa256Device <deviceId> <registryId> <rsaPath>  Creates an RSA256 device.
+      createEs256Device <deviceId> <registryId> <esPath>    Creates an ES256 device.
+      createUnauthDevice <deviceId> <registryId>            Creates a device without authorization.
+      createRegistry <registryId> <pubsubTopic>             Creates a device registry.
+      createIotTopic <pubsubTopic>                          Creates and configures a PubSub topic for Cloud IoT Core.
+      setupIotTopic <pubsubTopic>                           Configures the PubSub topic for Cloud IoT Core.
+      deleteDevice <deviceId> <registryId>                  Deletes a device from the device registry.
+      clearRegistry <registryId>                            !!Be careful! Removes all devices and then deletes a device
+                                                            registry!!
+      deleteRegistry <registryId>                           Deletes a device registry.
+      getDevice <deviceId> <registryId>                     Retrieves device info given a device ID.
+      listDevices <registryId>                              Lists the devices in a given registry.
+      patchEs256 <deviceId> <registryId> <es256Path>        Patches a device with ES256 authorization credentials.
+      patchRsa256 <deviceId> <registryId> <rsa256Path>      Patches a device with RSA256 authentication credentials.
+      setConfig <deviceId> <registryId> <configuration> <version>  Sets a devices configuration to the specified data.
+
+    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]
+      --help                Show help                                                                              [boolean]
+      --cloudRegion, -c                                                                    [string] [default: "us-central1"]
+
+    Examples:
+      node manager.js createEs256Device my-es-device my-registry ../ec_public.pem
+      node manager.js createRegistry my-registry my-iot-topic \
+        --serviceAccount=$HOME/creds_iot.json \
+        --projectId=my-project-id --cloudRegion=from-console
+      node manager.js createRsa256Device my-rsa-device my-registry ../rsa_cert.pem
+      node manager.js createUnauthDevice my-device my-registry
+      node manager.js deleteDevice my-device my-registry
+      node manager.js deleteRegistry my-device my-registry
+      node manager.js getDevice my-device my-registry
+      node manager.js getDeviceState my-device my-registry
+      node manager.js getRegistry my-registry -cloudRegion europe-west1
+      node manager.js listDevices my-node-registry
+      node manager.js listRegistries -c asia-east1 -p your-project -s path/svc.json
+      node manager.js patchRsa256 my-device my-registry ../rsa_cert.pem
+      node manager.js patchEs256 my-device my-registry ../ec_public.pem
+      node manager.js setConfig my-device my-registry "test" 0
+      node manager.js setupTopic my-iot-topic --serviceAccount=$HOME/creds_iot.json --projectId=my-project-id
+
+    For more information, see https://cloud.google.com/iot-core/docs
diff --git a/samples/manager/manager.js b/samples/manager/manager.js
new file mode 100644
index 0000000000000000000000000000000000000000..2b956390a30a09963c36851ddcbd6ae57df5a040
--- /dev/null
+++ b/samples/manager/manager.js
@@ -0,0 +1,1864 @@
+// Copyright 2020 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 {readFileSync} = require('fs');
+
+// Configures the topic for Cloud IoT Core.
+const setupIotTopic = async topicName => {
+  const {PubSub} = require('@google-cloud/pubsub');
+
+  const pubsub = new PubSub();
+  const topic = pubsub.topic(topicName);
+  const serviceAccount = 'serviceAccount:cloud-iot@system.gserviceaccount.com';
+
+  async function setPolicy() {
+    // Construct request
+    let policy = await topic.iam.getPolicy();
+    policy = policy[0] || {};
+
+    policy.bindings || (policy.bindings = []);
+    console.log(JSON.stringify(policy, null, 2));
+
+    let hasRole = false;
+    let binding = {
+      role: 'roles/pubsub.publisher',
+      members: [serviceAccount],
+    };
+
+    policy.bindings.forEach(_binding => {
+      if (_binding.role === binding.role) {
+        binding = _binding;
+        hasRole = true;
+        return false;
+      }
+    });
+
+    if (hasRole) {
+      binding.members || (binding.members = []);
+      if (binding.members.indexOf(serviceAccount) === -1) {
+        binding.members.push(serviceAccount);
+      }
+    } else {
+      policy.bindings.push(binding);
+    }
+
+    // Updates the IAM policy for the topic
+    const [updatedPolicy] = await topic.iam.setPolicy(policy);
+    console.log(JSON.stringify(updatedPolicy, null, 2));
+  }
+
+  setPolicy();
+};
+
+const createIotTopic = async topicName => {
+  // Imports the Google Cloud client library
+  const {PubSub} = require('@google-cloud/pubsub');
+
+  // Instantiates a client
+  const pubsub = new PubSub();
+
+  await pubsub.createTopic(topicName);
+  await setupIotTopic(topicName);
+};
+
+// Lookup the registry, assuming that it exists.
+const lookupRegistry = async (registryId, projectId, cloudRegion) => {
+  // [START iot_lookup_registry]
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  const registryName = iotClient.registryPath(
+    projectId,
+    cloudRegion,
+    registryId
+  );
+
+  async function getDeviceRegistry() {
+    // Construct request
+    const [response] = await iotClient.getDeviceRegistry({name: registryName});
+    console.log(response);
+  }
+
+  getDeviceRegistry();
+  // [END iot_lookup_registry]
+};
+
+const createRegistry = async (
+  registryId,
+  projectId,
+  cloudRegion,
+  pubsubTopicId
+) => {
+  // [START iot_create_registry]
+  // Client retrieved in callback
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  // function errCb = lookupRegistry; // Lookup registry if already exists.
+  const iot = require('@google-cloud/iot');
+
+  // Lookup the pubsub topic
+  const topicPath = `projects/${projectId}/topics/${pubsubTopicId}`;
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function createDeviceRegistry() {
+    // Construct request
+    const newParent = iotClient.locationPath(projectId, cloudRegion);
+    const deviceRegistry = {
+      eventNotificationConfigs: [
+        {
+          pubsubTopicName: topicPath,
+        },
+      ],
+      id: registryId,
+    };
+    const request = {
+      parent: newParent,
+      deviceRegistry: deviceRegistry,
+    };
+
+    const [response] = await iotClient.createDeviceRegistry(request);
+
+    console.log('Successfully created registry');
+    console.log(response);
+  }
+
+  createDeviceRegistry();
+  // [END iot_create_registry]
+};
+
+// Create a new device with a given public key format
+const createDevice = async (
+  deviceId,
+  registryId,
+  projectId,
+  cloudRegion,
+  publicKeyFormat,
+  publicKeyFile
+) => {
+  // [START iot_create_device]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function createDevice() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
+    const device = {
+      id: deviceId,
+      credentials: [
+        {
+          publicKey: {
+            format: publicKeyFormat,
+            key: readFileSync(publicKeyFile).toString(),
+          },
+        },
+      ],
+    };
+
+    const request = {
+      parent: regPath,
+      device,
+    };
+
+    const [response] = await iotClient.createDevice(request);
+    console.log('Created device', response);
+  }
+
+  createDevice();
+  // [END iot_create_device]
+};
+
+// Create a new device with the given id. The body defines the parameters for
+// the device, such as authentication.
+const createUnauthDevice = async (
+  deviceId,
+  registryId,
+  projectId,
+  cloudRegion
+) => {
+  // [START iot_create_unauth_device]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-unauth-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function createDevice() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
+    const device = {id: deviceId};
+    const request = {
+      parent: regPath,
+      device,
+    };
+
+    const [response] = await iotClient.createDevice(request);
+    console.log('Created device', response);
+  }
+
+  createDevice();
+  // [END iot_create_unauth_device]
+};
+
+// Create a device using RSA256 for authentication.
+const createRsaDevice = async (
+  deviceId,
+  registryId,
+  projectId,
+  cloudRegion,
+  rsaCertificateFile
+) => {
+  // [START iot_create_rsa_device]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-rsa-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function createDevice() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
+    const device = {
+      id: deviceId,
+      credentials: [
+        {
+          publicKey: {
+            format: 'RSA_X509_PEM',
+            key: readFileSync(rsaCertificateFile).toString(),
+          },
+        },
+      ],
+    };
+
+    const request = {
+      parent: regPath,
+      device,
+    };
+
+    const [response] = await iotClient.createDevice(request);
+    console.log('Created device', response);
+  }
+
+  createDevice();
+  // [END iot_create_rsa_device]
+};
+
+// Create a device using ES256 for authentication.
+const createEsDevice = async (
+  deviceId,
+  registryId,
+  projectId,
+  cloudRegion,
+  esCertificateFile
+) => {
+  // [START iot_create_es_device]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-es-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function createDevice() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
+    const device = {
+      id: deviceId,
+      credentials: [
+        {
+          publicKey: {
+            format: 'ES256_PEM',
+            key: readFileSync(esCertificateFile).toString(),
+          },
+        },
+      ],
+    };
+    const request = {
+      parent: regPath,
+      device,
+    };
+
+    const [response] = await iotClient.createDevice(request);
+    console.log('Created device', response);
+  }
+
+  createDevice();
+  // [END iot_create_es_device]
+};
+
+// Add RSA256 authentication to the given device.
+const patchRsa256ForAuth = async (
+  deviceId,
+  registryId,
+  rsaPublicKeyFile,
+  projectId,
+  cloudRegion
+) => {
+  // [START iot_patch_rsa]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-rsa-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function updateDevice() {
+    // Construct request
+    const devPath = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    const device = {
+      name: devPath,
+      credentials: [
+        {
+          publicKey: {
+            format: 'RSA_X509_PEM',
+            key: readFileSync(rsaPublicKeyFile).toString(),
+          },
+        },
+      ],
+    };
+
+    const [response] = await iotClient.updateDevice({
+      device: device,
+      updateMask: {paths: ['credentials']},
+    });
+
+    console.log('Patched device:', deviceId);
+    console.log('Response', response);
+  }
+
+  updateDevice();
+  // [END iot_patch_rsa]
+};
+
+// Add ES256 authentication to the given device.
+const patchEs256ForAuth = async (
+  deviceId,
+  registryId,
+  esPublicKeyFile,
+  projectId,
+  cloudRegion
+) => {
+  // [START iot_patch_es]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-es-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function updateDevice() {
+    // Construct request
+    const devPath = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    const device = {
+      name: devPath,
+      credentials: [
+        {
+          publicKey: {
+            format: 'ES256_PEM',
+            key: readFileSync(esPublicKeyFile).toString(),
+          },
+        },
+      ],
+    };
+
+    const [response] = await iotClient.updateDevice({
+      device: device,
+      updateMask: {paths: ['credentials']},
+    });
+
+    console.log('Patched device:', deviceId);
+    console.log('Response', response);
+  }
+
+  updateDevice();
+  // [END iot_patch_es]
+};
+
+// List all of the devices in the given registry.
+const listDevices = async (registryId, projectId, cloudRegion) => {
+  // [START iot_list_devices]
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDevices() {
+    // Construct request
+    const parentName = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+
+    // See full list of device fields: https://cloud.google.com/iot/docs/reference/cloudiot/rest/v1/projects.locations.registries.devices
+    // Warning! Use snake_case field names.
+    const fieldMask = {
+      paths: [
+        'id',
+        'name',
+        'num_id',
+        'credentials',
+        'last_heartbeat_time',
+        'last_event_time',
+        'last_state_time',
+        'last_config_ack_time',
+        'last_config_send_time',
+        'blocked',
+        'last_error_time',
+        'last_error_status',
+        'config',
+        'state',
+        'log_level',
+        'metadata',
+        'gateway_config',
+      ],
+    };
+
+    const [response] = await iotClient.listDevices({
+      parent: parentName,
+      fieldMask,
+    });
+    const devices = response;
+
+    if (devices.length > 0) {
+      console.log('Current devices in registry:');
+    } else {
+      console.log('No devices in registry.');
+    }
+
+    for (let i = 0; i < devices.length; i++) {
+      const device = devices[i];
+      console.log(`Device ${i}: `, device);
+    }
+  }
+
+  listDevices();
+  // [END iot_list_devices]
+};
+
+// List all of the registries in the given project.
+const listRegistries = async (projectId, cloudRegion) => {
+  // [START iot_list_registries]
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  const iot = require('@google-cloud/iot');
+
+  const newClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDeviceRegistries() {
+    // Construct request
+    // Iterate over all elements.
+    const formattedParent = newClient.locationPath(projectId, cloudRegion);
+
+    const [response] = await newClient.listDeviceRegistries({
+      parent: formattedParent,
+    });
+    const resources = response;
+    console.log('Current registries in project:\n', resources);
+  }
+
+  listDeviceRegistries();
+  // [END iot_list_registries]
+};
+
+// Delete the given device from the registry.
+const deleteDevice = async (deviceId, registryId, projectId, cloudRegion) => {
+  // [START iot_delete_device]
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function deleteDevice() {
+    // Construct request
+    const devPath = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    const [responses] = await iotClient.deleteDevice({name: devPath});
+    console.log('Successfully deleted device', responses);
+  }
+
+  deleteDevice();
+  // [END iot_delete_device]
+};
+
+// Clear the given registry by removing all devices and deleting the registry.
+const clearRegistry = async (registryId, projectId, cloudRegion) => {
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient();
+
+  let devices;
+  try {
+    [devices] = await iotClient.listDeviceRegistries({
+      parent: iotClient.locationPath(projectId, cloudRegion),
+    });
+  } catch (err) {
+    console.error('Could not list devices', err);
+    return;
+  }
+
+  // Delete devices in registry
+  console.log('Current devices in registry:', devices);
+  if (devices) {
+    const promises = devices.map((device, index) => {
+      console.log(`${device.id} [${index}/${devices.length}] removed`);
+      return deleteDevice(device.id, registryId, projectId, cloudRegion);
+    });
+    await Promise.all(promises);
+  }
+
+  async function deleteRegistry() {
+    const registryName = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+    await iotClient.deleteDeviceRegistry({
+      name: registryName,
+    });
+    console.log(`Successfully deleted registry ${registryName}`);
+  }
+
+  // Delete registry
+  deleteRegistry();
+};
+
+// Delete the given registry. Note that this will only succeed if the registry
+// is empty.
+const deleteRegistry = async (registryId, projectId, cloudRegion) => {
+  // [START iot_delete_registry]
+  // Client retrieved in callback
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function deleteDeviceRegistry() {
+    // Construct request
+    const registryName = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+
+    const [response] = await iotClient.deleteDeviceRegistry({
+      name: registryName,
+    });
+    console.log(response);
+    console.log('Successfully deleted registry');
+  }
+
+  deleteDeviceRegistry();
+  // [END iot_delete_registry]
+};
+
+// Retrieve the given device from the registry.
+const getDevice = async (deviceId, registryId, projectId, cloudRegion) => {
+  // [START iot_get_device]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function getDevice() {
+    // Construct request
+    const devicePath = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    // See full list of device fields: https://cloud.google.com/iot/docs/reference/cloudiot/rest/v1/projects.locations.registries.devices
+    // Warning! Use snake_case field names.
+    const fieldMask = {
+      paths: [
+        'id',
+        'name',
+        'num_id',
+        'credentials',
+        'last_heartbeat_time',
+        'last_event_time',
+        'last_state_time',
+        'last_config_ack_time',
+        'last_config_send_time',
+        'blocked',
+        'last_error_time',
+        'last_error_status',
+        'config',
+        'state',
+        'log_level',
+        'metadata',
+        'gateway_config',
+      ],
+    };
+
+    const [response] = await iotClient.getDevice({
+      name: devicePath,
+      fieldMask,
+    });
+    const data = response;
+
+    console.log('Found device:', deviceId, data);
+  }
+
+  getDevice();
+  // [END iot_get_device]
+};
+
+// Retrieve the given device's state from the registry.
+const getDeviceState = async (deviceId, registryId, projectId, cloudRegion) => {
+  // [START iot_get_device_state]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDeviceStates() {
+    const devicePath = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    const [response] = await iotClient.listDeviceStates({name: devicePath});
+    const states = response.deviceStates;
+    if (states.length === 0) {
+      console.log(`No States for device: ${deviceId}`);
+    } else {
+      console.log(`States for device: ${deviceId}`);
+    }
+
+    for (let i = 0; i < states.length; i++) {
+      const state = states[i];
+      console.log(
+        'State:',
+        state,
+        '\nData:\n',
+        state.binaryData.toString('utf8')
+      );
+    }
+  }
+
+  listDeviceStates();
+  // [END iot_get_device_state]
+};
+
+// Retrieve the given device's configuration history from the registry.
+const getDeviceConfigs = async (
+  deviceId,
+  registryId,
+  projectId,
+  cloudRegion
+) => {
+  // [START iot_get_device_configs]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDeviceConfigVersions() {
+    // Construct request
+    const devicePath = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    const [response] = await iotClient.listDeviceConfigVersions({
+      name: devicePath,
+    });
+    const configs = response.deviceConfigs;
+
+    if (configs.length === 0) {
+      console.log(`No configs for device: ${deviceId}`);
+    } else {
+      console.log('Configs:');
+    }
+
+    for (let i = 0; i < configs.length; i++) {
+      const config = configs[i];
+      console.log(
+        'Config:',
+        config,
+        '\nData:\n',
+        config.binaryData.toString('utf8')
+      );
+    }
+  }
+
+  listDeviceConfigVersions();
+  // [END iot_get_device_configs]
+};
+
+// Send configuration data to device.
+const setDeviceConfig = async (
+  deviceId,
+  registryId,
+  projectId,
+  cloudRegion,
+  data,
+  version
+) => {
+  // [START iot_set_device_config]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  // const data = 'test-data';
+  // const version = 0;
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function modifyCloudToDeviceConfig() {
+    // Construct request
+    const formattedName = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    const binaryData = Buffer.from(data).toString('base64');
+    const request = {
+      name: formattedName,
+      versionToUpdate: version,
+      binaryData: binaryData,
+    };
+
+    const [response] = await iotClient.modifyCloudToDeviceConfig(request);
+    console.log('Success:', response);
+  }
+
+  modifyCloudToDeviceConfig();
+  // [END iot_set_device_config]
+};
+
+// sends a command to a specified device subscribed to the commands topic
+const sendCommand = async (
+  deviceId,
+  registryId,
+  projectId,
+  cloudRegion,
+  commandMessage
+) => {
+  // [START iot_send_command]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-device';
+  // const commandMessage = 'message for device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function sendCommand() {
+    // Construct request
+    const formattedName = iotClient.devicePath(
+      projectId,
+      cloudRegion,
+      registryId,
+      deviceId
+    );
+
+    const binaryData = Buffer.from(commandMessage);
+
+    const request = {
+      name: formattedName,
+      binaryData: binaryData,
+    };
+
+    const [response] = await iotClient.sendCommandToDevice(request);
+    console.log('Sent command: ', response);
+  }
+
+  sendCommand();
+  // [END iot_send_command]
+};
+
+// Retrieve the given device from the registry.
+const getRegistry = async (registryId, projectId, cloudRegion) => {
+  // [START iot_get_registry]
+  // Client retrieved in callback
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  const registryName = iotClient.registryPath(
+    projectId,
+    cloudRegion,
+    registryId
+  );
+
+  async function getDeviceRegistry() {
+    // Construct request
+    const [response] = await iotClient.getDeviceRegistry({name: registryName});
+
+    console.log('Found registry:', registryId);
+    console.log(response);
+  }
+
+  getDeviceRegistry();
+  // [END iot_get_registry]
+};
+
+// Retrieves the IAM policy for a given registry.
+const getIamPolicy = async (registryId, projectId, cloudRegion) => {
+  // [START iot_get_iam_policy]
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function getIamPolicy() {
+    // Construct request
+    const formattedResource = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+
+    let bindings;
+    const [response] = await iotClient.getIamPolicy({
+      resource: formattedResource,
+    });
+
+    bindings = response.bindings;
+    const etag = response.etag;
+
+    console.log('ETAG:', etag);
+    bindings = bindings || [];
+
+    bindings.forEach(_binding => {
+      console.log(`Role: ${_binding.role}`);
+      _binding.members || (_binding.members = []);
+      _binding.members.forEach(_member => {
+        console.log(`\t${_member}`);
+      });
+    });
+  }
+
+  getIamPolicy();
+
+  // [END iot_get_iam_policy]
+};
+
+// Sets the IAM permissions for a given registry to a single member / role.
+const setIamPolicy = async (
+  registryId,
+  projectId,
+  cloudRegion,
+  member,
+  role
+) => {
+  // [START iot_set_iam_policy]
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function setIamPolicy() {
+    // Construct request
+    const resource = iotClient.registryPath(projectId, cloudRegion, registryId);
+
+    const policy = {
+      bindings: [
+        {
+          members: [member],
+          role: role,
+        },
+      ],
+    };
+
+    const request = {
+      resource: resource,
+      policy: policy,
+    };
+
+    let bindings;
+
+    const [response] = await iotClient.setIamPolicy(request);
+
+    bindings = response.bindings;
+    const etag = response.etag;
+
+    console.log('ETAG:', etag);
+    bindings = bindings || [];
+
+    bindings.forEach(_binding => {
+      console.log(`Role: ${_binding.role}`);
+      _binding.members || (_binding.members = []);
+      _binding.members.forEach(_member => {
+        console.log(`\t${_member}`);
+      });
+    });
+  }
+
+  setIamPolicy();
+  // [END iot_set_iam_policy]
+};
+
+// Creates a gateway.
+const createGateway = async (
+  projectId,
+  cloudRegion,
+  registryId,
+  gatewayId,
+  publicKeyFormat,
+  publicKeyFile,
+  gatewayAuthMethod
+) => {
+  // [START iot_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 gatewayAuthMethod = 'ASSOCIATION_ONLY';
+  const iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function createDevice() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
+
+    console.log('Creating gateway:', gatewayId);
+
+    let credentials = [];
+
+    // if public key format and path are specified, use those
+    if (publicKeyFormat && publicKeyFile) {
+      credentials = [
+        {
+          publicKey: {
+            format: publicKeyFormat,
+            key: readFileSync(publicKeyFile).toString(),
+          },
+        },
+      ];
+    }
+
+    const device = {
+      id: gatewayId,
+      credentials: credentials,
+      gatewayConfig: {
+        gatewayType: 'GATEWAY',
+        gatewayAuthMethod: gatewayAuthMethod,
+      },
+    };
+
+    const request = {
+      parent: regPath,
+      device,
+    };
+
+    const [response] = await iotClient.createDevice(request);
+    console.log('Created device:', response);
+  }
+
+  createDevice();
+  // [END iot_create_gateway]
+};
+
+// Binds a device to a gateway so that it can be attached.
+const bindDeviceToGateway = async (
+  projectId,
+  cloudRegion,
+  registryId,
+  deviceId,
+  gatewayId
+) => {
+  // [START iot_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 iot = require('@google-cloud/iot');
+
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function bindDeviceToGateway() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
+
+    const bindRequest = {
+      parent: regPath,
+      deviceId: deviceId,
+      gatewayId: gatewayId,
+    };
+
+    console.log(`Binding device: ${deviceId}`);
+
+    await iotClient.bindDeviceToGateway(bindRequest);
+
+    console.log(`Bound ${deviceId} to`, gatewayId);
+  }
+
+  bindDeviceToGateway();
+  // [END iot_bind_device_to_gateway]
+};
+
+// Unbinds a device from a gateway.
+const unbindDeviceFromGateway = async (
+  projectId,
+  cloudRegion,
+  registryId,
+  deviceId,
+  gatewayId
+) => {
+  // [START iot_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 iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function unbindDeviceFromGateway() {
+    // Construct request
+    const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
+
+    const unbindRequest = {
+      parent: regPath,
+      deviceId: deviceId,
+      gatewayId: gatewayId,
+    };
+
+    await iotClient.unbindDeviceFromGateway(unbindRequest);
+    console.log(`Unbound ${deviceId} from`, gatewayId);
+  }
+
+  unbindDeviceFromGateway();
+  // [END iot_unbind_device_to_gateway]
+};
+
+// Unbinds the given device from all gateways
+const unbindDeviceFromAllGateways = async (
+  projectId,
+  cloudRegion,
+  registryId,
+  deviceId
+) => {
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({});
+
+  let device;
+  const devicePath = iotClient.devicePath(
+    projectId,
+    cloudRegion,
+    registryId,
+    deviceId
+  );
+  async function getDevice() {
+    const [response] = await iotClient.getDevice({name: devicePath});
+    device = response;
+    console.log(`Found Device ${device.id}`);
+  }
+
+  try {
+    getDevice();
+  } catch (err) {
+    console.error('Could not find device:', deviceId);
+    console.error('Trace:', err);
+    return;
+  }
+
+  async function unbindDeviceFromAllGateways() {
+    // Construct request
+    if (device) {
+      const parentName = iotClient.registryPath(
+        projectId,
+        cloudRegion,
+        registryId
+      );
+      const [response] = await iotClient.listDevices({
+        parent: parentName,
+        gatewayListOptions: {associationsDeviceId: deviceId},
+      });
+      const gateways = response;
+      if (gateways && gateways.length > 0) {
+        for (let i = 0; i < gateways.length; i++) {
+          const gatewayId = gateways[i].id;
+          unbindDeviceFromGateway(
+            projectId,
+            cloudRegion,
+            registryId,
+            deviceId,
+            gatewayId
+          );
+        }
+      }
+    }
+  }
+
+  unbindDeviceFromAllGateways();
+};
+
+const unbindAllDevices = async (projectId, cloudRegion, registryId) => {
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDevices() {
+    // Construct request
+    const parentName = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+
+    const [response] = await iotClient.listDevices({parent: parentName});
+    const devices = response;
+    if (devices.length > 0) {
+      console.log('Current devices in registry:');
+    } else {
+      console.log('No devices in registry.');
+    }
+
+    for (let i = 0; i < devices.length; i++) {
+      const device = devices[i];
+      unbindDeviceFromAllGateways(
+        projectId,
+        cloudRegion,
+        registryId,
+        device.id
+      );
+    }
+  }
+
+  listDevices();
+};
+
+// Lists gateways in a registry.
+const listGateways = async (projectId, cloudRegion, registryId) => {
+  // [START iot_list_gateways]
+  // const cloudRegion = 'us-central1';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDevices() {
+    // Construct request
+    const registryPath = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+
+    console.log('Current gateways in registry:');
+    const [response] = await iotClient.listDevices({
+      parent: registryPath,
+      fieldMask: {paths: ['config', 'gateway_config']},
+    });
+    const devices = response;
+
+    devices.forEach(device => {
+      if (
+        device.gatewayConfig !== undefined &&
+        device.gatewayConfig.gatewayType === 'GATEWAY'
+      ) {
+        console.log('----\n', device);
+      }
+    });
+  }
+
+  listDevices();
+  // [END iot_list_gateways]
+};
+
+// Lists devices bound to a gateway.
+const listDevicesForGateway = async (
+  projectId,
+  cloudRegion,
+  registryId,
+  gatewayId
+) => {
+  // [START iot_list_devices_for_gateway]
+  // const cloudRegion = 'us-central1';
+  // const gatewayId = 'my-gateway';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDevices() {
+    // Construct request
+    const parentName = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+    const [response] = await iotClient.listDevices({
+      parent: parentName,
+      gatewayListOptions: {associationsGatewayId: gatewayId},
+    });
+    const devices = response;
+
+    if (devices.length > 0) {
+      console.log('Current devices bound to gateway: ', gatewayId);
+    } else {
+      console.log('No devices bound to this gateway.');
+    }
+
+    for (let i = 0; i < devices.length; i++) {
+      const device = devices[i];
+      console.log(`\tDevice: ${device.numId}: ${device.id}`);
+    }
+  }
+
+  listDevices();
+  // [END iot_list_devices_for_gateway]
+};
+
+// Lists gateways a given device is bound to.
+const listGatewaysForDevice = async (
+  projectId,
+  cloudRegion,
+  registryId,
+  deviceId
+) => {
+  // [START iot_list_gateways_for_device]
+  // const cloudRegion = 'us-central1';
+  // const deviceId = 'my-device';
+  // const projectId = 'adjective-noun-123';
+  // const registryId = 'my-registry';
+  const iot = require('@google-cloud/iot');
+  const iotClient = new iot.v1.DeviceManagerClient({
+    // optional auth parameters.
+  });
+
+  async function listDevices() {
+    // Construct request
+    const parentName = iotClient.registryPath(
+      projectId,
+      cloudRegion,
+      registryId
+    );
+
+    const [response] = await iotClient.listDevices({
+      parent: parentName,
+      gatewayListOptions: {associationsDeviceId: deviceId},
+    });
+    const devices = response;
+
+    if (devices.length > 0) {
+      console.log('Current gateways for: ', deviceId);
+    } else {
+      console.log('No gateways associated with this device.');
+    }
+
+    for (let i = 0; i < devices.length; i++) {
+      const device = devices[i];
+      console.log(`\tDevice: ${device.numId}: ${device.id}`);
+    }
+  }
+
+  listDevices();
+  // [END iot_list_gateways_for_device]
+};
+
+require(`yargs`) // eslint-disable-line
+  .demand(1)
+  .options({
+    cloudRegion: {
+      alias: 'c',
+      default: 'us-central1',
+      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',
+    },
+  })
+  .command(
+    'createRsa256Device <deviceId> <registryId> <rsaPath>',
+    'Creates an RSA256 device.',
+    {},
+    async opts => {
+      await createRsaDevice(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.rsaPath
+      );
+    }
+  )
+  .command(
+    'createEs256Device <deviceId> <registryId> <esPath>',
+    'Creates an ES256 device.',
+    {},
+    async opts => {
+      await createEsDevice(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.esPath
+      );
+    }
+  )
+  .command(
+    'createUnauthDevice <deviceId> <registryId>',
+    'Creates a device without authorization.',
+    {},
+    async opts => {
+      await createUnauthDevice(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion
+      );
+    }
+  )
+  .command(
+    'createDevice <deviceId> <registryId>',
+    'Creates a device with the given public key. Public key can be ommitted and added later on.',
+    {
+      publicKeyFormat: {
+        default: 'RSA_X509_PEM',
+        description: 'Public key format for devices.',
+        requiresArg: true,
+        choices: ['RSA_PEM', 'RSA_X509_PEM', 'ES256_PEM', 'ES256_X509_PEM'],
+        type: 'string',
+      },
+      publicKeyFile: {
+        description:
+          'Path to the public key file used for device authentication.',
+        requiresArg: true,
+        type: 'string',
+      },
+    },
+    async opts => {
+      await createDevice(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.publicKeyFormat,
+        opts.publicKeyFile
+      );
+    }
+  )
+  .command(
+    'createRegistry <registryId> <pubsubTopic>',
+    'Creates a device registry.',
+    {},
+    async opts => {
+      await createRegistry(
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.pubsubTopic
+      );
+    }
+  )
+  .command(
+    'lookupRegistry <registryId>',
+    'Gets a device registry.',
+    {},
+    async opts => {
+      await lookupRegistry(opts.registryId, opts.projectId, opts.cloudRegion);
+    }
+  )
+  .command(
+    'createIotTopic <pubsubTopic>',
+    'Creates and configures a PubSub topic for Cloud IoT Core.',
+    {},
+    opts => createIotTopic(opts.pubsubTopic)
+  )
+  .command(
+    'setupIotTopic <pubsubTopic>',
+    'Configures the PubSub topic for Cloud IoT Core.',
+    {},
+    opts => setupIotTopic(opts.pubsubTopic)
+  )
+  .command(
+    'deleteDevice <deviceId> <registryId>',
+    'Deletes a device from the device registry.',
+    {},
+    async opts => {
+      await deleteDevice(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion
+      );
+    }
+  )
+  .command(
+    'clearRegistry <registryId>',
+    '!!Be careful! Removes all devices and then deletes a device registry!!',
+    {},
+    async opts => {
+      await clearRegistry(opts.registryId, opts.projectId, opts.cloudRegion);
+    }
+  )
+  .command(
+    'deleteRegistry <registryId>',
+    'Deletes a device registry.',
+    {},
+    async opts => {
+      await deleteRegistry(opts.registryId, opts.projectId, opts.cloudRegion);
+    }
+  )
+  .command(
+    'getDevice <deviceId> <registryId>',
+    'Retrieves device info given a device ID.',
+    {},
+    async opts => {
+      await getDevice(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion
+      );
+    }
+  )
+  .command(
+    'getDeviceConfigs <deviceId> <registryId>',
+    'Retrieves device configurations given a device ID.',
+    {},
+    async opts => {
+      getDeviceConfigs(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion
+      );
+    }
+  )
+  .command(
+    'getDeviceState <deviceId> <registryId>',
+    'Retrieves device state given a device ID.',
+    {},
+    async opts => {
+      getDeviceState(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion
+      );
+    }
+  )
+  .command(
+    'getRegistry <registryId>',
+    'Retrieves a registry.',
+    {},
+    async opts => {
+      await getRegistry(opts.registryId, opts.projectId, opts.cloudRegion);
+    }
+  )
+  .command(
+    'listDevices <registryId>',
+    'Lists the devices in a given registry.',
+    {},
+    async opts => {
+      await listDevices(opts.registryId, opts.projectId, opts.cloudRegion);
+    }
+  )
+  .command(
+    'listRegistries',
+    'Lists the registries in a given project.',
+    {},
+    async opts => {
+      await listRegistries(opts.projectId, opts.cloudRegion);
+    }
+  )
+  .command(
+    'patchEs256 <deviceId> <registryId> <es256Path>',
+    'Patches a device with ES256 authorization credentials.',
+    {},
+    async opts => {
+      await patchEs256ForAuth(
+        opts.deviceId,
+        opts.registryId,
+        opts.es256Path,
+        opts.projectId,
+        opts.cloudRegion
+      );
+    }
+  )
+  .command(
+    'patchRsa256 <deviceId> <registryId> <rsa256Path>',
+    'Patches a device with RSA256 authentication credentials.',
+    {},
+    async opts => {
+      await patchRsa256ForAuth(
+        opts.deviceId,
+        opts.registryId,
+        opts.rsa256Path,
+        opts.projectId,
+        opts.cloudRegion
+      );
+    }
+  )
+  .command(
+    'setConfig <deviceId> <registryId> <configuration> <version>',
+    'Sets a devices configuration to the specified data.',
+    {},
+    async opts => {
+      await setDeviceConfig(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.configuration,
+        opts.version || 0
+      );
+    }
+  )
+  .command(
+    'sendCommand <deviceId> <registryId> <commandMsg>',
+    'Sends a command message to a device subscribed to the commands topic',
+    {},
+    async opts => {
+      await sendCommand(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.commandMsg
+      );
+    }
+  )
+  .command(
+    'getIamPolicy <registryId>',
+    'Gets the IAM permissions for a given registry',
+    {},
+    async opts => {
+      await getIamPolicy(opts.registryId, opts.projectId, opts.cloudRegion);
+    }
+  )
+  .command(
+    'setIamPolicy <registryId> <member> <role>',
+    'Gets the IAM permissions for a given registry',
+    {},
+    async opts => {
+      await setIamPolicy(
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.member,
+        opts.role
+      );
+    }
+  )
+  .command(
+    'createGateway',
+    'Creates a gateway',
+    {
+      registryId: {
+        description:
+          'Enter a permanent ID that starts with a lower case letter. Must end in a letter or number.',
+        requiresArg: true,
+        type: 'string',
+      },
+      gatewayId: {
+        description:
+          'Enter a permanent ID that starts with a lowercase letter. Must end in a letter or number',
+        requiresArg: true,
+        type: 'string',
+      },
+      publicKeyFormat: {
+        alias: 'format',
+        default: 'RSA_X509_PEM',
+        description: 'Public key format for devices.',
+        requiresArg: true,
+        choices: ['RSA_PEM', 'RSA_X509_PEM', 'ES256_PEM', 'ES256_X509_PEM'],
+        type: 'string',
+      },
+      publicKeyFile: {
+        alias: 'key',
+        description:
+          'Path to the public key file used for device authentication.',
+        requiresArg: true,
+        type: 'string',
+      },
+      gatewayAuthMethod: {
+        default: 'ASSOCIATION_ONLY',
+        description:
+          'Determines how Cloud IoT Core verifies and trusts devices associated with this gateway.',
+        requiresArg: true,
+        choices: [
+          'ASSOCIATION_ONLY',
+          'DEVICE_AUTH_TOKEN_ONLY',
+          'ASSOCIATION_AND_DEVICE_AUTH_TOKEN',
+          'GATEWAY_AUTH_METHOD_UNSPECIFIED',
+        ],
+        type: 'string',
+      },
+    },
+    async opts => {
+      await createGateway(
+        opts.projectId,
+        opts.cloudRegion,
+        opts.registryId,
+        opts.gatewayId,
+        opts.publicKeyFormat,
+        opts.publicKeyFile
+      );
+    }
+  )
+  .command(
+    'listGateways <registryId>',
+    'Lists gateways in a registry.',
+    {},
+    async opts => {
+      await listGateways(opts.projectId, opts.cloudRegion, opts.registryId);
+    }
+  )
+  .command(
+    'bindDeviceToGateway <registryId> <gatewayId> <deviceId>',
+    'Binds a device to a gateway',
+    {},
+    async opts => {
+      await bindDeviceToGateway(
+        opts.projectId,
+        opts.cloudRegion,
+        opts.registryId,
+        opts.deviceId,
+        opts.gatewayId
+      );
+    }
+  )
+  .command(
+    'unbindDeviceFromGateway <registryId> <gatewayId> <deviceId>',
+    'Unbinds a device from a gateway',
+    {},
+    async opts => {
+      await unbindDeviceFromGateway(
+        opts.projectId,
+        opts.cloudRegion,
+        opts.registryId,
+        opts.deviceId,
+        opts.gatewayId
+      );
+    }
+  )
+  .command(
+    'unbindDeviceFromAllGateways <registryId> <deviceId>',
+    'Unbinds a device from all gateways',
+    {},
+    async opts => {
+      await unbindDeviceFromAllGateways(
+        opts.projectId,
+        opts.cloudRegion,
+        opts.registryId,
+        opts.deviceId
+      );
+    }
+  )
+  .command(
+    'unbindAllDevices <registryId>',
+    'Unbinds all devices in a given registry. Mainly for clearing registries',
+    {},
+    async opts => {
+      await unbindAllDevices(opts.projectId, opts.cloudRegion, opts.registryId);
+    }
+  )
+  .command(
+    'listDevicesForGateway <registryId> <gatewayId>',
+    'Lists devices in a gateway.',
+    {},
+    async opts => {
+      await listDevicesForGateway(
+        opts.projectId,
+        opts.cloudRegion,
+        opts.registryId,
+        opts.gatewayId
+      );
+    }
+  )
+  .command(
+    'listGatewaysForDevice <registryId> <deviceId>',
+    'Lists gateways for a given device.',
+    {},
+    async opts => {
+      await listGatewaysForDevice(
+        opts.projectId,
+        opts.cloudRegion,
+        opts.registryId,
+        opts.deviceId
+      );
+    }
+  )
+  .example(
+    'node $0 createDevice my-device my-registry RS256_X509_PEM ./rsa_cert.pem'
+  )
+  .example(
+    'node $0 createEs256Device my-es-device my-registry ../ec_public.pem'
+  )
+  .example(
+    'node $0 createRegistry my-registry my-iot-topic --serviceAccount=$secure/svc.json --projectId=my-project-id'
+  )
+  .example(
+    'node $0 createRsa256Device my-rsa-device my-registry ../rsa_cert.pem'
+  )
+  .example(
+    'node $0 createGateway --registryId=my-registry --gatewayId=my-gateway\
+    --format=RS256_X509_PEM --key=./rsa_cert.pem'
+  )
+  .example('node $0 createUnauthDevice my-device my-registry')
+  .example('node $0 deleteDevice my-device my-registry')
+  .example('node $0 deleteRegistry my-device my-registry')
+  .example('node $0 getDevice my-device my-registry')
+  .example('node $0 getDeviceState my-device my-registry')
+  .example('node $0 getIamPolicy my-registry')
+  .example('node $0 getRegistry my-registry')
+  .example(
+    'node $0 listDevices -s path/svc.json -p your-project-id -c asia-east1 my-registry'
+  )
+  .example(
+    'node $0 listRegistries -s path/svc.json -p your-project-id -c europe-west1'
+  )
+  .example('node $0 patchRsa256 my-device my-registry ../rsa_cert.pem')
+  .example('node $0 patchEs256 my-device my-registry ../ec_public.pem')
+  .example('node $0 setConfig my-device my-registry "test" 0')
+  .example('node $0 sendCommand my-device my-registry test')
+  .example(
+    'node $0 setIamPolicy my-registry user:example@example.com roles/viewer'
+  )
+  .example(
+    'node $0 setupTopic my-iot-topic --serviceAccount=$HOME/creds_iot.json --projectId=my-project-id'
+  )
+  .wrap(120)
+  .recommendCommands()
+  .epilogue('For more information, see https://cloud.google.com/iot-core/docs')
+  .help()
+  .strict().argv;
diff --git a/samples/manager/package.json b/samples/manager/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..689ab4757f6be6a8b6eccc87f483f134b8c0d7d9
--- /dev/null
+++ b/samples/manager/package.json
@@ -0,0 +1,30 @@
+{
+  "name": "nodejs-docs-samples-iot-manager",
+  "version": "0.0.1",
+  "description": "Example of Cloud IoT device administration",
+  "main": "manager.js",
+  "license": "Apache-2.0",
+  "author": "Google LLC",
+  "files": [
+    "*.js"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "test": "mocha --timeout=600000"
+  },
+  "dependencies": {
+    "@google-cloud/iot": "^2.0.0",
+    "@google-cloud/pubsub": "^3.0.0",
+    "yargs": "^16.0.0"
+  },
+  "devDependencies": {
+    "mocha": "^8.1.1",
+    "uuid": "^8.0.0"
+  }
+}
diff --git a/samples/manager/test/manager.test.js b/samples/manager/test/manager.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..1bc4a78e8addc439ea55f2631a535d6ed1318430
--- /dev/null
+++ b/samples/manager/test/manager.test.js
@@ -0,0 +1,438 @@
+// Copyright 2020 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 assert = require('assert');
+const iot = require('@google-cloud/iot');
+const path = require('path');
+const {PubSub} = require('@google-cloud/pubsub');
+const uuid = require('uuid');
+
+const {after, before, it, xit} = require('mocha');
+
+const topicName = `nodejs-iot-test-topic-${uuid.v4()}`;
+const registryName = `nodejs-iot-test-registry-${uuid.v4()}`;
+const region = 'us-central1';
+const projectId =
+  process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
+
+const cmd = 'node manager.js';
+const cp = require('child_process');
+const cwd = path.join(__dirname, '..');
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+const installDeps = 'npm install';
+const rsaPublicCert = '../resources/rsa_cert.pem'; // process.env.NODEJS_IOT_RSA_PUBLIC_CERT;
+const rsaPrivateKey = '../resources/rsa_private.pem'; //process.env.NODEJS_IOT_RSA_PRIVATE_KEY;
+const ecPublicKey = '../resources/ec_public.pem'; // process.env.NODEJS_IOT_EC_PUBLIC_KEY;
+
+const iotClient = new iot.v1.DeviceManagerClient();
+const pubSubClient = new PubSub({projectId});
+
+before(async () => {
+  execSync(installDeps, `${cwd}/mqtt_example`);
+  assert(
+    process.env.GCLOUD_PROJECT,
+    'Must set GCLOUD_PROJECT environment variable!'
+  );
+  assert(
+    process.env.GOOGLE_APPLICATION_CREDENTIALS,
+    'Must set GOOGLE_APPLICATION_CREDENTIALS environment variable!'
+  );
+  // Create a topic to be used for testing.
+  const [topic] = await pubSubClient.createTopic(topicName);
+  console.log(`Topic ${topic.name} created.`);
+
+  // Creates a registry to be used for tests.
+  const createRegistryRequest = {
+    parent: iotClient.locationPath(projectId, region),
+    deviceRegistry: {
+      id: registryName,
+      eventNotificationConfigs: [
+        {
+          pubsubTopicName: topic.name,
+        },
+      ],
+    },
+  };
+  await execSync(`${cmd} setupIotTopic ${topicName}`, cwd);
+
+  await iotClient.createDeviceRegistry(createRegistryRequest);
+  console.log(`Created registry: ${registryName}`);
+});
+
+after(async () => {
+  await pubSubClient.topic(topicName).delete();
+  console.log(`Topic ${topicName} deleted.`);
+
+  // Cleans up the registry by removing all associations and deleting all devices.
+  execSync(`${cmd} unbindAllDevices ${registryName}`, cwd);
+  execSync(`${cmd} clearRegistry ${registryName}`, cwd);
+
+  console.log('Deleted test registry.');
+});
+
+it('should create and delete an unauthorized device', async () => {
+  const localDevice = 'test-device-unauth-delete';
+
+  let output = await execSync(
+    `${cmd} createUnauthDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully deleted device'));
+});
+
+it('should list configs for a device', async () => {
+  const localDevice = 'test-device-configs';
+  let output = await execSync(
+    `${cmd} createUnauthDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(
+    `${cmd} getDeviceConfigs ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Configs'));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully deleted device'));
+});
+
+it('should create and delete an RSA256 device', async () => {
+  const localDevice = 'test-rsa-device';
+  let output = await execSync(
+    `${cmd} createRsa256Device ${localDevice} ${registryName} ${rsaPublicCert}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(
+    `${cmd} getDeviceState ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('State'));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully deleted device'));
+});
+
+it('should create and delete an ES256 device', async () => {
+  const localDevice = 'test-es256-device';
+  let output = await execSync(
+    `${cmd} createEs256Device ${localDevice} ${registryName} ${ecPublicKey}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(
+    `${cmd} getDeviceState ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('State'));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully deleted device'));
+});
+
+it('should patch an unauthorized device with RSA256', async () => {
+  const localDevice = 'test-device-patch-rs256';
+  let output = await execSync(
+    `${cmd} createUnauthDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(
+    `${cmd} patchRsa256 ${localDevice} ${registryName} ${rsaPublicCert}`,
+    cwd
+  );
+  assert.ok(output.includes('Patched device:'));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully deleted device'));
+});
+
+it('should patch an unauthorized device with ES256', async () => {
+  const localDevice = 'test-device-patch-es256';
+  let output = await execSync(
+    `${cmd} createUnauthDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(
+    `${cmd} patchEs256 ${localDevice} ${registryName} ${ecPublicKey}`,
+    cwd
+  );
+  assert.ok(output.includes('Patched device:'));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully deleted device'));
+});
+
+it('should create and list devices', async () => {
+  const localDevice = 'test-device-list';
+  let output = await execSync(
+    `${cmd} createUnauthDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(`${cmd} listDevices ${registryName}`, cwd);
+  assert.ok(output.includes('Current devices in registry:'));
+  assert.ok(output.includes(localDevice));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully deleted device'));
+});
+
+it('should create and get a device', async () => {
+  const localDevice = 'test-device-get';
+
+  let output = await execSync(
+    `${cmd} createUnauthDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes('Created device'));
+  output = await execSync(
+    `${cmd} getDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+  assert.ok(output.includes(`Found device: ${localDevice}`));
+  output = await execSync(
+    `${cmd} deleteDevice ${localDevice} ${registryName}`,
+    cwd
+  );
+});
+
+it('should create and get an iam policy', async () => {
+  const localMember = 'group:dpebot@google.com';
+  const localRole = 'roles/viewer';
+
+  let output = await execSync(
+    `${cmd} setIamPolicy ${registryName} ${localMember} ${localRole}`,
+    cwd
+  );
+  assert.ok(output.includes('ETAG'));
+
+  output = await execSync(`${cmd} getIamPolicy ${registryName}`, cwd);
+  assert.ok(output.includes('dpebot'));
+});
+
+it('should create and delete a registry', async () => {
+  const createRegistryId = `${registryName}-create`;
+
+  let output = await execSync(`${cmd} setupIotTopic ${topicName}`, cwd);
+  output = await execSync(
+    `${cmd} createRegistry ${createRegistryId} ${topicName}`,
+    cwd
+  );
+  assert.ok(output.includes('Successfully created registry'));
+  output = await execSync(`${cmd} deleteRegistry ${createRegistryId}`, cwd);
+  assert.ok(output.includes('Successfully deleted registry'));
+});
+
+xit('should send command message to device', async () => {
+  const deviceId = 'test-device-command';
+  const commandMessage = 'rotate:180_degrees';
+
+  await execSync(
+    `${cmd} createRsa256Device ${deviceId} ${registryName} ${rsaPublicCert}`,
+    cwd
+  );
+
+  cp.exec(
+    `node mqtt_example/cloudiot_mqtt_example_nodejs.js mqttDeviceDemo --deviceId=${deviceId} --registryId=${registryName}\
+  --privateKeyFile=${rsaPrivateKey} --algorithm=RS256 --numMessages=20 --mqttBridgePort=8883`,
+    path.join(__dirname, '../../mqtt_example')
+  );
+
+  const output = await execSync(
+    `${cmd} sendCommand ${deviceId} ${registryName} ${commandMessage}`
+  );
+  console.log(output);
+  assert.ok(output.includes('Sent command'));
+
+  await execSync(`${cmd} deleteDevice ${deviceId} ${registryName}`, cwd);
+});
+
+it('should create a new gateway', async () => {
+  const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
+  const gatewayOut = await execSync(
+    `${cmd} createGateway --registryId=${registryName} --gatewayId=${gatewayId}\
+  --format=RSA_X509_PEM --key=${rsaPublicCert}`
+  );
+
+  // test no error on create gateway.
+  assert.ok(gatewayOut.includes('Created device'));
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, gatewayId),
+  });
+});
+
+it('should list gateways', async () => {
+  const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
+  await execSync(
+    `${cmd} createGateway --registryId=${registryName} --gatewayId=${gatewayId}\
+  --format=RSA_X509_PEM --key=${rsaPublicCert}`
+  );
+
+  // look for output in list gateway
+  const gateways = await execSync(`${cmd} listGateways ${registryName}`);
+  assert.ok(gateways.includes(`${gatewayId}`));
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, gatewayId),
+  });
+});
+
+it('should bind existing device to gateway', async () => {
+  const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
+  await execSync(
+    `${cmd} createGateway --registryId=${registryName} --gatewayId=${gatewayId}\
+  --format=RSA_X509_PEM --key=${rsaPublicCert}`
+  );
+
+  // create device
+  const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
+  await iotClient.createDevice({
+    parent: iotClient.registryPath(projectId, region, registryName),
+    device: {
+      id: deviceId,
+    },
+  });
+
+  // bind device to gateway
+  const bind = await execSync(
+    `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+
+  assert.ok(bind.includes(`Binding device: ${deviceId}`));
+  assert.strictEqual(bind.includes('Could not bind device'), false);
+
+  // test unbind
+  const unbind = await execSync(
+    `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+  assert.ok(unbind.includes(`Unbound ${deviceId} from ${gatewayId}`));
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, gatewayId),
+  });
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, deviceId),
+  });
+});
+
+it('should list devices bound to gateway', async () => {
+  const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
+  await execSync(
+    `${cmd} createGateway --registryId=${registryName} --gatewayId=${gatewayId}\
+  --format=RSA_X509_PEM --key=${rsaPublicCert}`
+  );
+
+  const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
+  await iotClient.createDevice({
+    parent: iotClient.registryPath(projectId, region, registryName),
+    device: {
+      id: deviceId,
+    },
+  });
+
+  await execSync(
+    `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+
+  const devices = await execSync(
+    `${cmd} listDevicesForGateway ${registryName} ${gatewayId}`
+  );
+
+  assert.ok(devices.includes(deviceId));
+  assert.strictEqual(
+    devices.includes('No devices bound to this gateway.'),
+    false
+  );
+
+  // cleanup
+  await execSync(
+    `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, gatewayId),
+  });
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, deviceId),
+  });
+});
+
+it('should list gateways for bound device', async () => {
+  const gatewayId = `nodejs-test-gateway-iot-${uuid.v4()}`;
+  await execSync(
+    `${cmd} createGateway --registryId=${registryName} --gatewayId=${gatewayId}\
+  --format=RSA_X509_PEM --key=${rsaPublicCert}`
+  );
+
+  // create device
+  const deviceId = `nodejs-test-device-iot-${uuid.v4()}`;
+  await iotClient.createDevice({
+    parent: iotClient.registryPath(projectId, region, registryName),
+    device: {
+      id: deviceId,
+    },
+  });
+
+  await execSync(
+    `${cmd} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+
+  const devices = await execSync(
+    `${cmd} listGatewaysForDevice ${registryName} ${deviceId}`
+  );
+
+  assert.ok(devices.includes(gatewayId));
+  assert.strictEqual(
+    devices.includes('No gateways associated with this device'),
+    false
+  );
+
+  // cleanup
+  await execSync(
+    `${cmd} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, gatewayId),
+  });
+
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, deviceId),
+  });
+});
diff --git a/samples/mqtt_example/README.md b/samples/mqtt_example/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..dbe49723e11fbcbdf21629fa280955eeb6b9c644
--- /dev/null
+++ b/samples/mqtt_example/README.md
@@ -0,0 +1,101 @@
+<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
+
+# Google Cloud IoT Core NodeJS MQTT example
+
+This sample app publishes data to Cloud Pub/Sub using the MQTT bridge provided
+as part of Google Cloud IoT Core.
+
+Note that before you can run this sample, you must register a device as
+described in the parent README. For the gateway samples, you must register and bind
+a device as described in the [Cloud IoT gateway docs](https://cloud.google.com/iot/docs/how-tos/gateways/#setup).
+
+# Setup
+
+Run the following command to install the library dependencies for NodeJS:
+
+    npm install
+
+Download server certificate as described in the [Cloud IoT MQTT guides](https://cloud.google.com/iot/docs/how-tos/mqtt-bridge#downloading_mqtt_server_certificates).
+
+# Running the sample
+
+The following command summarizes the sample usage:
+
+    Usage: cloudiot_mqtt_example_nodejs [command] [options]
+
+    Commands:
+        mqttDeviceDemo              Example Google Cloud IoT Core MQTT device connection demo.
+        sendDataFromBoundDevice     Demonstrates sending data from a gateway on behalf of a bound device.
+        listenForConfigMessages     Demonstrates listening for config messages on a gateway client of a bound device.
+        listenForErrorMessages      Demonstrates listening for error messages on a gateway.
+
+    Options:
+
+        --projectId           The Project ID to use. Defaults to the value of the GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT
+                            environment variables.
+        --cloudRegion         GCP cloud region.
+        --registryId          Cloud IoT registry ID.
+        --deviceId            Cloud IoT device ID.
+        --privateKeyFile      Path to private key file.
+        --serverCertFile      Path to server certificate file.
+        --algorithm           Encryption algorithm to generate the JWT.
+        --numMessages         Number of messages to publish.
+        --tokenExpMins        Minutes to JWT token expiration.
+        --mqttBridgeHostname  MQTT bridge hostname.
+        --mqttBridgePort      MQTT bridge port.
+        --messageType         Message type to publish.
+        --help                Show help
+
+For example, if your project ID is `blue-jet-123`, your service account
+credentials are stored in your home folder in creds.json and you have generated
+your credentials using the shell script provided in the parent folder, you can
+run the following examples:
+
+    node cloudiot_mqtt_example_nodejs.js mqttDeviceDemo \
+        --projectId=blue-jet-123 \
+        --cloudRegion=us-central1 \
+        --registryId=my-registry \
+        --deviceId=my-device \
+        --privateKeyFile=../rsa_private.pem \
+        --serverCertFile=../roots.pem \
+        --algorithm=RS256
+
+    node cloudiot_mqtt_example_nodejs.js sendDataFromBoundDevice \
+        --projectId=blue-jet-123 \
+        --cloudRegion=us-central1 \
+        --registryId=my-registry \
+        --gatewayId=my-gateway \
+        --deviceId=my-device \
+        --privateKeyFile=../rsa_private.pem \
+        --serverCertFile=../roots.pem \
+        --algorithm=RS256
+
+    node cloudiot_mqtt_example_nodejs.js listenForConfigMessages \
+        --projectId=blue-jet-123 \
+        --cloudRegion=us-central1 \
+        --registryId=my-registry \
+        --gatewayid=my-gateway \
+        --deviceId=my-device \
+        --privateKeyFile=../rsa_private.pem \
+        --serverCertFile=../roots.pem \
+        --algorithm=RS256
+        --clientDuration=60000
+
+# Sending a configuration update
+
+For `listenForConfigMessages` example, try sending a config update to the device while the client is running. This can be done via the Google Cloud IoT Core UI or through the command line with the following command.
+
+    gcloud iot devices configs update --region=us-central1 --registry=my-registry --device=my-device --config-data="testing"
+
+# Reading the messages written by the sample client
+
+1. Create a subscription to your topic.
+
+        gcloud pubsub subscriptions create \
+            projects/your-project-id/subscriptions/my-subscription \
+            --topic device-events
+
+2. Read messages published to the topic
+
+        gcloud pubsub subscriptions pull --auto-ack \
+            projects/my-iot-project/subscriptions/my-subscription
diff --git a/samples/mqtt_example/cloudiot_mqtt_example_nodejs.js b/samples/mqtt_example/cloudiot_mqtt_example_nodejs.js
new file mode 100644
index 0000000000000000000000000000000000000000..75e23cd40a89fe34215951a3218f48c05b0e74af
--- /dev/null
+++ b/samples/mqtt_example/cloudiot_mqtt_example_nodejs.js
@@ -0,0 +1,893 @@
+// Copyright 2020 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';
+
+// [START iot_mqtt_include]
+const {readFileSync} = require('fs');
+const jwt = require('jsonwebtoken');
+const mqtt = require('mqtt');
+// [END iot_mqtt_include]
+
+// 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;
+
+console.log('Google Cloud IoT Core MQTT example.');
+
+// 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 = readFileSync(privateKeyFile);
+  return jwt.sign(token, privateKey, {algorithm: algorithm});
+};
+// [END iot_mqtt_jwt]
+
+// Publish numMessages messages asynchronously, starting from message
+// messagesSent.
+// [START iot_mqtt_publish]
+const publishAsync = (
+  mqttTopic,
+  client,
+  iatTime,
+  messagesSent,
+  numMessages,
+  connectionArgs
+) => {
+  // 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.');
+    }
+    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.`);
+  }
+
+  setTimeout(() => {
+	const payload = JSON.stringify({
+        "thingId": "zRYzhAEAHAABAAAKCRtcAAsAuAB5gBAQ",
+        "controllerNumber": "1",
+        "moduleNumber": "1",
+        "variableNumber": "15",
+        "time": "1665479317",
+        "value": "190.0",
+        "alarmClass": "4",
+        "dataType": "2"
+    }); 
+    //const payload = `${argv.registryId}/${argv.deviceId}-payload-${messagesSent}`;
+
+    // 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);
+    client.publish(mqttTopic, payload, {qos: 1}, err => {
+      if (!err) {
+        shouldBackoff = false;
+        backoffTime = MINIMUM_BACKOFF_TIME;
+      }
+    });
+
+    const schedulePublishDelayMs = argv.messageType === 'events' ? 1000 : 2000;
+    setTimeout(() => {
+      // [START iot_mqtt_jwt_refresh]
+      const secsFromIssue = parseInt(Date.now() / 1000) - iatTime;
+      if (secsFromIssue > argv.tokenExpMins * 60) {
+        iatTime = parseInt(Date.now() / 1000);
+        console.log(`\tRefreshing token after ${secsFromIssue} seconds.`);
+
+        client.end();
+        connectionArgs.password = createJwt(
+          argv.projectId,
+          argv.privateKeyFile,
+          argv.algorithm
+        );
+        connectionArgs.protocolId = 'MQTT';
+        connectionArgs.protocolVersion = 4;
+        connectionArgs.clean = true;
+        client = mqtt.connect(connectionArgs);
+        // [END iot_mqtt_jwt_refresh]
+
+        client.on('connect', success => {
+          console.log('connect');
+          if (!success) {
+            console.log('Client not connected...');
+          } else if (!publishChainInProgress) {
+            publishAsync(
+              mqttTopic,
+              client,
+              iatTime,
+              messagesSent,
+              numMessages,
+              connectionArgs
+            );
+          }
+        });
+
+        client.on('close', () => {
+          console.log('close');
+          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
+        });
+      }
+      publishAsync(
+        mqttTopic,
+        client,
+        iatTime,
+        messagesSent + 1,
+        numMessages,
+        connectionArgs
+      );
+    }, schedulePublishDelayMs);
+  }, publishDelayMs);
+};
+// [END iot_mqtt_publish]
+
+const mqttDeviceDemo = (
+  deviceId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  messageType,
+  numMessages
+) => {
+  // [START iot_mqtt_run]
+
+  // const deviceId = `myDevice`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const messageType = `events`;
+  // const numMessages = 5;
+
+  // The mqttClientId is a unique string that identifies this device. For Google
+  // Cloud IoT Core, it must be in the format below.
+  const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${deviceId}`;
+
+  // With Google Cloud IoT Core, the username field is ignored, however it must be
+  // non-empty. The password field is used to transmit a JWT to authorize the
+  // device. The "mqtts" protocol causes the library to connect using SSL, which
+  // is required for Cloud IoT Core.
+  const connectionArgs = {
+    host: mqttBridgeHostname,
+    port: mqttBridgePort,
+    clientId: mqttClientId,
+    username: 'unused',
+    password: createJwt(projectId, privateKeyFile, algorithm),
+    protocol: 'mqtts',
+    secureProtocol: 'TLSv1_2_method',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // Create a client, and connect to the Google MQTT bridge.
+  const iatTime = parseInt(Date.now() / 1000);
+  const client = mqtt.connect(connectionArgs);
+
+  // Subscribe to the /devices/{device-id}/config topic to receive config updates.
+  // Config updates are recommended to use QoS 1 (at least once delivery)
+  client.subscribe(`/devices/${deviceId}/config`, {qos: 1});
+
+  // Subscribe to the /devices/{device-id}/commands/# topic to receive all
+  // commands or to the /devices/{device-id}/commands/<subfolder> to just receive
+  // messages published to a specific commands folder; we recommend you use
+  // QoS 0 (at most once delivery)
+  client.subscribe(`/devices/${deviceId}/commands/#`, {qos: 0});
+
+  // The MQTT topic that this device will publish data to. The MQTT topic name is
+  // required to be in the format below. The topic name must end in 'state' to
+  // publish state and 'events' to publish telemetry. Note that this is not the
+  // same as the device registry's Cloud Pub/Sub topic.
+  const mqttTopic = `/devices/${deviceId}/${messageType}`;
+
+  client.on('connect', success => {
+    console.log('connect');
+    if (!success) {
+      console.log('Client not connected...');
+    } else if (!publishChainInProgress) {
+      publishAsync(mqttTopic, client, iatTime, 1, numMessages, connectionArgs);
+    }
+  });
+
+  client.on('close', () => {
+    console.log('close');
+    shouldBackoff = true;
+  });
+
+  client.on('error', err => {
+    console.log('error', err);
+  });
+
+  client.on('message', (topic, message) => {
+    let messageStr = 'Message received: ';
+    if (topic === `/devices/${deviceId}/config`) {
+      messageStr = 'Config message received: ';
+    } else if (topic.startsWith(`/devices/${deviceId}/commands`)) {
+      messageStr = 'Command message received: ';
+    }
+
+    messageStr += Buffer.from(message, 'base64').toString('ascii');
+    console.log(messageStr);
+  });
+
+  client.on('packetsend', () => {
+    // Note: logging packet send is very verbose
+  });
+
+  // Once all of the messages have been published, the connection to Google Cloud
+  // IoT will be closed and the process will exit. See the publishAsync method.
+  // [END iot_mqtt_run]
+};
+
+// Attaches a device to a gateway.
+const attachDevice = (deviceId, client, jwt) => {
+  // [START attach_device]
+  // const deviceId = 'my-unauth-device';
+  const attachTopic = `/devices/${deviceId}/attach`;
+  console.log(`Attaching: ${attachTopic}`);
+  let attachPayload = '{}';
+  if (jwt && jwt !== '') {
+    attachPayload = `{ 'authorization' : ${jwt} }`;
+  }
+
+  client.publish(attachTopic, attachPayload, {qos: 1}, err => {
+    if (!err) {
+      shouldBackoff = false;
+      backoffTime = MINIMUM_BACKOFF_TIME;
+    } else {
+      console.log(err);
+    }
+  });
+  // [END attach_device]
+};
+
+// Detaches a device from a gateway.
+const detachDevice = (deviceId, client, jwt) => {
+  // [START detach_device]
+  const detachTopic = `/devices/${deviceId}/detach`;
+  console.log(`Detaching: ${detachTopic}`);
+  let detachPayload = '{}';
+  if (jwt && jwt !== '') {
+    detachPayload = `{ 'authorization' : ${jwt} }`;
+  }
+
+  client.publish(detachTopic, detachPayload, {qos: 1}, err => {
+    if (!err) {
+      shouldBackoff = false;
+      backoffTime = MINIMUM_BACKOFF_TIME;
+    } else {
+      console.log(err);
+    }
+  });
+  // [END detach_device]
+};
+
+// Publish numMessages messages asynchronously through a gateway client connection
+const publishAsyncGateway = (
+  client,
+  iatTime,
+  tokenExpMins,
+  messagesSent,
+  numMessages,
+  registryId,
+  deviceId,
+  gatewayId,
+  connectionArgs,
+  projectId,
+  privateKeyFile,
+  algorithm
+) => {
+  // 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(() => {
+      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);
+      }
+      publishAsyncGateway(
+        client,
+        iatTime,
+        tokenExpMins,
+        messagesSent + 1,
+        numMessages,
+        registryId,
+        deviceId,
+        gatewayId
+      );
+    }, schedulePublishDelayMs);
+  }, publishDelayMs);
+};
+
+// Sends data from a gateway on behalf of a device that is bound to that gateway.
+const sendDataFromBoundDevice = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  numMessages,
+  tokenExpMins
+) => {
+  // [START iot_send_data_from_bound_device]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const numMessages = 5;
+  // const tokenExpMins = 60;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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');
+        publishAsyncGateway(
+          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_data_from_bound_device]
+};
+
+// Listen for configuration messages on a gateway and bound device.
+const listenForConfigMessages = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  clientDuration
+) => {
+  // [START iot_listen_for_config_messages]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const clientDuration = 60000;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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 iot_listen_for_config_messages]
+};
+
+// Listen for error messages on a gateway.
+const listenForErrorMessages = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  clientDuration
+) => {
+  // [START iot_listen_for_error_messages]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const projectId = `my-project-123`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const clientDuration = 60000;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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 iot_listen_for_error_messages]
+};
+
+const {argv} = require('yargs')
+  .options({
+    projectId: {
+      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',
+    },
+    cloudRegion: {
+      default: 'us-central1',
+      description: 'GCP cloud region.',
+      requiresArg: true,
+      type: 'string',
+    },
+    registryId: {
+      description: 'Cloud IoT registry ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    deviceId: {
+      description: 'Cloud IoT device ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    privateKeyFile: {
+      description: 'Path to private key file.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    serverCertFile: {
+      description: 'Path to server certificate file.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    algorithm: {
+      description: 'Encryption algorithm to generate the JWT.',
+      requiresArg: true,
+      demandOption: true,
+      choices: ['RS256', 'ES256'],
+      type: 'string',
+    },
+    tokenExpMins: {
+      default: 20,
+      description: 'Minutes to JWT token expiration.',
+      requiresArg: true,
+      type: 'number',
+    },
+    mqttBridgeHostname: {
+      default: 'mqtt.googleapis.com',
+      description: 'MQTT bridge hostname.',
+      requiresArg: true,
+      type: 'string',
+    },
+    mqttBridgePort: {
+      default: 8883,
+      description: 'MQTT bridge port.',
+      requiresArg: true,
+      type: 'number',
+    },
+  })
+  .command(
+    'mqttDeviceDemo',
+    'Connects a device, sends data, and receives data',
+    {
+      messageType: {
+        default: 'events',
+        description: 'Message type to publish.',
+        requiresArg: true,
+        choices: ['events', 'state'],
+        type: 'string',
+      },
+      numMessages: {
+        default: 10,
+        description: 'Number of messages to publish.',
+        demandOption: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      mqttDeviceDemo(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.messageType,
+        opts.numMessages
+      );
+    }
+  )
+  .command(
+    'sendDataFromBoundDevice',
+    'Sends data from a gateway on behalf of a bound device.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      numMessages: {
+        default: 10,
+        description: 'Number of messages to publish.',
+        demandOption: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      sendDataFromBoundDevice(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.numMessages,
+        opts.tokenExpMins
+      );
+    }
+  )
+  .command(
+    'listenForConfigMessages',
+    'Listens for configuration changes on a gateway and bound device.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      clientDuration: {
+        default: 60000,
+        description: 'Duration in milliseconds for MQTT client to run.',
+        requiresArg: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      listenForConfigMessages(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.clientDuration
+      );
+    }
+  )
+  .command(
+    'listenForErrorMessages',
+    'Listens for error messages on a gateway.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      clientDuration: {
+        default: 60000,
+        description: 'Duration in milliseconds for MQTT client to run.',
+        requiresArg: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      listenForErrorMessages(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.clientDuration
+      );
+    }
+  )
+  .example(
+    'node $0 mqttDeviceDemo --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --numMessages=10 \\\n'
+  )
+  .example(
+    'node $0 sendDataFromBoundDevice --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n'
+  )
+  .example(
+    'node $0 listenForConfigMessages --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n\t--clientDuration=300000 \\\n'
+  )
+  .example(
+    'node $0 listenForErrorMessages --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n\t--clientDuration=300000 \\\n'
+  )
+  .wrap(120)
+  .recommendCommands()
+  .epilogue('For more information, see https://cloud.google.com/iot-core/docs')
+  .help()
+  .strict();
diff --git a/samples/mqtt_example/package.json b/samples/mqtt_example/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..2f548c9b072c8f0f8113be777000a201f2537e7b
--- /dev/null
+++ b/samples/mqtt_example/package.json
@@ -0,0 +1,32 @@
+{
+  "author": "Google Inc.",
+  "version": "0.0.1",
+  "description": "MQTT Example for Google Cloud IoT Core using NodeJS.",
+  "license": "Apache-2.0",
+  "main": "cloudiot_mqtt_example_nodejs.js",
+  "name": "nodejs-docs-samples-iot-mqtt-example",
+  "files": [
+    "*.js"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/googleapis/nodejs-iot.git"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "test": "mocha --timeout=600000"
+  },
+  "dependencies": {
+    "@google-cloud/iot": "^2.0.0",
+    "@google-cloud/pubsub": "^3.0.0",
+    "jsonwebtoken": "^8.5.0",
+    "mqtt": "^4.0.0",
+    "yargs": "^16.0.0"
+  },
+  "devDependencies": {
+    "mocha": "^8.1.1",
+    "uuid": "^8.0.0"
+  }
+}
diff --git a/samples/mqtt_example/resources/README.md b/samples/mqtt_example/resources/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..29a1f453ee47d2b30eaf04e852f4ded4dac48175
--- /dev/null
+++ b/samples/mqtt_example/resources/README.md
@@ -0,0 +1,4 @@
+# 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.
diff --git a/samples/mqtt_example/resources/roots.pem b/samples/mqtt_example/resources/roots.pem
new file mode 100644
index 0000000000000000000000000000000000000000..0a6808dba87f5cca02505884859de146d796d448
--- /dev/null
+++ b/samples/mqtt_example/resources/roots.pem
@@ -0,0 +1,1222 @@
+# Operating CA: DigiCert
+# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Label: "Baltimore CyberTrust Root"
+# Serial: 33554617
+# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4
+# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74
+# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Label: "Cybertrust Global Root"
+# Serial: 4835703278459682877484360
+# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1
+# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6
+# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
+A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
+bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
+ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
+b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
+7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
+J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
+HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
+t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
+FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
+XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
+hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
+MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
+A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
+Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
+XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
+omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
+A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root CA"
+# Serial: 17154717934120587862167794914071425081
+# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
+# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
+# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G2"
+# Serial: 15385348160840213938643033620894905419
+# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d
+# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f
+# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G3"
+# Serial: 15459312981008553731928384953135426796
+# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb
+# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89
+# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root CA"
+# Serial: 10944719598952040374951832963794454346
+# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
+# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
+# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G2"
+# Serial: 4293743540046975378534879503202253541
+# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44
+# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4
+# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G3"
+# Serial: 7089244469030293291760083333884364146
+# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca
+# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e
+# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert High Assurance EV Root CA"
+# Serial: 3553400076410547919724730734378100087
+# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
+# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
+# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Trusted Root G4"
+# Serial: 7451500558977370777930084869016614236
+# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49
+# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4
+# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Subject: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Label: "GeoTrust Global CA"
+# Serial: 144470
+# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5
+# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12
+# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Label: "Entrust Root Certification Authority"
+# Serial: 1164660820
+# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4
+# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9
+# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - EC1"
+# Serial: 51543124481930649114116133369
+# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc
+# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47
+# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - G2"
+# Serial: 1246989352
+# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2
+# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4
+# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Label: "Entrust.net Premium 2048 Secure Server CA"
+# Serial: 946069240
+# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90
+# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31
+# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Commercial O=AffirmTrust
+# Subject: CN=AffirmTrust Commercial O=AffirmTrust
+# Label: "AffirmTrust Commercial"
+# Serial: 8608355977964138876
+# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7
+# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7
+# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Networking O=AffirmTrust
+# Subject: CN=AffirmTrust Networking O=AffirmTrust
+# Label: "AffirmTrust Networking"
+# Serial: 8957382827206547757
+# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f
+# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f
+# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Premium O=AffirmTrust
+# Subject: CN=AffirmTrust Premium O=AffirmTrust
+# Label: "AffirmTrust Premium"
+# Serial: 7893706540734352110
+# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57
+# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27
+# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Label: "AffirmTrust Premium ECC"
+# Serial: 8401224907861490260
+# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d
+# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb
+# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Label: "GlobalSign Root CA"
+# Serial: 4835703278459707669005204
+# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
+# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
+# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Label: "GlobalSign Root CA - R3"
+# Serial: 4835703278459759426209954
+# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
+# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
+# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Label: "GlobalSign ECC Root CA - R5"
+# Serial: 32785792099990507226680698011560947931244
+# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08
+# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa
+# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Label: "GlobalSign Root CA - R6"
+# Serial: 1417766617973444989252670301619537
+# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae
+# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1
+# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+# Note: "GlobalSign Root CA - R7" not added on purpose. It is P-521.
+
+# Operating CA: GoDaddy
+# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Label: "Go Daddy Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
+# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
+# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
+# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
+# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Label: "Starfield Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24
+# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a
+# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Label: "Go Daddy Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67
+# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4
+# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Label: "GlobalSign Root CA - R2"
+# Serial: 4835703278459682885658125
+# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30
+# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe
+# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Label: "GlobalSign ECC Root CA - R4"
+# Serial: 14367148294922964480859022125800977897474
+# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e
+# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb
+# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
+FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
+uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
+kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
+ewv4n4Q=
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R1
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R1
+# Label: "GTS Root R1"
+# Serial: 6e:47:a9:c5:4b:47:0c:0d:ec:33:d0:89:b9:1c:f4:e1
+# MD5 Fingerprint: 82:1A:EF:D4:D2:4A:F2:9F:E2:3D:97:06:14:70:72:85
+# SHA1 Fingerprint: E1:C9:50:E6:EF:22:F8:4C:56:45:72:8B:92:20:60:D7:D5:A7:A3:E8
+# SHA256 Fingerprint: 2A:57:54:71:E3:13:40:BC:21:58:1C:BD:2C:F1:3E:15:84:63:20:3E:CE:94:BC:F9:D3:CC:19:6B:F0:9A:54:72
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH
+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
+QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
+MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
+cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
+f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX
+mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7
+zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P
+fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc
+vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4
+Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp
+zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO
+Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW
+k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+
+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF
+lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW
+Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
+d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z
+XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR
+gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3
+d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv
+J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg
+DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM
++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy
+F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9
+SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws
+E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R2
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R2
+# Label: "GTS Root R2"
+# Serial: 6e:47:a9:c6:5a:b3:e7:20:c5:30:9a:3f:68:52:f2:6f
+# MD5 Fingerprint: 44:ED:9A:0E:A4:09:3B:00:F2:AE:4C:A3:C6:61:B0:8B
+# SHA1 Fingerprint: D2:73:96:2A:2A:5E:39:9F:73:3F:E1:C7:1E:64:3F:03:38:34:FC:4D
+# SHA256 Fingerprint: C4:5D:7B:B0:8E:6D:67:E6:2E:42:35:11:0B:56:4E:5F:78:FD:92:EF:05:8C:84:0A:EA:4E:64:55:D7:58:5C:60
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH
+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
+QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
+MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
+cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
+CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg
+GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu
+XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd
+re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu
+PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1
+mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K
+8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj
+x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR
+nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0
+kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok
+twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp
+8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
+vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT
+z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA
+pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb
+pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB
+R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R
+RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk
+0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC
+5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF
+izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn
+yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R3
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R3
+# Label: "GTS Root R3"
+# Serial: 6e:47:a9:c7:6c:a9:73:24:40:89:0f:03:55:dd:8d:1d
+# MD5 Fingerprint: 1A:79:5B:6B:04:52:9C:5D:C7:74:33:1B:25:9A:F9:25
+# SHA1 Fingerprint: 30:D4:24:6F:07:FF:DB:91:89:8A:0B:E9:49:66:11:EB:8C:5E:46:E5
+# SHA256 Fingerprint: 15:D5:B8:77:46:19:EA:7D:54:CE:1C:A6:D0:B0:C4:03:E0:37:A9:17:F1:31:E8:A0:4E:1E:6B:7A:71:BA:BC:E5
+-----BEGIN CERTIFICATE-----
+MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
+736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A
+DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk
+fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA
+njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R4
+# Label: "GTS Root R4"
+# Serial: 6e:47:a9:c8:8b:94:b6:e8:bb:3b:2a:d8:a2:b2:c1:99
+# MD5 Fingerprint: 5D:B6:6A:C4:60:17:24:6A:1A:99:A8:4B:EE:5E:B4:26
+# SHA1 Fingerprint: 2A:1D:60:27:D9:4A:B1:0A:1C:4D:91:5C:CD:33:A0:CB:3E:2D:54:CB
+# SHA256 Fingerprint: 71:CC:A5:39:1F:9E:79:4B:04:80:25:30:B3:63:E1:21:DA:8A:30:43:BB:26:66:2F:EA:4D:CA:7F:C9:51:A4:BD
+-----BEGIN CERTIFICATE-----
+MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
+hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l
+xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0
+CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx
+sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
+# Subject: CN=AAA Certificate Services O=Comodo CA Limited
+# Label: "Comodo AAA Services root"
+# Serial: 1
+# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0
+# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49
+# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
+# Label: "COMODO Certification Authority"
+# Serial: 104350513648249232941998508985834464573
+# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75
+# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b
+# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Label: "COMODO ECC Certification Authority"
+# Serial: 41578283867086692638256921589707938090
+# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
+# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
+# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Label: "COMODO RSA Certification Authority"
+# Serial: 101909084537582093308941363524873193117
+# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18
+# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4
+# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Label: "USERTrust ECC Certification Authority"
+# Serial: 123013823720199481456569720443997572134
+# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1
+# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0
+# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Label: "USERTrust RSA Certification Authority"
+# Serial: 2645093764781058787591871645665788717
+# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5
+# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e
+# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
diff --git a/samples/mqtt_example/resources/rsa_cert.pem b/samples/mqtt_example/resources/rsa_cert.pem
new file mode 100644
index 0000000000000000000000000000000000000000..a8f357f2c97432644f35bedf5cad373fbbbe597d
--- /dev/null
+++ b/samples/mqtt_example/resources/rsa_cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICsjCCAZoCCQCq0D93IhEzRjANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBu
+b2RlanNJb3RUZXN0aW5nMB4XDTIwMTAxOTIyMTAyMVoXDTI2MDQxMTIyMTAyMVow
+GzEZMBcGA1UEAwwQbm9kZWpzSW90VGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKQ0OS71+Plqm8A7qoEOdoMdxQ8f0qcgOBBUxB12UMRGeOeq
+6iUe4VESAh7D9n39lr/l5NLnaznC/Di3V8/nhBTQs95dYQ6GZdJ3chQ+Y7ouI8aP
+aQQh/4xEyYgbzq2EwqQ0w6thG0VX22F/dM2LsANHjYQacuuFHa3MyIFlLRxvMx9I
+HRwcvgmZioqlv6ym6/STOb5KmCtwGVKr/vN+EBTFN9Ag2xnQEraen54oCGBgSv+O
+BrFwu6q9d3oZt2IhxLeIbcnHUCf7YlfxXC3HK5De3qPfrnR7Q4sTIpphjzcviwZV
+h+2vq3O6guIZcA5V0s+jP0x9NNQPdZH42eUfiXsCAwEAATANBgkqhkiG9w0BAQsF
+AAOCAQEASM0QZKSd0ZAbFfrjioP8ygDXePKoI/efXTX2XpjbygDmwJeZLbt5pRvR
+lcD8W5XWF/+L4UBwn7b081PL2ZYCJpZp+0jr4oFsCvitpi9Fi0/6sgiHPIc4XD2y
+Pek2SFoEcQLX36aD3ScWQR13xfJj14nrovHbvWPKijl7UeQlS1ZFXf3kI3aVBGTp
+fMUIRl84eRg+sWS9sNacArsUJpauMpms+Ms611lMbnP2K+J9KHvT5Sb163VvHj6B
+3AefC/q2BO+h1Lzs3fBYnQiq+GD4qc5nonomHdau94RU/iXcvtEgsWRjlAbMz8Fj
+4f5AoLEzrZ1eIeUH/V48kyVCAjw4wQ==
+-----END CERTIFICATE-----
diff --git a/samples/mqtt_example/resources/rsa_private.pem b/samples/mqtt_example/resources/rsa_private.pem
new file mode 100644
index 0000000000000000000000000000000000000000..056f65ef93adb974bce000f08b9ca31a0adfc6ca
--- /dev/null
+++ b/samples/mqtt_example/resources/rsa_private.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQCkNDku9fj5apvA
+O6qBDnaDHcUPH9KnIDgQVMQddlDERnjnquolHuFREgIew/Z9/Za/5eTS52s5wvw4
+t1fP54QU0LPeXWEOhmXSd3IUPmO6LiPGj2kEIf+MRMmIG86thMKkNMOrYRtFV9th
+f3TNi7ADR42EGnLrhR2tzMiBZS0cbzMfSB0cHL4JmYqKpb+spuv0kzm+SpgrcBlS
+q/7zfhAUxTfQINsZ0BK2np+eKAhgYEr/jgaxcLuqvXd6GbdiIcS3iG3Jx1An+2JX
+8VwtxyuQ3t6j3650e0OLEyKaYY83L4sGVYftr6tzuoLiGXAOVdLPoz9MfTTUD3WR
++NnlH4l7AgMBAAECggEAQgKkglZrsojC+DKERsFzrx4GnB/k5T60iwwoktd/fIgA
+DtHMswOI/LhKleedbeTF93sJ1CcoGd5i2sIJ0RB3Lo7/4AKWA+rPgB54g97Y5H2r
+8CSyyPCJ9O+qPMdA/MyEGtMDXh/5gJTjInzEjeT76zWWlGa1kCzBU58hc7MiwWzl
+mh9toYFdFF5Dhj5/DQ4Ij8E6bXozRZQl9mFdeACxyNDcbFAvDOUNhRJ73zq5iFGN
+nS4j1Iw+RcDN6fISZDnqUK1rrJvv962YwgXi2rfG9JiaDcPati6q8MDKao9aBa5w
+7RC/3825v76bU+K6Z1MEcOFt8I2kaZa93wVfmmI4UQKBgQDVpSDFqRaOzpYtx691
+V/tHn86r4gRXLhlYzZuCc9/R8gyD8zbrDPwELpYFEjyHFyK4ni1FA1oqOLBbOppe
+8lhnxm57QFzuMLlMuwnlximvRUTqBEo/v3BmA/z0AkNwgcWR/mM/2PsIy4nnJmwg
+Mq5aX4NpOtVKJqkiM/vzKbg/hwKBgQDEwd+YRWJaUU9ZYAtdAskqWRCOumU5UMEA
+HwFUWsoqOIoMuMfbcJ6NQdvHyn2ZoFnoIlZjem7FCsAs9Cc13HnpsbsMndMf6hsT
+p19mExeIQ0m/FHpvNk1MWB43WH53bs6OP2nPHsaxkVoRxMCCdnzusWdEOCOBbpQs
+yyd+bwzbbQKBgQCaw7MY3ONlcgvif/v/okt6WC7L3r/MM63S4abcenpRyOj+EQrg
+fRh3IxQz+kD0j3LskFE05DfFzCkc/TfkveQC0QEpsbdgKNWi2v9RfxqlSCWi7Jao
+1VJj5FGypY0bDDcGCmT1VIaNmXx9gRzkujIJb5VvfloSDC2LhGLohHlfMwJ/IpXx
+t9J6d2XTjOJVHQRgWBFP18bsBCctxdetZCaRYtqNaa8RcoFZXXs2JuhxK5AEPcnL
+ZbEfx4McRMqmGdGnnGyhdJZJhlKgb9P78PVqLYmmbPAslV/2NnVG2nOzx0qzBE4h
+S0cdphjmvDjZnhU14L9OZ692jknhwf3z80WR/QKBgDibdXdw6JppPg5W1egpkGav
+Y6yxJp/pP9ZoG0QWcBj0fkXbHgSFOYwEynbtQpBkkWKkbN833SOq+vI64Fwhky5K
+q9l8VOyys3KH3xEyeq8VqrDeCRudWJjcPdvf7ws6L+4qZXYV8boP7EqplnqOFx3J
+O0S+MOfB7EG7WDyK+wxL
+-----END PRIVATE KEY-----
diff --git a/samples/mqtt_example/roots.pem b/samples/mqtt_example/roots.pem
new file mode 100644
index 0000000000000000000000000000000000000000..f5f842c5ac5845bb6e0fdf720512c36156c7226e
--- /dev/null
+++ b/samples/mqtt_example/roots.pem
@@ -0,0 +1,1130 @@
+# Operating CA: DigiCert
+# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Label: "Baltimore CyberTrust Root"
+# Serial: 33554617
+# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4
+# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74
+# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root CA"
+# Serial: 17154717934120587862167794914071425081
+# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
+# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
+# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G2"
+# Serial: 15385348160840213938643033620894905419
+# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d
+# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f
+# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G3"
+# Serial: 15459312981008553731928384953135426796
+# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb
+# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89
+# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root CA"
+# Serial: 10944719598952040374951832963794454346
+# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
+# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
+# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G2"
+# Serial: 4293743540046975378534879503202253541
+# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44
+# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4
+# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G3"
+# Serial: 7089244469030293291760083333884364146
+# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca
+# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e
+# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert High Assurance EV Root CA"
+# Serial: 3553400076410547919724730734378100087
+# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
+# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
+# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Trusted Root G4"
+# Serial: 7451500558977370777930084869016614236
+# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49
+# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4
+# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Label: "Entrust Root Certification Authority"
+# Serial: 1164660820
+# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4
+# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9
+# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - EC1"
+# Serial: 51543124481930649114116133369
+# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc
+# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47
+# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - G2"
+# Serial: 1246989352
+# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2
+# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4
+# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Label: "Entrust.net Premium 2048 Secure Server CA"
+# Serial: 946069240
+# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90
+# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31
+# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Commercial O=AffirmTrust
+# Subject: CN=AffirmTrust Commercial O=AffirmTrust
+# Label: "AffirmTrust Commercial"
+# Serial: 8608355977964138876
+# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7
+# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7
+# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Networking O=AffirmTrust
+# Subject: CN=AffirmTrust Networking O=AffirmTrust
+# Label: "AffirmTrust Networking"
+# Serial: 8957382827206547757
+# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f
+# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f
+# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Premium O=AffirmTrust
+# Subject: CN=AffirmTrust Premium O=AffirmTrust
+# Label: "AffirmTrust Premium"
+# Serial: 7893706540734352110
+# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57
+# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27
+# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Label: "AffirmTrust Premium ECC"
+# Serial: 8401224907861490260
+# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d
+# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb
+# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Label: "GlobalSign Root CA"
+# Serial: 4835703278459707669005204
+# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
+# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
+# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Label: "GlobalSign Root CA - R3"
+# Serial: 4835703278459759426209954
+# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
+# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
+# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Label: "GlobalSign ECC Root CA - R5"
+# Serial: 32785792099990507226680698011560947931244
+# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08
+# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa
+# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Label: "GlobalSign Root CA - R6"
+# Serial: 1417766617973444989252670301619537
+# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae
+# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1
+# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+# Note: "GlobalSign Root CA - R7" not added on purpose. It is P-521.
+
+# Operating CA: GoDaddy
+# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Label: "Go Daddy Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
+# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
+# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
+# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
+# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Label: "Starfield Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24
+# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a
+# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Label: "Go Daddy Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67
+# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4
+# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
+# Subject: CN=AAA Certificate Services O=Comodo CA Limited
+# Label: "Comodo AAA Services root"
+# Serial: 1
+# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0
+# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49
+# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
+# Label: "COMODO Certification Authority"
+# Serial: 104350513648249232941998508985834464573
+# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75
+# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b
+# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Label: "COMODO ECC Certification Authority"
+# Serial: 41578283867086692638256921589707938090
+# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
+# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
+# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Label: "COMODO RSA Certification Authority"
+# Serial: 101909084537582093308941363524873193117
+# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18
+# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4
+# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Label: "USERTrust ECC Certification Authority"
+# Serial: 123013823720199481456569720443997572134
+# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1
+# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0
+# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Label: "USERTrust RSA Certification Authority"
+# Serial: 2645093764781058787591871645665788717
+# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5
+# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e
+# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R1
+# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R1
+# Label: "GTS Root R1"
+# Serial: 0203E5936F31B01349886BA217
+# MD5 Fingerprint: 05:FE:D0:BF:71:A8:A3:76:63:DA:01:E0:D8:52:DC:40
+# SHA1 Fingerprint: E5:8C:1C:C4:91:3B:38:63:4B:E9:10:6E:E3:AD:8E:6B:9D:D9:81:4A
+# SHA256 Fingerprint: D9:47:43:2A:BD:E7:B7:FA:90:FC:2E:6B:59:10:1B:12:80:E0:E1:C7:E4:E4:0F:A3:C6:88:7F:FF:57:A7:F4:CF
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
+27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
+Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
+TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
+qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
+szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
+Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
+MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
+wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
+aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
+VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
+C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
+h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
+7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
+ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
+MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
+Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
+6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
+0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
+2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
+bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R2
+# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R2
+# Label: "GTS Root R2"
+# Serial: 0203E5AEC58D04251AAB1125AA
+# MD5 Fingerprint=1E:39:C0:53:E6:1E:29:82:0B:CA:52:55:36:5D:57:DC
+# SHA1 Fingerprint=9A:44:49:76:32:DB:DE:FA:D0:BC:FB:5A:7B:17:BD:9E:56:09:24:94
+# SHA256 Fingerprint=8D:25:CD:97:22:9D:BF:70:35:6B:DA:4E:B3:CC:73:40:31:E2:4C:F0:0F:AF:CF:D3:2D:C7:6E:B5:84:1C:7E:A8
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt
+nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY
+6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu
+MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k
+RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg
+f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV
++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo
+dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
+Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa
+G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq
+gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H
+vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC
+B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u
+NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg
+yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev
+HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6
+xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR
+TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg
+JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV
+7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl
+6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R3
+# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R3
+# Label: "GTS Root R3"
+# Serial: 0203E5B882EB20F825276D3D66
+# MD5 Fingerprint: 3E:E7:9D:58:02:94:46:51:94:E5:E0:22:4A:8B:E7:73
+# SHA1 Fingerprint: ED:E5:71:80:2B:C8:92:B9:5B:83:3C:D2:32:68:3F:09:CD:A0:1E:46
+# SHA256 Fingerprint: 34:D8:A7:3E:E2:08:D9:BC:DB:0D:95:65:20:93:4B:4E:40:E6:94:82:59:6E:8B:6F:73:C8:42:6B:01:0A:6F:48
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G
+jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2
+4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7
+VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm
+ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R4
+# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R4
+# Label: "GTS Root R4"
+# Serial: 0203E5C068EF631A9C72905052
+# MD5 Fingerprint=43:96:83:77:19:4D:76:B3:9D:65:52:E4:1D:22:A5:E8
+# SHA1 Fingerprint=77:D3:03:67:B5:E0:0C:15:F6:0C:38:61:DF:7C:E1:3B:92:46:4D:47
+# SHA256 Fingerprint=34:9D:FA:40:58:C5:E2:63:12:3B:39:8A:E7:95:57:3C:4E:13:13:C8:3F:E6:8F:93:55:6C:D5:E8:03:1B:3C:7D
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi
+QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR
+HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D
+9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8
+p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
+# Issuer: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
+# Label: "GlobalSign R4"
+# Serial: 0203E57EF53F93FDA50921B2A6
+# MD5 Fingerprint: 26:29:F8:6D:E1:88:BF:A2:65:7F:AA:C4:CD:0F:7F:FC
+# SHA1 Fingerprint: 6B:A0:B0:98:E1:71:EF:5A:AD:FE:48:15:80:77:10:F4:BD:6F:0B:28
+# SHA256 Fingerprint: B0:85:D7:0B:96:4F:19:1A:73:E4:AF:0D:54:AE:7A:0E:07:AA:FD:AF:9B:71:DD:08:62:13:8A:B7:32:5A:24:A2
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD
+VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw
+MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g
+UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT
+BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx
+uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV
+HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/
++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147
+bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
diff --git a/samples/mqtt_example/rsa_private.pem b/samples/mqtt_example/rsa_private.pem
new file mode 100644
index 0000000000000000000000000000000000000000..c0cf6a64044834fd3bb480b3f96444d8359f809b
--- /dev/null
+++ b/samples/mqtt_example/rsa_private.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDD/X8gdE24Svzm
+csvCqd1QVDX7EoZ6CyAZ7BbkakqKAHaDxyajzUFSYzVk+kzTktNUiPgTIZBzj0BT
+Hd5a2MLayhsaSwIxyeCplL3n40GQbExOJzrteViI8cXMfRPwjnhyqHlh7iuu7G7O
+FQdCQCig5IM/Kw5HEV6Nj4CUXasxJqjM9vYIckiwzznyxrQVFgv7eXnnsYWQkfJe
+nLDjvQ2h+XcjigCw8xJwR3jy++pBQhmKPbl4oV3l89YFddbxdIcAPhFN/0v5fc+L
+tSutmuueR+mT2HRUkcwBqpyqGzzqoOnrv1bbWVd1mnyFZbmOnc7vGvw9NSnjflad
+VaEarqY9AgMBAAECggEADQPIbV9LyfEw2hzFayfcinkNHJ8eTvxuJUqIOqLUUFW3
+iQiwiDAZJl9wLERy1ZnqbrKpxptz/DiHDP3uxhme1uiU5CoW+zdss9YsxjlRIUYP
+yyDPyPVF69IiUHH94PuVBAgsB1TJkdQhh43d7YhVKloCXS9+wzlkDgJ5h2Cw/ZJ1
+zahR/6vW7GAfTV2i8S/DeZUCN6o4xOG8+d5aMJnb6+Q/glb6ZCFj8vI2aAaA8Phq
+eK1LrkzY4N5U2tCKt8CRCEdOvPiFUKgXNlNWmlsShKiY4EfMvl9SbUX+au32eetG
+Wqat9iTYUEnMstESUpGdPcBiEF2YcunnHZz1wsu8AQKBgQDxjAFIMEZv/8ttl9Lc
+AHXyvlmvbgbx/KeOXN9EAaPQCZokZ1PUsj0mUfyqZEd3r5E8CcvWDLq/yLVFcMxt
+YrlAbMl98bzMBGiMe+562t57u5rkB7+VagltJuab3rIoHMHyd15SmrRgKElb6QGZ
+UZet5Zv8pbxxh2YGRe8vZxQqYwKBgQDPt6iF2ExmU2yF6jEAntG07KAJutEjoWpI
+B6lsAOtT2FzFK9R7V23q7Awjmi5F5Oe4u0g4Yu25ivAcRyr4IOQrs+ftdi+Kti1F
+CYIqXt9xyJw5ux3Ab3hS0cy6JurhhFsvk5y+ytUOh4uoVuAPFUNREwwvjDKN+hME
+muzVewt+3wKBgCYHUtRYtV5AuXhhpNL6R5eWHGygN/u1OXQSbxw33eCNAnWkxu//
+t9zmn478BrxzKbx4Fl1215gGM3PhVG4MUvovpnFrs7uzHfqwMFWrS8fTO4mXJrSR
+YzaKH1h+8TGbhXV1EaaTsL5K2XHc92F6FRVNxwc52LdPB+MI86VU5zndAoGBAL0x
+7niC7Auj3swW5K1I+3+Mq7RRCd8nTfPvrpxmNfJ3twAMjQwPNVntyJzA+XbGKV20
+j/J0AU2nxE4tcHDzHIDF6/D5XhI9HvyrzXikU2eDLvDSgyXdIj5lQ9EmU3g3owqx
+q+qIOwlx4n3hK1Hxrw/whn/kdcOlzJ68Mg28dlsHAoGBALt9CNv+WgvZvNDFdX7K
+M3N/Q3iIHTTTkuXIZwBz5u5CxmbgEsJ83kt+lctvmg+V0oWMRy0/VVvx3yRj6zGq
+YkDzvuuX4aqFelFyr4DfIaQSE+MhFix4hG6tiWh1axc74YrakDL1A9JZtYYYIV/c
+49Q8J4ctvDo07wMgXONiFEBX
+-----END PRIVATE KEY-----
diff --git a/samples/mqtt_example/rsa_public.pem b/samples/mqtt_example/rsa_public.pem
new file mode 100644
index 0000000000000000000000000000000000000000..5d520d5814daec3acdf56eb70ed260109d8d13c1
--- /dev/null
+++ b/samples/mqtt_example/rsa_public.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw/1/IHRNuEr85nLLwqnd
+UFQ1+xKGegsgGewW5GpKigB2g8cmo81BUmM1ZPpM05LTVIj4EyGQc49AUx3eWtjC
+2sobGksCMcngqZS95+NBkGxMTic67XlYiPHFzH0T8I54cqh5Ye4rruxuzhUHQkAo
+oOSDPysORxFejY+AlF2rMSaozPb2CHJIsM858sa0FRYL+3l557GFkJHyXpyw470N
+ofl3I4oAsPMScEd48vvqQUIZij25eKFd5fPWBXXW8XSHAD4RTf9L+X3Pi7UrrZrr
+nkfpk9h0VJHMAaqcqhs86qDp679W21lXdZp8hWW5jp3O7xr8PTUp435WnVWhGq6m
+PQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/samples/mqtt_example/temperature__mqtt_example_nodejs.js b/samples/mqtt_example/temperature__mqtt_example_nodejs.js
new file mode 100644
index 0000000000000000000000000000000000000000..8c8a140cad5942f61569b085abebba8839db2b11
--- /dev/null
+++ b/samples/mqtt_example/temperature__mqtt_example_nodejs.js
@@ -0,0 +1,887 @@
+// Copyright 2020 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';
+
+// [START iot_mqtt_include]
+const {readFileSync} = require('fs');
+const jwt = require('jsonwebtoken');
+const mqtt = require('mqtt');
+// [END iot_mqtt_include]
+
+// 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;
+
+console.log('Google Cloud IoT Core MQTT example.');
+
+// 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 = readFileSync(privateKeyFile);
+  return jwt.sign(token, privateKey, {algorithm: algorithm});
+};
+// [END iot_mqtt_jwt]
+
+// Publish numMessages messages asynchronously, starting from message
+// messagesSent.
+// [START iot_mqtt_publish]
+const publishAsync = (
+  mqttTopic,
+  client,
+  iatTime,
+  messagesSent,
+  numMessages,
+  connectionArgs
+) => {
+  // 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.');
+    }
+    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.`);
+  }
+
+  setTimeout(() => {
+  let currentTimestamp = Date.now();
+	const payload = JSON.stringify({
+  "timestamp": currentTimestamp,
+  "temperature":"89" }); 
+    //const payload = `${argv.registryId}/${argv.deviceId}-payload-${messagesSent}`;
+
+    // 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);
+    client.publish(mqttTopic, payload, {qos: 1}, err => {
+      if (!err) {
+        shouldBackoff = false;
+        backoffTime = MINIMUM_BACKOFF_TIME;
+      }
+    });
+
+    const schedulePublishDelayMs = argv.messageType === 'events' ? 1000 : 2000;
+    setTimeout(() => {
+      // [START iot_mqtt_jwt_refresh]
+      const secsFromIssue = parseInt(Date.now() / 1000) - iatTime;
+      if (secsFromIssue > argv.tokenExpMins * 60) {
+        iatTime = parseInt(Date.now() / 1000);
+        console.log(`\tRefreshing token after ${secsFromIssue} seconds.`);
+
+        client.end();
+        connectionArgs.password = createJwt(
+          argv.projectId,
+          argv.privateKeyFile,
+          argv.algorithm
+        );
+        connectionArgs.protocolId = 'MQTT';
+        connectionArgs.protocolVersion = 4;
+        connectionArgs.clean = true;
+        client = mqtt.connect(connectionArgs);
+        // [END iot_mqtt_jwt_refresh]
+
+        client.on('connect', success => {
+          console.log('connect');
+          if (!success) {
+            console.log('Client not connected...');
+          } else if (!publishChainInProgress) {
+            publishAsync(
+              mqttTopic,
+              client,
+              iatTime,
+              messagesSent,
+              numMessages,
+              connectionArgs
+            );
+          }
+        });
+
+        client.on('close', () => {
+          console.log('close');
+          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
+        });
+      }
+      publishAsync(
+        mqttTopic,
+        client,
+        iatTime,
+        messagesSent + 1,
+        numMessages,
+        connectionArgs
+      );
+    }, schedulePublishDelayMs);
+  }, publishDelayMs);
+};
+// [END iot_mqtt_publish]
+
+const mqttDeviceDemo = (
+  deviceId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  messageType,
+  numMessages
+) => {
+  // [START iot_mqtt_run]
+
+  // const deviceId = `myDevice`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const messageType = `events`;
+  // const numMessages = 5;
+
+  // The mqttClientId is a unique string that identifies this device. For Google
+  // Cloud IoT Core, it must be in the format below.
+  const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${deviceId}`;
+
+  // With Google Cloud IoT Core, the username field is ignored, however it must be
+  // non-empty. The password field is used to transmit a JWT to authorize the
+  // device. The "mqtts" protocol causes the library to connect using SSL, which
+  // is required for Cloud IoT Core.
+  const connectionArgs = {
+    host: mqttBridgeHostname,
+    port: mqttBridgePort,
+    clientId: mqttClientId,
+    username: 'unused',
+    password: createJwt(projectId, privateKeyFile, algorithm),
+    protocol: 'mqtts',
+    secureProtocol: 'TLSv1_2_method',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // Create a client, and connect to the Google MQTT bridge.
+  const iatTime = parseInt(Date.now() / 1000);
+  const client = mqtt.connect(connectionArgs);
+
+  // Subscribe to the /devices/{device-id}/config topic to receive config updates.
+  // Config updates are recommended to use QoS 1 (at least once delivery)
+  client.subscribe(`/devices/${deviceId}/config`, {qos: 1});
+
+  // Subscribe to the /devices/{device-id}/commands/# topic to receive all
+  // commands or to the /devices/{device-id}/commands/<subfolder> to just receive
+  // messages published to a specific commands folder; we recommend you use
+  // QoS 0 (at most once delivery)
+  client.subscribe(`/devices/${deviceId}/commands/#`, {qos: 0});
+
+  // The MQTT topic that this device will publish data to. The MQTT topic name is
+  // required to be in the format below. The topic name must end in 'state' to
+  // publish state and 'events' to publish telemetry. Note that this is not the
+  // same as the device registry's Cloud Pub/Sub topic.
+  const mqttTopic = `/devices/${deviceId}/${messageType}`;
+
+  client.on('connect', success => {
+    console.log('connect');
+    if (!success) {
+      console.log('Client not connected...');
+    } else if (!publishChainInProgress) {
+      publishAsync(mqttTopic, client, iatTime, 1, numMessages, connectionArgs);
+    }
+  });
+
+  client.on('close', () => {
+    console.log('close');
+    shouldBackoff = true;
+  });
+
+  client.on('error', err => {
+    console.log('error', err);
+  });
+
+  client.on('message', (topic, message) => {
+    let messageStr = 'Message received: ';
+    if (topic === `/devices/${deviceId}/config`) {
+      messageStr = 'Config message received: ';
+    } else if (topic.startsWith(`/devices/${deviceId}/commands`)) {
+      messageStr = 'Command message received: ';
+    }
+
+    messageStr += Buffer.from(message, 'base64').toString('ascii');
+    console.log(messageStr);
+  });
+
+  client.on('packetsend', () => {
+    // Note: logging packet send is very verbose
+  });
+
+  // Once all of the messages have been published, the connection to Google Cloud
+  // IoT will be closed and the process will exit. See the publishAsync method.
+  // [END iot_mqtt_run]
+};
+
+// Attaches a device to a gateway.
+const attachDevice = (deviceId, client, jwt) => {
+  // [START attach_device]
+  // const deviceId = 'my-unauth-device';
+  const attachTopic = `/devices/${deviceId}/attach`;
+  console.log(`Attaching: ${attachTopic}`);
+  let attachPayload = '{}';
+  if (jwt && jwt !== '') {
+    attachPayload = `{ 'authorization' : ${jwt} }`;
+  }
+
+  client.publish(attachTopic, attachPayload, {qos: 1}, err => {
+    if (!err) {
+      shouldBackoff = false;
+      backoffTime = MINIMUM_BACKOFF_TIME;
+    } else {
+      console.log(err);
+    }
+  });
+  // [END attach_device]
+};
+
+// Detaches a device from a gateway.
+const detachDevice = (deviceId, client, jwt) => {
+  // [START detach_device]
+  const detachTopic = `/devices/${deviceId}/detach`;
+  console.log(`Detaching: ${detachTopic}`);
+  let detachPayload = '{}';
+  if (jwt && jwt !== '') {
+    detachPayload = `{ 'authorization' : ${jwt} }`;
+  }
+
+  client.publish(detachTopic, detachPayload, {qos: 1}, err => {
+    if (!err) {
+      shouldBackoff = false;
+      backoffTime = MINIMUM_BACKOFF_TIME;
+    } else {
+      console.log(err);
+    }
+  });
+  // [END detach_device]
+};
+
+// Publish numMessages messages asynchronously through a gateway client connection
+const publishAsyncGateway = (
+  client,
+  iatTime,
+  tokenExpMins,
+  messagesSent,
+  numMessages,
+  registryId,
+  deviceId,
+  gatewayId,
+  connectionArgs,
+  projectId,
+  privateKeyFile,
+  algorithm
+) => {
+  // 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(() => {
+      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);
+      }
+      publishAsyncGateway(
+        client,
+        iatTime,
+        tokenExpMins,
+        messagesSent + 1,
+        numMessages,
+        registryId,
+        deviceId,
+        gatewayId
+      );
+    }, schedulePublishDelayMs);
+  }, publishDelayMs);
+};
+
+// Sends data from a gateway on behalf of a device that is bound to that gateway.
+const sendDataFromBoundDevice = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  numMessages,
+  tokenExpMins
+) => {
+  // [START iot_send_data_from_bound_device]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const numMessages = 5;
+  // const tokenExpMins = 60;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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');
+        publishAsyncGateway(
+          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_data_from_bound_device]
+};
+
+// Listen for configuration messages on a gateway and bound device.
+const listenForConfigMessages = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  clientDuration
+) => {
+  // [START iot_listen_for_config_messages]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const clientDuration = 60000;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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 iot_listen_for_config_messages]
+};
+
+// Listen for error messages on a gateway.
+const listenForErrorMessages = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  clientDuration
+) => {
+  // [START iot_listen_for_error_messages]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const projectId = `my-project-123`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const clientDuration = 60000;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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 iot_listen_for_error_messages]
+};
+
+const {argv} = require('yargs')
+  .options({
+    projectId: {
+      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',
+    },
+    cloudRegion: {
+      default: 'us-central1',
+      description: 'GCP cloud region.',
+      requiresArg: true,
+      type: 'string',
+    },
+    registryId: {
+      description: 'Cloud IoT registry ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    deviceId: {
+      description: 'Cloud IoT device ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    privateKeyFile: {
+      description: 'Path to private key file.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    serverCertFile: {
+      description: 'Path to server certificate file.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    algorithm: {
+      description: 'Encryption algorithm to generate the JWT.',
+      requiresArg: true,
+      demandOption: true,
+      choices: ['RS256', 'ES256'],
+      type: 'string',
+    },
+    tokenExpMins: {
+      default: 20,
+      description: 'Minutes to JWT token expiration.',
+      requiresArg: true,
+      type: 'number',
+    },
+    mqttBridgeHostname: {
+      default: 'mqtt.googleapis.com',
+      description: 'MQTT bridge hostname.',
+      requiresArg: true,
+      type: 'string',
+    },
+    mqttBridgePort: {
+      default: 8883,
+      description: 'MQTT bridge port.',
+      requiresArg: true,
+      type: 'number',
+    },
+  })
+  .command(
+    'mqttDeviceDemo',
+    'Connects a device, sends data, and receives data',
+    {
+      messageType: {
+        default: 'events',
+        description: 'Message type to publish.',
+        requiresArg: true,
+        choices: ['events', 'state'],
+        type: 'string',
+      },
+      numMessages: {
+        default: 10,
+        description: 'Number of messages to publish.',
+        demandOption: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      mqttDeviceDemo(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.messageType,
+        opts.numMessages
+      );
+    }
+  )
+  .command(
+    'sendDataFromBoundDevice',
+    'Sends data from a gateway on behalf of a bound device.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      numMessages: {
+        default: 10,
+        description: 'Number of messages to publish.',
+        demandOption: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      sendDataFromBoundDevice(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.numMessages,
+        opts.tokenExpMins
+      );
+    }
+  )
+  .command(
+    'listenForConfigMessages',
+    'Listens for configuration changes on a gateway and bound device.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      clientDuration: {
+        default: 60000,
+        description: 'Duration in milliseconds for MQTT client to run.',
+        requiresArg: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      listenForConfigMessages(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.clientDuration
+      );
+    }
+  )
+  .command(
+    'listenForErrorMessages',
+    'Listens for error messages on a gateway.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      clientDuration: {
+        default: 60000,
+        description: 'Duration in milliseconds for MQTT client to run.',
+        requiresArg: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      listenForErrorMessages(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.clientDuration
+      );
+    }
+  )
+  .example(
+    'node $0 mqttDeviceDemo --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --numMessages=10 \\\n'
+  )
+  .example(
+    'node $0 sendDataFromBoundDevice --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n'
+  )
+  .example(
+    'node $0 listenForConfigMessages --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n\t--clientDuration=300000 \\\n'
+  )
+  .example(
+    'node $0 listenForErrorMessages --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n\t--clientDuration=300000 \\\n'
+  )
+  .wrap(120)
+  .recommendCommands()
+  .epilogue('For more information, see https://cloud.google.com/iot-core/docs')
+  .help()
+  .strict();
diff --git a/samples/mqtt_example/test/cloudiot_mqtt_example.test.js b/samples/mqtt_example/test/cloudiot_mqtt_example.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..48ec95d4688ef13092948673068f8a1cf51df822
--- /dev/null
+++ b/samples/mqtt_example/test/cloudiot_mqtt_example.test.js
@@ -0,0 +1,268 @@
+// Copyright 2020 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 assert = require('assert');
+const cp = require('child_process');
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+const util = require('util');
+const exec = util.promisify(require('child_process').exec);
+const iot = require('@google-cloud/iot');
+const {PubSub} = require('@google-cloud/pubsub');
+const uuid = require('uuid');
+
+const {after, before, it, xit} = require('mocha');
+
+const projectId =
+  process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
+const topicName = `nodejs-iot-test-mqtt-topic-${uuid.v4()}`;
+const registryName = `nodejs-iot-test-mqtt-registry-${uuid.v4()}`;
+const region = 'us-central1';
+const rsaPublicCert = 'resources/rsa_cert.pem'; //process.env.NODEJS_IOT_RSA_PUBLIC_CERT;
+const rsaPrivateKey = 'resources/rsa_private.pem'; //process.env.NODEJS_IOT_RSA_PRIVATE_KEY;
+const serverCert = 'resources/roots.pem'; //process.env.NODEJS_IOT_SERVER_CERT;'
+
+const helper = 'node ../manager/manager.js';
+const cmd = 'node cloudiot_mqtt_example_nodejs.js';
+
+const cmdSuffix = ` --privateKeyFile=${rsaPrivateKey} --serverCertFile=${serverCert} --algorithm=RS256`;
+const installDeps = 'npm install';
+
+const iotClient = new iot.v1.DeviceManagerClient();
+const pubSubClient = new PubSub({projectId});
+
+assert.ok(execSync(installDeps, '../manager'));
+before(async () => {
+  assert(
+    process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT,
+    'Must set GOOGLE_CLOUD_PROJECT or GCLOUD_PROJECT environment variable!'
+  );
+  assert(
+    process.env.GOOGLE_APPLICATION_CREDENTIALS,
+    'Must set GOOGLE_APPLICATION_CREDENTIALS environment variable!'
+  );
+  // Create a unique topic to be used for testing.
+  const [topic] = await pubSubClient.createTopic(topicName);
+
+  // Creates a registry to be used for tests.
+  const createRegistryRequest = {
+    parent: iotClient.locationPath(projectId, region),
+    deviceRegistry: {
+      id: registryName,
+      eventNotificationConfigs: [
+        {
+          pubsubTopicName: topic.name,
+        },
+      ],
+    },
+  };
+  await execSync(`${helper} setupIotTopic ${topicName}`);
+
+  await iotClient.createDeviceRegistry(createRegistryRequest);
+});
+
+after(async () => {
+  await pubSubClient.topic(topicName).delete();
+
+  // Cleans up the registry by removing all associations and deleting all devices.
+  execSync(`${helper} unbindAllDevices ${registryName}`);
+  execSync(`${helper} clearRegistry ${registryName}`);
+});
+
+it('should receive configuration message', async () => {
+  const localDevice = 'test-rsa-device';
+  const localRegName = `${registryName}-rsa256`;
+
+  let output = await execSync(`${helper} setupIotTopic ${topicName}`);
+  await execSync(`${helper} createRegistry ${localRegName} ${topicName}`);
+  await execSync(
+    `${helper} createRsa256Device ${localDevice} ${localRegName} ${rsaPublicCert}`
+  );
+
+  output = await execSync(
+    `${cmd} mqttDeviceDemo --messageType=events --registryId="${localRegName}" --deviceId="${localDevice}" --numMessages=1 ${cmdSuffix}`
+  );
+
+  assert.strictEqual(new RegExp('connect').test(output), true);
+  assert.strictEqual(new RegExp('Config message received:').test(output), true);
+
+  // Check / cleanup
+  await execSync(`${helper} getDeviceState ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteDevice ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteRegistry ${localRegName}`);
+});
+
+it('should send event message', async () => {
+  const localDevice = 'test-rsa-device';
+  const localRegName = `${registryName}-rsa256`;
+
+  await execSync(`${helper} setupIotTopic ${topicName}`);
+  await execSync(`${helper} createRegistry ${localRegName} ${topicName}`);
+  await execSync(
+    `${helper} createRsa256Device ${localDevice} ${localRegName} ${rsaPublicCert}`
+  );
+
+  const output = await execSync(
+    `${cmd} mqttDeviceDemo --messageType=events --registryId="${localRegName}" --deviceId="${localDevice}" --numMessages=1 ${cmdSuffix}`
+  );
+  assert.strictEqual(new RegExp('Publishing message:').test(output), true);
+
+  // Check / cleanup
+  await execSync(`${helper} getDeviceState ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteDevice ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteRegistry ${localRegName}`);
+});
+
+it('should send state message', async () => {
+  const localDevice = 'test-rsa-device';
+  const localRegName = `${registryName}-rsa256`;
+  await execSync(`${helper} setupIotTopic ${topicName}`);
+  await execSync(`${helper} createRegistry ${localRegName} ${topicName}`);
+  await execSync(
+    `${helper} createRsa256Device ${localDevice} ${localRegName} ${rsaPublicCert}`
+  );
+
+  const output = await execSync(
+    `${cmd} mqttDeviceDemo --messageType=state --registryId="${localRegName}" --deviceId="${localDevice}" --numMessages=1 ${cmdSuffix}`
+  );
+  assert.strictEqual(new RegExp('Publishing message:').test(output), true);
+
+  // Check / cleanup
+  await execSync(`${helper} getDeviceState ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteDevice ${localDevice} ${localRegName}`);
+  await execSync(`${helper} deleteRegistry ${localRegName}`);
+});
+
+xit('should receive command message', async () => {
+  const deviceId = 'commands-device';
+  const message = 'rotate 180 degrees';
+
+  await execSync(
+    `${helper} createRsa256Device ${deviceId} ${registryName} ${rsaPublicCert}`
+  );
+
+  const mqttClientExec = exec(
+    `${cmd} mqttDeviceDemo --registryId=${registryName} --deviceId=${deviceId} --numMessages=5 --mqttBridgePort=8883 ${cmdSuffix}`
+  );
+
+  await execSync(
+    `${helper} sendCommand ${deviceId} ${registryName} "${message}"`
+  );
+
+  const {stdout} = await mqttClientExec;
+
+  assert.strictEqual(
+    new RegExp(`Command message received: ${message}`).test(stdout.toString()),
+    true
+  );
+
+  // Cleanup
+  await iotClient.deleteDevice({
+    name: iotClient.devicePath(projectId, region, registryName, deviceId),
+  });
+});
+
+it('should listen for bound device config message', async () => {
+  const gatewayId = 'nodejs-test-gateway-cm';
+  await execSync(
+    `${helper} createGateway --registryId=${registryName} --gatewayId=${gatewayId} --publicKeyFormat=RSA_X509_PEM --publicKeyFile=${rsaPublicCert}`
+  );
+
+  const deviceId = 'nodejs-test-device-cm';
+  await execSync(`${helper} createUnauthDevice  ${deviceId} ${registryName}`);
+
+  await execSync(
+    `${helper} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+
+  // listen for configuration changes
+  const out = await execSync(
+    `${cmd} listenForConfigMessages --deviceId=${deviceId} --gatewayId=${gatewayId} --registryId=${registryName} --clientDuration=10000 ${cmdSuffix}`
+  );
+
+  assert.strictEqual(new RegExp('message received').test(out), true);
+
+  // cleanup
+  await execSync(
+    `${helper} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+  await execSync(`${helper} deleteDevice ${gatewayId} ${registryName}`);
+  await execSync(`${helper} deleteDevice ${deviceId} ${registryName}`);
+});
+
+it('should listen for error topic messages', async () => {
+  const gatewayId = `nodejs-test-gateway-err-${uuid.v4()}`;
+  await execSync(
+    `${helper} createGateway --registryId=${registryName} --gatewayId=${gatewayId} --publicKeyFormat=RSA_X509_PEM --publicKeyFile=${rsaPublicCert}`
+  );
+
+  // create a device but don't associate it with the gateway
+  const deviceId = `nodejs-test-device-err-${uuid.v4()}`;
+  await execSync(
+    `${helper} createRsa256Device ${deviceId} ${registryName} ${rsaPublicCert}`
+  );
+
+  // check error topic contains error of attaching a device that is not bound
+  const out = await cp.execSync(
+    `${cmd} listenForErrorMessages --gatewayId=${gatewayId} --registryId=${registryName} --deviceId=${deviceId} --clientDuration=30000 ${cmdSuffix}`
+  );
+
+  const stdout = Buffer.from(out).toString();
+
+  assert.strictEqual(
+    new RegExp('message received on error topic').test(stdout),
+    true
+  );
+
+  // cleanup
+  await execSync(
+    `${helper} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+  await execSync(`${helper} deleteDevice ${gatewayId} ${registryName}`);
+  await execSync(`${helper} deleteDevice ${deviceId} ${registryName}`);
+});
+
+xit('should send data from bound device', async () => {
+  const gatewayId = `nodejs-test-gateway-sdbd-${uuid.v4()}`;
+  await execSync(
+    `${helper} createGateway --registryId=${registryName} --gatewayId=${gatewayId} --publicKeyFormat=RSA_X509_PEM --publicKeyFile=${rsaPublicCert}`
+  );
+
+  const deviceId = `nodejs-test-sdbd-${uuid.v4()}`;
+  await iotClient.createDevice({
+    parent: iotClient.registryPath(projectId, region, registryName),
+    device: {
+      id: deviceId,
+    },
+  });
+
+  await execSync(
+    `${helper} bindDeviceToGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+
+  // relay telemetry on behalf of device
+  const out = await execSync(
+    `${cmd} sendDataFromBoundDevice --deviceId=${deviceId} --gatewayId=${gatewayId} --registryId=${registryName} --numMessages=5`
+  );
+
+  assert.strictEqual(new RegExp('Publishing message 5/5').test(out), true);
+  assert.strictEqual(new RegExp('Error: Connection refused').test(out), false);
+
+  await execSync(
+    `${helper} unbindDeviceFromGateway ${registryName} ${gatewayId} ${deviceId}`
+  );
+  await execSync(`${helper} deleteDevice ${gatewayId} ${registryName}`);
+  await execSync(`${helper} deleteDevice ${deviceId} ${registryName}`);
+});
diff --git a/samples/mqtt_example/test_temperature.js b/samples/mqtt_example/test_temperature.js
new file mode 100644
index 0000000000000000000000000000000000000000..5d5022d3b17885b4ff17fc77e578f5782002a366
--- /dev/null
+++ b/samples/mqtt_example/test_temperature.js
@@ -0,0 +1,892 @@
+// Copyright 2020 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';
+
+// [START iot_mqtt_include]
+const {readFileSync} = require('fs');
+const jwt = require('jsonwebtoken');
+const mqtt = require('mqtt');
+// [END iot_mqtt_include]
+
+// 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;
+
+console.log('Google Cloud IoT Core MQTT example.');
+
+// 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 = readFileSync(privateKeyFile);
+  return jwt.sign(token, privateKey, {algorithm: algorithm});
+};
+// [END iot_mqtt_jwt]
+
+// Publish numMessages messages asynchronously, starting from message
+// messagesSent.
+// [START iot_mqtt_publish]
+const publishAsync = (
+  mqttTopic,
+  client,
+  iatTime,
+  messagesSent,
+  numMessages,
+  connectionArgs
+) => {
+  // 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.');
+    }
+    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.`);
+  }
+
+  setTimeout(() => {
+  let currentTimestamp = Date.now();
+	const payload = JSON.stringify({
+  "timestamp": currentTimestamp,
+  "temperature": 89.7 }); 
+    //const payload = `${argv.registryId}/${argv.deviceId}-payload-${messagesSent}`;
+
+    // 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);
+    client.publish(mqttTopic, payload, {qos: 1}, err => {
+      if (!err) {
+        shouldBackoff = false;
+        backoffTime = MINIMUM_BACKOFF_TIME;
+      }
+    });
+
+    const schedulePublishDelayMs = argv.messageType === 'events' ? 1000 : 2000;
+    setTimeout(() => {
+      // [START iot_mqtt_jwt_refresh]
+      const secsFromIssue = parseInt(Date.now() / 1000) - iatTime;
+      if (secsFromIssue > argv.tokenExpMins * 60) {
+        iatTime = parseInt(Date.now() / 1000);
+        console.log(`\tRefreshing token after ${secsFromIssue} seconds.`);
+
+        client.end();
+        connectionArgs.password = createJwt(
+          argv.projectId,
+          argv.privateKeyFile,
+          argv.algorithm
+        );
+        connectionArgs.protocolId = 'MQTT';
+        connectionArgs.protocolVersion = 4;
+        connectionArgs.clean = true;
+        client = mqtt.connect(connectionArgs);
+        // [END iot_mqtt_jwt_refresh]
+
+        client.on('connect', success => {
+          console.log('connect');
+          if (!success) {
+            console.log('Client not connected...');
+          } else if (!publishChainInProgress) {
+            publishAsync(
+              mqttTopic,
+              client,
+              iatTime,
+              messagesSent,
+              numMessages,
+              connectionArgs
+            );
+          }
+        });
+
+        client.on('close', () => {
+          console.log('close');
+          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
+        });
+      }
+      publishAsync(
+        mqttTopic,
+        client,
+        iatTime,
+        messagesSent + 1,
+        numMessages,
+        connectionArgs
+      );
+    }, schedulePublishDelayMs);
+  }, publishDelayMs);
+};
+// [END iot_mqtt_publish]
+
+const mqttDeviceDemo = (
+  deviceId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  messageType,
+  numMessages
+) => {
+  // [START iot_mqtt_run]
+
+  // const deviceId = `myDevice`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const messageType = `events`;
+  // const numMessages = 5;
+
+  // The mqttClientId is a unique string that identifies this device. For Google
+  // Cloud IoT Core, it must be in the format below.
+  const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${deviceId}`;
+
+  // With Google Cloud IoT Core, the username field is ignored, however it must be
+  // non-empty. The password field is used to transmit a JWT to authorize the
+  // device. The "mqtts" protocol causes the library to connect using SSL, which
+  // is required for Cloud IoT Core.
+  const connectionArgs = {
+    host: mqttBridgeHostname,
+    port: mqttBridgePort,
+    clientId: mqttClientId,
+    username: 'unused',
+    password: createJwt(projectId, privateKeyFile, algorithm),
+    protocol: 'mqtts',
+    secureProtocol: 'TLSv1_2_method',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // Create a client, and connect to the Google MQTT bridge.
+  const iatTime = parseInt(Date.now() / 1000);
+  const client = mqtt.connect(connectionArgs);
+
+  // Subscribe to the /devices/{device-id}/config topic to receive config updates.
+  // Config updates are recommended to use QoS 1 (at least once delivery)
+  client.subscribe(`/devices/${deviceId}/config`, {qos: 1});
+
+  // Subscribe to the /devices/{device-id}/commands/# topic to receive all
+  // commands or to the /devices/{device-id}/commands/<subfolder> to just receive
+  // messages published to a specific commands folder; we recommend you use
+  // QoS 0 (at most once delivery)
+  client.subscribe(`/devices/${deviceId}/commands/#`, {qos: 0});
+
+  // The MQTT topic that this device will publish data to. The MQTT topic name is
+  // required to be in the format below. The topic name must end in 'state' to
+  // publish state and 'events' to publish telemetry. Note that this is not the
+  // same as the device registry's Cloud Pub/Sub topic.
+  let mqttTopic = `/devices/${deviceId}/${messageType}`;
+  if(messageType === 'events') {
+    console.log('Setting event topic to serenity-temperature-telemetry...');
+    mqttTopic = `/devices/${deviceId}/${messageType}/temperature-data`;
+  }
+  console.log(mqttTopic);
+
+  client.on('connect', success => {
+    console.log('connect');
+    if (!success) {
+      console.log('Client not connected...');
+    } else if (!publishChainInProgress) {
+      publishAsync(mqttTopic, client, iatTime, 1, numMessages, connectionArgs);
+    }
+  });
+
+  client.on('close', () => {
+    console.log('close');
+    shouldBackoff = true;
+  });
+
+  client.on('error', err => {
+    console.log('error', err);
+  });
+
+  client.on('message', (topic, message) => {
+    let messageStr = 'Message received: ';
+    if (topic === `/devices/${deviceId}/config`) {
+      messageStr = 'Config message received: ';
+    } else if (topic.startsWith(`/devices/${deviceId}/commands`)) {
+      messageStr = 'Command message received: ';
+    }
+
+    messageStr += Buffer.from(message, 'base64').toString('ascii');
+    console.log(messageStr);
+  });
+
+  client.on('packetsend', () => {
+    // Note: logging packet send is very verbose
+  });
+
+  // Once all of the messages have been published, the connection to Google Cloud
+  // IoT will be closed and the process will exit. See the publishAsync method.
+  // [END iot_mqtt_run]
+};
+
+// Attaches a device to a gateway.
+const attachDevice = (deviceId, client, jwt) => {
+  // [START attach_device]
+  // const deviceId = 'my-unauth-device';
+  const attachTopic = `/devices/${deviceId}/attach`;
+  console.log(`Attaching: ${attachTopic}`);
+  let attachPayload = '{}';
+  if (jwt && jwt !== '') {
+    attachPayload = `{ 'authorization' : ${jwt} }`;
+  }
+
+  client.publish(attachTopic, attachPayload, {qos: 1}, err => {
+    if (!err) {
+      shouldBackoff = false;
+      backoffTime = MINIMUM_BACKOFF_TIME;
+    } else {
+      console.log(err);
+    }
+  });
+  // [END attach_device]
+};
+
+// Detaches a device from a gateway.
+const detachDevice = (deviceId, client, jwt) => {
+  // [START detach_device]
+  const detachTopic = `/devices/${deviceId}/detach`;
+  console.log(`Detaching: ${detachTopic}`);
+  let detachPayload = '{}';
+  if (jwt && jwt !== '') {
+    detachPayload = `{ 'authorization' : ${jwt} }`;
+  }
+
+  client.publish(detachTopic, detachPayload, {qos: 1}, err => {
+    if (!err) {
+      shouldBackoff = false;
+      backoffTime = MINIMUM_BACKOFF_TIME;
+    } else {
+      console.log(err);
+    }
+  });
+  // [END detach_device]
+};
+
+// Publish numMessages messages asynchronously through a gateway client connection
+const publishAsyncGateway = (
+  client,
+  iatTime,
+  tokenExpMins,
+  messagesSent,
+  numMessages,
+  registryId,
+  deviceId,
+  gatewayId,
+  connectionArgs,
+  projectId,
+  privateKeyFile,
+  algorithm
+) => {
+  // 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(() => {
+      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);
+      }
+      publishAsyncGateway(
+        client,
+        iatTime,
+        tokenExpMins,
+        messagesSent + 1,
+        numMessages,
+        registryId,
+        deviceId,
+        gatewayId
+      );
+    }, schedulePublishDelayMs);
+  }, publishDelayMs);
+};
+
+// Sends data from a gateway on behalf of a device that is bound to that gateway.
+const sendDataFromBoundDevice = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  numMessages,
+  tokenExpMins
+) => {
+  // [START iot_send_data_from_bound_device]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const numMessages = 5;
+  // const tokenExpMins = 60;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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');
+        publishAsyncGateway(
+          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_data_from_bound_device]
+};
+
+// Listen for configuration messages on a gateway and bound device.
+const listenForConfigMessages = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  clientDuration
+) => {
+  // [START iot_listen_for_config_messages]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const clientDuration = 60000;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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 iot_listen_for_config_messages]
+};
+
+// Listen for error messages on a gateway.
+const listenForErrorMessages = (
+  deviceId,
+  gatewayId,
+  registryId,
+  projectId,
+  region,
+  algorithm,
+  privateKeyFile,
+  serverCertFile,
+  mqttBridgeHostname,
+  mqttBridgePort,
+  clientDuration
+) => {
+  // [START iot_listen_for_error_messages]
+  // const deviceId = `myDevice`;
+  // const gatewayId = `mygateway`;
+  // const registryId = `myRegistry`;
+  // const projectId = `my-project-123`;
+  // const region = `us-central1`;
+  // const algorithm = `RS256`;
+  // const privateKeyFile = `./rsa_private.pem`;
+  // const serverCertFile = `./roots.pem`;
+  // const mqttBridgeHostname = `mqtt.googleapis.com`;
+  // const mqttBridgePort = 8883;
+  // const clientDuration = 60000;
+
+  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',
+    ca: [readFileSync(serverCertFile)],
+  };
+
+  // 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 iot_listen_for_error_messages]
+};
+
+const {argv} = require('yargs')
+  .options({
+    projectId: {
+      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',
+    },
+    cloudRegion: {
+      default: 'us-central1',
+      description: 'GCP cloud region.',
+      requiresArg: true,
+      type: 'string',
+    },
+    registryId: {
+      description: 'Cloud IoT registry ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    deviceId: {
+      description: 'Cloud IoT device ID.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    privateKeyFile: {
+      description: 'Path to private key file.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    serverCertFile: {
+      description: 'Path to server certificate file.',
+      requiresArg: true,
+      demandOption: true,
+      type: 'string',
+    },
+    algorithm: {
+      description: 'Encryption algorithm to generate the JWT.',
+      requiresArg: true,
+      demandOption: true,
+      choices: ['RS256', 'ES256'],
+      type: 'string',
+    },
+    tokenExpMins: {
+      default: 20,
+      description: 'Minutes to JWT token expiration.',
+      requiresArg: true,
+      type: 'number',
+    },
+    mqttBridgeHostname: {
+      default: 'mqtt.googleapis.com',
+      description: 'MQTT bridge hostname.',
+      requiresArg: true,
+      type: 'string',
+    },
+    mqttBridgePort: {
+      default: 8883,
+      description: 'MQTT bridge port.',
+      requiresArg: true,
+      type: 'number',
+    },
+  })
+  .command(
+    'mqttDeviceDemo',
+    'Connects a device, sends data, and receives data',
+    {
+      messageType: {
+        default: 'events',
+        description: 'Message type to publish.',
+        requiresArg: true,
+        choices: ['events', 'state'],
+        type: 'string',
+      },
+      numMessages: {
+        default: 10,
+        description: 'Number of messages to publish.',
+        demandOption: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      mqttDeviceDemo(
+        opts.deviceId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.messageType,
+        opts.numMessages
+      );
+    }
+  )
+  .command(
+    'sendDataFromBoundDevice',
+    'Sends data from a gateway on behalf of a bound device.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      numMessages: {
+        default: 10,
+        description: 'Number of messages to publish.',
+        demandOption: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      sendDataFromBoundDevice(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.numMessages,
+        opts.tokenExpMins
+      );
+    }
+  )
+  .command(
+    'listenForConfigMessages',
+    'Listens for configuration changes on a gateway and bound device.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      clientDuration: {
+        default: 60000,
+        description: 'Duration in milliseconds for MQTT client to run.',
+        requiresArg: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      listenForConfigMessages(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.clientDuration
+      );
+    }
+  )
+  .command(
+    'listenForErrorMessages',
+    'Listens for error messages on a gateway.',
+    {
+      gatewayId: {
+        description: 'Cloud IoT gateway ID.',
+        requiresArg: true,
+        demandOption: true,
+        type: 'string',
+      },
+      clientDuration: {
+        default: 60000,
+        description: 'Duration in milliseconds for MQTT client to run.',
+        requiresArg: true,
+        type: 'number',
+      },
+    },
+    opts => {
+      listenForErrorMessages(
+        opts.deviceId,
+        opts.gatewayId,
+        opts.registryId,
+        opts.projectId,
+        opts.cloudRegion,
+        opts.algorithm,
+        opts.privateKeyFile,
+        opts.serverCertFile,
+        opts.mqttBridgeHostname,
+        opts.mqttBridgePort,
+        opts.clientDuration
+      );
+    }
+  )
+  .example(
+    'node $0 mqttDeviceDemo --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --numMessages=10 \\\n'
+  )
+  .example(
+    'node $0 sendDataFromBoundDevice --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n'
+  )
+  .example(
+    'node $0 listenForConfigMessages --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n\t--clientDuration=300000 \\\n'
+  )
+  .example(
+    'node $0 listenForErrorMessages --projectId=blue-jet-123 \\\n\t--registryId=my-registry --deviceId=my-node-device \\\n\t--privateKeyFile=../rsa_private.pem \\\n\t--serverCertFile=../roots.pem --algorithm=RS256 \\\n\t--cloudRegion=us-central1 --gatewayId=my-node-gateway \\\n\t--clientDuration=300000 \\\n'
+  )
+  .wrap(120)
+  .recommendCommands()
+  .epilogue('For more information, see https://cloud.google.com/iot-core/docs')
+  .help()
+  .strict();
diff --git a/samples/package.json b/samples/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..04512cbd4e5253cd04575ddc55246f8416ee2295
--- /dev/null
+++ b/samples/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "@google-cloud/iot-samples",
+  "description": "Samples for the Cloud IoT Client Library for Node.js.",
+  "files": [
+    "*.js"
+  ],
+  "license": "Apache-2.0",
+  "author": "Google LLC",
+  "engines": {
+    "node": ">=12.0.0"
+  },
+  "repository": "googleapis/nodejs-iot",
+  "private": true,
+  "scripts": {
+    "test": "cd manager && npm test && cd ../ && cd http_example && npm test && cd ../ && cd mqtt_example && npm test && cd ../ && cd access_token_example && npm test && cd ../"
+  },
+  "dependencies": {
+    "@google-cloud/iot": "^3.1.0",
+    "@google-cloud/pubsub": "^3.0.0",
+    "@google-cloud/storage": "^6.0.0"
+  },
+  "devDependencies": {
+    "chai": "^4.2.0",
+    "hash_file": "^0.1.1",
+    "jsonwebtoken": "^8.5.0",
+    "mocha": "^8.1.1",
+    "mqtt": "^4.0.0",
+    "uuid": "^8.0.0",
+    "yargs": "^16.0.0"
+  }
+}
diff --git a/samples/quickstart.js b/samples/quickstart.js
new file mode 100644
index 0000000000000000000000000000000000000000..01cd81a0329173fe26e607fef3610c3c3d9962bf
--- /dev/null
+++ b/samples/quickstart.js
@@ -0,0 +1,34 @@
+// 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
+//
+//     https://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';
+
+async function main() {
+  // [START iot_quickstart]
+  const iot = require('@google-cloud/iot');
+  const client = new iot.v1.DeviceManagerClient();
+
+  async function quickstart() {
+    const projectId = await client.getProjectId();
+    const parent = client.locationPath(projectId, 'us-central1');
+    const [resources] = await client.listDeviceRegistries({parent});
+    console.log(`${resources.length} resource(s) found.`);
+    for (const resource of resources) {
+      console.log(resource);
+    }
+  }
+  quickstart();
+  // [END iot_quickstart]
+}
+main();
diff --git a/samples/resources/README.md b/samples/resources/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ba272ccaf74fa2c773e8cc3d8cbf62312b889bd5
--- /dev/null
+++ b/samples/resources/README.md
@@ -0,0 +1,4 @@
+# Test public certificate files
+
+The public certificates in this folder are only provided for testing and should
+not be used for registering your devices.
diff --git a/samples/resources/ec_public.pem b/samples/resources/ec_public.pem
new file mode 100644
index 0000000000000000000000000000000000000000..9c7e5b2e986810a44ab7773c8075187296d6b4e4
--- /dev/null
+++ b/samples/resources/ec_public.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvcIrwr9Zb17mOu1kLHvlZ2LOYnVx
+ceKgUWX93xab9j7OGKnEeXzafG+G0D8+d0Kw26/hV7OSvO5t1sB6FHJKkQ==
+-----END PUBLIC KEY-----
diff --git a/samples/resources/logo.png b/samples/resources/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..1db90106cae8596e8d784ee62072abcd3c048669
Binary files /dev/null and b/samples/resources/logo.png differ
diff --git a/samples/resources/roots.pem b/samples/resources/roots.pem
new file mode 100644
index 0000000000000000000000000000000000000000..0a6808dba87f5cca02505884859de146d796d448
--- /dev/null
+++ b/samples/resources/roots.pem
@@ -0,0 +1,1222 @@
+# Operating CA: DigiCert
+# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Label: "Baltimore CyberTrust Root"
+# Serial: 33554617
+# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4
+# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74
+# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Label: "Cybertrust Global Root"
+# Serial: 4835703278459682877484360
+# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1
+# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6
+# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
+A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
+bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
+ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
+b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
+7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
+J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
+HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
+t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
+FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
+XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
+hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
+MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
+A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
+Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
+XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
+omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
+A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root CA"
+# Serial: 17154717934120587862167794914071425081
+# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
+# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
+# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G2"
+# Serial: 15385348160840213938643033620894905419
+# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d
+# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f
+# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G3"
+# Serial: 15459312981008553731928384953135426796
+# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb
+# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89
+# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root CA"
+# Serial: 10944719598952040374951832963794454346
+# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
+# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
+# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G2"
+# Serial: 4293743540046975378534879503202253541
+# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44
+# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4
+# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G3"
+# Serial: 7089244469030293291760083333884364146
+# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca
+# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e
+# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert High Assurance EV Root CA"
+# Serial: 3553400076410547919724730734378100087
+# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
+# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
+# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Trusted Root G4"
+# Serial: 7451500558977370777930084869016614236
+# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49
+# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4
+# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+# Operating CA: DigiCert
+# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Subject: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Label: "GeoTrust Global CA"
+# Serial: 144470
+# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5
+# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12
+# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Label: "Entrust Root Certification Authority"
+# Serial: 1164660820
+# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4
+# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9
+# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - EC1"
+# Serial: 51543124481930649114116133369
+# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc
+# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47
+# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - G2"
+# Serial: 1246989352
+# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2
+# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4
+# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Label: "Entrust.net Premium 2048 Secure Server CA"
+# Serial: 946069240
+# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90
+# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31
+# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Commercial O=AffirmTrust
+# Subject: CN=AffirmTrust Commercial O=AffirmTrust
+# Label: "AffirmTrust Commercial"
+# Serial: 8608355977964138876
+# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7
+# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7
+# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Networking O=AffirmTrust
+# Subject: CN=AffirmTrust Networking O=AffirmTrust
+# Label: "AffirmTrust Networking"
+# Serial: 8957382827206547757
+# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f
+# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f
+# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Premium O=AffirmTrust
+# Subject: CN=AffirmTrust Premium O=AffirmTrust
+# Label: "AffirmTrust Premium"
+# Serial: 7893706540734352110
+# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57
+# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27
+# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# Operating CA: Entrust Datacard
+# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Label: "AffirmTrust Premium ECC"
+# Serial: 8401224907861490260
+# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d
+# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb
+# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Label: "GlobalSign Root CA"
+# Serial: 4835703278459707669005204
+# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
+# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
+# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Label: "GlobalSign Root CA - R3"
+# Serial: 4835703278459759426209954
+# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
+# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
+# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Label: "GlobalSign ECC Root CA - R5"
+# Serial: 32785792099990507226680698011560947931244
+# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08
+# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa
+# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+# Operating CA: GlobalSign
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
+# Label: "GlobalSign Root CA - R6"
+# Serial: 1417766617973444989252670301619537
+# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae
+# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1
+# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+# Note: "GlobalSign Root CA - R7" not added on purpose. It is P-521.
+
+# Operating CA: GoDaddy
+# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Label: "Go Daddy Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
+# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
+# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
+# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
+# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Label: "Starfield Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24
+# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a
+# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Operating CA: GoDaddy
+# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Label: "Go Daddy Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67
+# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4
+# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Label: "GlobalSign Root CA - R2"
+# Serial: 4835703278459682885658125
+# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30
+# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe
+# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Label: "GlobalSign ECC Root CA - R4"
+# Serial: 14367148294922964480859022125800977897474
+# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e
+# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb
+# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
+FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
+uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
+kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
+ewv4n4Q=
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R1
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R1
+# Label: "GTS Root R1"
+# Serial: 6e:47:a9:c5:4b:47:0c:0d:ec:33:d0:89:b9:1c:f4:e1
+# MD5 Fingerprint: 82:1A:EF:D4:D2:4A:F2:9F:E2:3D:97:06:14:70:72:85
+# SHA1 Fingerprint: E1:C9:50:E6:EF:22:F8:4C:56:45:72:8B:92:20:60:D7:D5:A7:A3:E8
+# SHA256 Fingerprint: 2A:57:54:71:E3:13:40:BC:21:58:1C:BD:2C:F1:3E:15:84:63:20:3E:CE:94:BC:F9:D3:CC:19:6B:F0:9A:54:72
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH
+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
+QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
+MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
+cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
+f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX
+mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7
+zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P
+fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc
+vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4
+Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp
+zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO
+Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW
+k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+
+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF
+lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW
+Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
+d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z
+XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR
+gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3
+d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv
+J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg
+DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM
++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy
+F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9
+SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws
+E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R2
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R2
+# Label: "GTS Root R2"
+# Serial: 6e:47:a9:c6:5a:b3:e7:20:c5:30:9a:3f:68:52:f2:6f
+# MD5 Fingerprint: 44:ED:9A:0E:A4:09:3B:00:F2:AE:4C:A3:C6:61:B0:8B
+# SHA1 Fingerprint: D2:73:96:2A:2A:5E:39:9F:73:3F:E1:C7:1E:64:3F:03:38:34:FC:4D
+# SHA256 Fingerprint: C4:5D:7B:B0:8E:6D:67:E6:2E:42:35:11:0B:56:4E:5F:78:FD:92:EF:05:8C:84:0A:EA:4E:64:55:D7:58:5C:60
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH
+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
+QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
+MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
+cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
+CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg
+GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu
+XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd
+re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu
+PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1
+mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K
+8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj
+x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR
+nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0
+kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok
+twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp
+8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
+vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT
+z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA
+pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb
+pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB
+R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R
+RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk
+0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC
+5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF
+izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn
+yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R3
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R3
+# Label: "GTS Root R3"
+# Serial: 6e:47:a9:c7:6c:a9:73:24:40:89:0f:03:55:dd:8d:1d
+# MD5 Fingerprint: 1A:79:5B:6B:04:52:9C:5D:C7:74:33:1B:25:9A:F9:25
+# SHA1 Fingerprint: 30:D4:24:6F:07:FF:DB:91:89:8A:0B:E9:49:66:11:EB:8C:5E:46:E5
+# SHA256 Fingerprint: 15:D5:B8:77:46:19:EA:7D:54:CE:1C:A6:D0:B0:C4:03:E0:37:A9:17:F1:31:E8:A0:4E:1E:6B:7A:71:BA:BC:E5
+-----BEGIN CERTIFICATE-----
+MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
+736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A
+DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk
+fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA
+njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd
+-----END CERTIFICATE-----
+
+# Operating CA: Google Trust Services LLC
+# Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4
+# Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R4
+# Label: "GTS Root R4"
+# Serial: 6e:47:a9:c8:8b:94:b6:e8:bb:3b:2a:d8:a2:b2:c1:99
+# MD5 Fingerprint: 5D:B6:6A:C4:60:17:24:6A:1A:99:A8:4B:EE:5E:B4:26
+# SHA1 Fingerprint: 2A:1D:60:27:D9:4A:B1:0A:1C:4D:91:5C:CD:33:A0:CB:3E:2D:54:CB
+# SHA256 Fingerprint: 71:CC:A5:39:1F:9E:79:4B:04:80:25:30:B3:63:E1:21:DA:8A:30:43:BB:26:66:2F:EA:4D:CA:7F:C9:51:A4:BD
+-----BEGIN CERTIFICATE-----
+MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
+hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l
+xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0
+CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx
+sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
+# Subject: CN=AAA Certificate Services O=Comodo CA Limited
+# Label: "Comodo AAA Services root"
+# Serial: 1
+# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0
+# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49
+# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
+# Label: "COMODO Certification Authority"
+# Serial: 104350513648249232941998508985834464573
+# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75
+# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b
+# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Label: "COMODO ECC Certification Authority"
+# Serial: 41578283867086692638256921589707938090
+# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
+# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
+# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Label: "COMODO RSA Certification Authority"
+# Serial: 101909084537582093308941363524873193117
+# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18
+# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4
+# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Label: "USERTrust ECC Certification Authority"
+# Serial: 123013823720199481456569720443997572134
+# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1
+# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0
+# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+# Operating CA: Sectigo
+# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Label: "USERTrust RSA Certification Authority"
+# Serial: 2645093764781058787591871645665788717
+# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5
+# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e
+# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
diff --git a/samples/resources/rsa_cert.pem b/samples/resources/rsa_cert.pem
new file mode 100644
index 0000000000000000000000000000000000000000..a8f357f2c97432644f35bedf5cad373fbbbe597d
--- /dev/null
+++ b/samples/resources/rsa_cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICsjCCAZoCCQCq0D93IhEzRjANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBBu
+b2RlanNJb3RUZXN0aW5nMB4XDTIwMTAxOTIyMTAyMVoXDTI2MDQxMTIyMTAyMVow
+GzEZMBcGA1UEAwwQbm9kZWpzSW90VGVzdGluZzCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKQ0OS71+Plqm8A7qoEOdoMdxQ8f0qcgOBBUxB12UMRGeOeq
+6iUe4VESAh7D9n39lr/l5NLnaznC/Di3V8/nhBTQs95dYQ6GZdJ3chQ+Y7ouI8aP
+aQQh/4xEyYgbzq2EwqQ0w6thG0VX22F/dM2LsANHjYQacuuFHa3MyIFlLRxvMx9I
+HRwcvgmZioqlv6ym6/STOb5KmCtwGVKr/vN+EBTFN9Ag2xnQEraen54oCGBgSv+O
+BrFwu6q9d3oZt2IhxLeIbcnHUCf7YlfxXC3HK5De3qPfrnR7Q4sTIpphjzcviwZV
+h+2vq3O6guIZcA5V0s+jP0x9NNQPdZH42eUfiXsCAwEAATANBgkqhkiG9w0BAQsF
+AAOCAQEASM0QZKSd0ZAbFfrjioP8ygDXePKoI/efXTX2XpjbygDmwJeZLbt5pRvR
+lcD8W5XWF/+L4UBwn7b081PL2ZYCJpZp+0jr4oFsCvitpi9Fi0/6sgiHPIc4XD2y
+Pek2SFoEcQLX36aD3ScWQR13xfJj14nrovHbvWPKijl7UeQlS1ZFXf3kI3aVBGTp
+fMUIRl84eRg+sWS9sNacArsUJpauMpms+Ms611lMbnP2K+J9KHvT5Sb163VvHj6B
+3AefC/q2BO+h1Lzs3fBYnQiq+GD4qc5nonomHdau94RU/iXcvtEgsWRjlAbMz8Fj
+4f5AoLEzrZ1eIeUH/V48kyVCAjw4wQ==
+-----END CERTIFICATE-----
diff --git a/samples/resources/rsa_private.pem b/samples/resources/rsa_private.pem
new file mode 100644
index 0000000000000000000000000000000000000000..056f65ef93adb974bce000f08b9ca31a0adfc6ca
--- /dev/null
+++ b/samples/resources/rsa_private.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQCkNDku9fj5apvA
+O6qBDnaDHcUPH9KnIDgQVMQddlDERnjnquolHuFREgIew/Z9/Za/5eTS52s5wvw4
+t1fP54QU0LPeXWEOhmXSd3IUPmO6LiPGj2kEIf+MRMmIG86thMKkNMOrYRtFV9th
+f3TNi7ADR42EGnLrhR2tzMiBZS0cbzMfSB0cHL4JmYqKpb+spuv0kzm+SpgrcBlS
+q/7zfhAUxTfQINsZ0BK2np+eKAhgYEr/jgaxcLuqvXd6GbdiIcS3iG3Jx1An+2JX
+8VwtxyuQ3t6j3650e0OLEyKaYY83L4sGVYftr6tzuoLiGXAOVdLPoz9MfTTUD3WR
++NnlH4l7AgMBAAECggEAQgKkglZrsojC+DKERsFzrx4GnB/k5T60iwwoktd/fIgA
+DtHMswOI/LhKleedbeTF93sJ1CcoGd5i2sIJ0RB3Lo7/4AKWA+rPgB54g97Y5H2r
+8CSyyPCJ9O+qPMdA/MyEGtMDXh/5gJTjInzEjeT76zWWlGa1kCzBU58hc7MiwWzl
+mh9toYFdFF5Dhj5/DQ4Ij8E6bXozRZQl9mFdeACxyNDcbFAvDOUNhRJ73zq5iFGN
+nS4j1Iw+RcDN6fISZDnqUK1rrJvv962YwgXi2rfG9JiaDcPati6q8MDKao9aBa5w
+7RC/3825v76bU+K6Z1MEcOFt8I2kaZa93wVfmmI4UQKBgQDVpSDFqRaOzpYtx691
+V/tHn86r4gRXLhlYzZuCc9/R8gyD8zbrDPwELpYFEjyHFyK4ni1FA1oqOLBbOppe
+8lhnxm57QFzuMLlMuwnlximvRUTqBEo/v3BmA/z0AkNwgcWR/mM/2PsIy4nnJmwg
+Mq5aX4NpOtVKJqkiM/vzKbg/hwKBgQDEwd+YRWJaUU9ZYAtdAskqWRCOumU5UMEA
+HwFUWsoqOIoMuMfbcJ6NQdvHyn2ZoFnoIlZjem7FCsAs9Cc13HnpsbsMndMf6hsT
+p19mExeIQ0m/FHpvNk1MWB43WH53bs6OP2nPHsaxkVoRxMCCdnzusWdEOCOBbpQs
+yyd+bwzbbQKBgQCaw7MY3ONlcgvif/v/okt6WC7L3r/MM63S4abcenpRyOj+EQrg
+fRh3IxQz+kD0j3LskFE05DfFzCkc/TfkveQC0QEpsbdgKNWi2v9RfxqlSCWi7Jao
+1VJj5FGypY0bDDcGCmT1VIaNmXx9gRzkujIJb5VvfloSDC2LhGLohHlfMwJ/IpXx
+t9J6d2XTjOJVHQRgWBFP18bsBCctxdetZCaRYtqNaa8RcoFZXXs2JuhxK5AEPcnL
+ZbEfx4McRMqmGdGnnGyhdJZJhlKgb9P78PVqLYmmbPAslV/2NnVG2nOzx0qzBE4h
+S0cdphjmvDjZnhU14L9OZ692jknhwf3z80WR/QKBgDibdXdw6JppPg5W1egpkGav
+Y6yxJp/pP9ZoG0QWcBj0fkXbHgSFOYwEynbtQpBkkWKkbN833SOq+vI64Fwhky5K
+q9l8VOyys3KH3xEyeq8VqrDeCRudWJjcPdvf7ws6L+4qZXYV8boP7EqplnqOFx3J
+O0S+MOfB7EG7WDyK+wxL
+-----END PRIVATE KEY-----
diff --git a/samples/scripts/generate_keys.sh b/samples/scripts/generate_keys.sh
new file mode 100644
index 0000000000000000000000000000000000000000..a112648e403393f874f9699d3ed8ca99762af426
--- /dev/null
+++ b/samples/scripts/generate_keys.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# Copyright 2017 Google Inc.
+#
+# 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.
+
+openssl req -x509 -newkey rsa:2048 -keyout rsa_private.pem -nodes -out \
+    rsa_cert.pem -subj "/CN=unused"
+openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem
+openssl ec -in ec_private.pem -pubout -out ec_public.pem
diff --git a/samples/scripts/iam.js b/samples/scripts/iam.js
new file mode 100644
index 0000000000000000000000000000000000000000..dc3bb7a02fa7f66fc90a38128d3056e59a2389be
--- /dev/null
+++ b/samples/scripts/iam.js
@@ -0,0 +1,75 @@
+// Copyright 2020 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.
+
+/**
+ * This application demonstrates how programatically grant access to the Google
+ * Cloud IoT Core service account on a given PubSub topic.
+ *
+ * For more information, see https://cloud.google.com/iot.
+ */
+
+const setTopicPolicy = async topicName => {
+  // Imports the Google Cloud client library
+  const {PubSub} = require('@google-cloud/pubsub');
+
+  // Instantiates a client
+  const pubsub = new PubSub();
+
+  // References an existing topic, e.g. "my-topic"
+  const topic = pubsub.topic(topicName);
+
+  // The new IAM policy
+  const serviceAccount = 'serviceAccount:cloud-iot@system.gserviceaccount.com';
+
+  let policy = await topic.iam.getPolicy();
+  policy = policy[0] || {};
+
+  policy.bindings || (policy.bindings = []);
+  console.log(JSON.stringify(policy, null, 2));
+
+  let hasRole = false;
+  let binding = {
+    role: 'roles/pubsub.publisher',
+    members: [serviceAccount],
+  };
+
+  policy.bindings.forEach(_binding => {
+    if (_binding.role === binding.role) {
+      binding = _binding;
+      hasRole = true;
+      return false;
+    }
+  });
+
+  if (hasRole) {
+    binding.members || (binding.members = []);
+    if (binding.members.indexOf(serviceAccount) === -1) {
+      binding.members.push(serviceAccount);
+    }
+  } else {
+    policy.bindings.push(binding);
+  }
+
+  // Updates the IAM policy for the topic
+  try {
+    const [updatedPolicy] = await topic.iam.setPolicy(policy);
+    console.log(JSON.stringify(updatedPolicy, null, 2));
+  } catch (err) {
+    console.error('ERROR:', err);
+  }
+};
+
+if (module === require.main) {
+  setTopicPolicy(process.argv[2]);
+}
diff --git a/samples/scripts/package.json b/samples/scripts/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..e652b538be5891018f7eb9417c25fea47d9de876
--- /dev/null
+++ b/samples/scripts/package.json
@@ -0,0 +1,13 @@
+{
+  "name": "nodejs-docs-samples-iot-scripts",
+  "version": "1.0.0",
+  "main": "iam.js",
+  "author": "Google Inc.",
+  "license": "Apache-2.0",
+  "engines": {
+    "node": ">=8.0.0"
+  },
+  "dependencies": {
+    "@google-cloud/pubsub": "^3.0.0"
+  }
+}
diff --git a/samples/test/quickstart.test.js b/samples/test/quickstart.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..90b3516114b91787a072f5d0ccc900c7c69dbbdf
--- /dev/null
+++ b/samples/test/quickstart.test.js
@@ -0,0 +1,28 @@
+// 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
+//
+//     https://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 {assert} = require('chai');
+const {describe, it} = require('mocha');
+const cp = require('child_process');
+
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+
+describe('iot samples', () => {
+  it('should run the quickstart', async () => {
+    const stdout = execSync('node quickstart');
+    assert.match(stdout, /\d resource\(s\) found./);
+  });
+});
diff --git a/smoke-test/.eslintrc.yml b/smoke-test/.eslintrc.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5adab99ca157e8e37221f37cea7535ae1f91fc59
--- /dev/null
+++ b/smoke-test/.eslintrc.yml
@@ -0,0 +1,4 @@
+---
+rules:
+  node/no-unpublished-require: off
+  no-console: off
diff --git a/smoke-test/device_manager_smoke_test.js b/smoke-test/device_manager_smoke_test.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef16ff26ae3835e3e21b1b9d4b5adfc521462cb6
--- /dev/null
+++ b/smoke-test/device_manager_smoke_test.js
@@ -0,0 +1,99 @@
+// Copyright 2019 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
+//
+//     https://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 {describe, it} = require('mocha');
+
+describe('DeviceManagerSmokeTest', () => {
+  if (!process.env.GCLOUD_PROJECT) {
+    throw new Error('Usage: GCLOUD_PROJECT=<project_id> node #{$0}');
+  }
+  const projectId = process.env.GCLOUD_PROJECT;
+
+  it('successfully makes a call to the service using promises', done => {
+    // eslint-disable-next-line node/no-missing-require
+    const iot = require('../src');
+
+    const client = new iot.v1.DeviceManagerClient({
+      // optional auth parameters.
+    });
+
+    // Iterate over all elements.
+    const formattedParent = client.locationPath(projectId, 'us-central1');
+
+    client
+      .listDeviceRegistries({parent: formattedParent})
+      .then(responses => {
+        const resources = responses[0];
+        for (const resource of resources) {
+          console.log(resource);
+        }
+      })
+      .then(done)
+      .catch(done);
+  });
+
+  it('successfully makes a call to the service using callbacks', done => {
+    // eslint-disable-next-line node/no-missing-require
+    const iot = require('../src');
+
+    const client = new iot.v1.DeviceManagerClient({
+      // optional auth parameters.
+    });
+
+    // Or obtain the paged response.
+    const formattedParent = client.locationPath(projectId, 'us-central1');
+
+    const options = {autoPaginate: false};
+    const callback = responses => {
+      // The actual resources in a response.
+      const resources = responses[0];
+      // The next request if the response shows that there are more responses.
+      const nextRequest = responses[1];
+      // The actual response object, if necessary.
+      // const rawResponse = responses[2];
+      for (const resource of resources) {
+        console.log(resource);
+      }
+      if (nextRequest) {
+        // Fetch the next page.
+        return client.listDeviceRegistries(nextRequest, options).then(callback);
+      }
+    };
+    client
+      .listDeviceRegistries({parent: formattedParent}, options)
+      .then(callback)
+      .then(done)
+      .catch(done);
+  });
+
+  it('successfully makes a call to the service using streaming', done => {
+    // eslint-disable-next-line node/no-missing-require
+    const iot = require('../src');
+
+    const client = new iot.v1.DeviceManagerClient({
+      // optional auth parameters.
+    });
+
+    const formattedParent = client.locationPath(projectId, 'us-central1');
+    client
+      .listDeviceRegistriesStream({parent: formattedParent})
+      .on('data', element => {
+        console.log(element);
+      })
+      .on('error', done)
+      .on('end', done);
+  });
+});
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9d70670fc3d6a8e7b90f93dd73826ffeead9255e
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,27 @@
+// Copyright 2020 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by synthtool. **
+// ** https://github.com/googleapis/synthtool **
+// ** All changes to this file may be overwritten. **
+
+import * as v1 from './v1';
+
+const DeviceManagerClient = v1.DeviceManagerClient;
+type DeviceManagerClient = v1.DeviceManagerClient;
+
+export {v1, DeviceManagerClient};
+export default {v1, DeviceManagerClient};
+import * as protos from '../protos/protos';
+export {protos};
diff --git a/src/v1/device_manager_client.ts b/src/v1/device_manager_client.ts
new file mode 100644
index 0000000000000000000000000000000000000000..948db8bca6e448a7df27c10d2fa2c0274e23f36d
--- /dev/null
+++ b/src/v1/device_manager_client.ts
@@ -0,0 +1,2571 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+/* global window */
+import * as gax from 'google-gax';
+import {
+  Callback,
+  CallOptions,
+  Descriptors,
+  ClientOptions,
+  PaginationCallback,
+  GaxCall,
+} from 'google-gax';
+
+import {Transform} from 'stream';
+import {RequestType} from 'google-gax/build/src/apitypes';
+import * as protos from '../../protos/protos';
+import jsonProtos = require('../../protos/protos.json');
+/**
+ * Client JSON configuration object, loaded from
+ * `src/v1/device_manager_client_config.json`.
+ * This file defines retry strategy and timeouts for all API methods in this library.
+ */
+import * as gapicConfig from './device_manager_client_config.json';
+
+const version = require('../../../package.json').version;
+
+/**
+ *  Internet of Things (IoT) service. Securely connect and manage IoT devices.
+ * @class
+ * @memberof v1
+ */
+export class DeviceManagerClient {
+  private _terminated = false;
+  private _opts: ClientOptions;
+  private _providedCustomServicePath: boolean;
+  private _gaxModule: typeof gax | typeof gax.fallback;
+  private _gaxGrpc: gax.GrpcClient | gax.fallback.GrpcClient;
+  private _protos: {};
+  private _defaults: {[method: string]: gax.CallSettings};
+  auth: gax.GoogleAuth;
+  descriptors: Descriptors = {
+    page: {},
+    stream: {},
+    longrunning: {},
+    batching: {},
+  };
+  warn: (code: string, message: string, warnType?: string) => void;
+  innerApiCalls: {[name: string]: Function};
+  pathTemplates: {[name: string]: gax.PathTemplate};
+  deviceManagerStub?: Promise<{[name: string]: Function}>;
+
+  /**
+   * Construct an instance of DeviceManagerClient.
+   *
+   * @param {object} [options] - The configuration object.
+   * The options accepted by the constructor are described in detail
+   * in [this document](https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md#creating-the-client-instance).
+   * The common options are:
+   * @param {object} [options.credentials] - Credentials object.
+   * @param {string} [options.credentials.client_email]
+   * @param {string} [options.credentials.private_key]
+   * @param {string} [options.email] - Account email address. Required when
+   *     using a .pem or .p12 keyFilename.
+   * @param {string} [options.keyFilename] - Full path to the a .json, .pem, or
+   *     .p12 key downloaded from the Google Developers Console. If you provide
+   *     a path to a JSON file, the projectId option below is not necessary.
+   *     NOTE: .pem and .p12 require you to specify options.email as well.
+   * @param {number} [options.port] - The port on which to connect to
+   *     the remote host.
+   * @param {string} [options.projectId] - The project ID from the Google
+   *     Developer's Console, e.g. 'grape-spaceship-123'. We will also check
+   *     the environment variable GCLOUD_PROJECT for your project ID. If your
+   *     app is running in an environment which supports
+   *     {@link https://developers.google.com/identity/protocols/application-default-credentials Application Default Credentials},
+   *     your project ID will be detected automatically.
+   * @param {string} [options.apiEndpoint] - The domain name of the
+   *     API remote host.
+   * @param {gax.ClientConfig} [options.clientConfig] - Client configuration override.
+   *     Follows the structure of {@link gapicConfig}.
+   * @param {boolean | "rest"} [options.fallback] - Use HTTP fallback mode.
+   *     Pass "rest" to use HTTP/1.1 REST API instead of gRPC.
+   *     For more information, please check the
+   *     {@link https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md#http11-rest-api-mode documentation}.
+   */
+  constructor(opts?: ClientOptions) {
+    // Ensure that options include all the required fields.
+    const staticMembers = this.constructor as typeof DeviceManagerClient;
+    const servicePath =
+      opts?.servicePath || opts?.apiEndpoint || staticMembers.servicePath;
+    this._providedCustomServicePath = !!(
+      opts?.servicePath || opts?.apiEndpoint
+    );
+    const port = opts?.port || staticMembers.port;
+    const clientConfig = opts?.clientConfig ?? {};
+    const fallback =
+      opts?.fallback ??
+      (typeof window !== 'undefined' && typeof window?.fetch === 'function');
+    opts = Object.assign({servicePath, port, clientConfig, fallback}, opts);
+
+    // If scopes are unset in options and we're connecting to a non-default endpoint, set scopes just in case.
+    if (servicePath !== staticMembers.servicePath && !('scopes' in opts)) {
+      opts['scopes'] = staticMembers.scopes;
+    }
+
+    // Choose either gRPC or proto-over-HTTP implementation of google-gax.
+    this._gaxModule = opts.fallback ? gax.fallback : gax;
+
+    // Create a `gaxGrpc` object, with any grpc-specific options sent to the client.
+    this._gaxGrpc = new this._gaxModule.GrpcClient(opts);
+
+    // Save options to use in initialize() method.
+    this._opts = opts;
+
+    // Save the auth object to the client, for use by other methods.
+    this.auth = this._gaxGrpc.auth as gax.GoogleAuth;
+
+    // Set useJWTAccessWithScope on the auth object.
+    this.auth.useJWTAccessWithScope = true;
+
+    // Set defaultServicePath on the auth object.
+    this.auth.defaultServicePath = staticMembers.servicePath;
+
+    // Set the default scopes in auth client if needed.
+    if (servicePath === staticMembers.servicePath) {
+      this.auth.defaultScopes = staticMembers.scopes;
+    }
+
+    // Determine the client header string.
+    const clientHeader = [`gax/${this._gaxModule.version}`, `gapic/${version}`];
+    if (typeof process !== 'undefined' && 'versions' in process) {
+      clientHeader.push(`gl-node/${process.versions.node}`);
+    } else {
+      clientHeader.push(`gl-web/${this._gaxModule.version}`);
+    }
+    if (!opts.fallback) {
+      clientHeader.push(`grpc/${this._gaxGrpc.grpcVersion}`);
+    } else if (opts.fallback === 'rest') {
+      clientHeader.push(`rest/${this._gaxGrpc.grpcVersion}`);
+    }
+    if (opts.libName && opts.libVersion) {
+      clientHeader.push(`${opts.libName}/${opts.libVersion}`);
+    }
+    // Load the applicable protos.
+    this._protos = this._gaxGrpc.loadProtoJSON(jsonProtos);
+
+    // This API contains "path templates"; forward-slash-separated
+    // identifiers to uniquely identify resources within the API.
+    // Create useful helper objects for these.
+    this.pathTemplates = {
+      devicePathTemplate: new this._gaxModule.PathTemplate(
+        'projects/{project}/locations/{location}/registries/{registry}/devices/{device}'
+      ),
+      locationPathTemplate: new this._gaxModule.PathTemplate(
+        'projects/{project}/locations/{location}'
+      ),
+      registryPathTemplate: new this._gaxModule.PathTemplate(
+        'projects/{project}/locations/{location}/registries/{registry}'
+      ),
+    };
+
+    // Some of the methods on this service return "paged" results,
+    // (e.g. 50 results at a time, with tokens to get subsequent
+    // pages). Denote the keys used for pagination and results.
+    this.descriptors.page = {
+      listDeviceRegistries: new this._gaxModule.PageDescriptor(
+        'pageToken',
+        'nextPageToken',
+        'deviceRegistries'
+      ),
+      listDevices: new this._gaxModule.PageDescriptor(
+        'pageToken',
+        'nextPageToken',
+        'devices'
+      ),
+    };
+
+    // Put together the default options sent with requests.
+    this._defaults = this._gaxGrpc.constructSettings(
+      'google.cloud.iot.v1.DeviceManager',
+      gapicConfig as gax.ClientConfig,
+      opts.clientConfig || {},
+      {'x-goog-api-client': clientHeader.join(' ')}
+    );
+
+    // Set up a dictionary of "inner API calls"; the core implementation
+    // of calling the API is handled in `google-gax`, with this code
+    // merely providing the destination and request information.
+    this.innerApiCalls = {};
+
+    // Add a warn function to the client constructor so it can be easily tested.
+    this.warn = gax.warn;
+  }
+
+  /**
+   * Initialize the client.
+   * Performs asynchronous operations (such as authentication) and prepares the client.
+   * This function will be called automatically when any class method is called for the
+   * first time, but if you need to initialize it before calling an actual method,
+   * feel free to call initialize() directly.
+   *
+   * You can await on this method if you want to make sure the client is initialized.
+   *
+   * @returns {Promise} A promise that resolves to an authenticated service stub.
+   */
+  initialize() {
+    // If the client stub promise is already initialized, return immediately.
+    if (this.deviceManagerStub) {
+      return this.deviceManagerStub;
+    }
+
+    // Put together the "service stub" for
+    // google.cloud.iot.v1.DeviceManager.
+    this.deviceManagerStub = this._gaxGrpc.createStub(
+      this._opts.fallback
+        ? (this._protos as protobuf.Root).lookupService(
+            'google.cloud.iot.v1.DeviceManager'
+          )
+        : // eslint-disable-next-line @typescript-eslint/no-explicit-any
+          (this._protos as any).google.cloud.iot.v1.DeviceManager,
+      this._opts,
+      this._providedCustomServicePath
+    ) as Promise<{[method: string]: Function}>;
+
+    // Iterate over each of the methods that the service provides
+    // and create an API call method for each.
+    const deviceManagerStubMethods = [
+      'createDeviceRegistry',
+      'getDeviceRegistry',
+      'updateDeviceRegistry',
+      'deleteDeviceRegistry',
+      'listDeviceRegistries',
+      'createDevice',
+      'getDevice',
+      'updateDevice',
+      'deleteDevice',
+      'listDevices',
+      'modifyCloudToDeviceConfig',
+      'listDeviceConfigVersions',
+      'listDeviceStates',
+      'setIamPolicy',
+      'getIamPolicy',
+      'testIamPermissions',
+      'sendCommandToDevice',
+      'bindDeviceToGateway',
+      'unbindDeviceFromGateway',
+    ];
+    for (const methodName of deviceManagerStubMethods) {
+      const callPromise = this.deviceManagerStub.then(
+        stub =>
+          (...args: Array<{}>) => {
+            if (this._terminated) {
+              return Promise.reject('The client has already been closed.');
+            }
+            const func = stub[methodName];
+            return func.apply(stub, args);
+          },
+        (err: Error | null | undefined) => () => {
+          throw err;
+        }
+      );
+
+      const descriptor = this.descriptors.page[methodName] || undefined;
+      const apiCall = this._gaxModule.createApiCall(
+        callPromise,
+        this._defaults[methodName],
+        descriptor
+      );
+
+      this.innerApiCalls[methodName] = apiCall;
+    }
+
+    return this.deviceManagerStub;
+  }
+
+  /**
+   * The DNS address for this API service.
+   * @returns {string} The DNS address for this service.
+   */
+  static get servicePath() {
+    return 'cloudiot.googleapis.com';
+  }
+
+  /**
+   * The DNS address for this API service - same as servicePath(),
+   * exists for compatibility reasons.
+   * @returns {string} The DNS address for this service.
+   */
+  static get apiEndpoint() {
+    return 'cloudiot.googleapis.com';
+  }
+
+  /**
+   * The port for this API service.
+   * @returns {number} The default port for this service.
+   */
+  static get port() {
+    return 443;
+  }
+
+  /**
+   * The scopes needed to make gRPC calls for every method defined
+   * in this service.
+   * @returns {string[]} List of default scopes.
+   */
+  static get scopes() {
+    return [
+      'https://www.googleapis.com/auth/cloud-platform',
+      'https://www.googleapis.com/auth/cloudiot',
+    ];
+  }
+
+  getProjectId(): Promise<string>;
+  getProjectId(callback: Callback<string, undefined, undefined>): void;
+  /**
+   * Return the project ID used by this class.
+   * @returns {Promise} A promise that resolves to string containing the project ID.
+   */
+  getProjectId(
+    callback?: Callback<string, undefined, undefined>
+  ): Promise<string> | void {
+    if (callback) {
+      this.auth.getProjectId(callback);
+      return;
+    }
+    return this.auth.getProjectId();
+  }
+
+  // -------------------
+  // -- Service calls --
+  // -------------------
+  /**
+   * Creates a device registry that contains devices.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The project and cloud region where this device registry must be created.
+   *   For example, `projects/example-project/locations/us-central1`.
+   * @param {google.cloud.iot.v1.DeviceRegistry} request.deviceRegistry
+   *   Required. The device registry. The field `name` must be empty. The server will
+   *   generate that field from the device registry `id` provided and the
+   *   `parent` field.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [DeviceRegistry]{@link google.cloud.iot.v1.DeviceRegistry}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.create_device_registry.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_CreateDeviceRegistry_async
+   */
+  createDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  createDeviceRegistry(
+    request: protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      | protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  createDeviceRegistry(
+    request: protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      | protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  createDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IDeviceRegistry,
+          | protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      | protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.ICreateDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.createDeviceRegistry(request, options, callback);
+  }
+  /**
+   * Gets a device registry configuration.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device registry. For example,
+   *   `projects/example-project/locations/us-central1/registries/my-registry`.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [DeviceRegistry]{@link google.cloud.iot.v1.DeviceRegistry}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.get_device_registry.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_GetDeviceRegistry_async
+   */
+  getDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.IGetDeviceRegistryRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.IGetDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  getDeviceRegistry(
+    request: protos.google.cloud.iot.v1.IGetDeviceRegistryRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.IGetDeviceRegistryRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  getDeviceRegistry(
+    request: protos.google.cloud.iot.v1.IGetDeviceRegistryRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.IGetDeviceRegistryRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  getDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.IGetDeviceRegistryRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IDeviceRegistry,
+          | protos.google.cloud.iot.v1.IGetDeviceRegistryRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.IGetDeviceRegistryRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.IGetDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.getDeviceRegistry(request, options, callback);
+  }
+  /**
+   * Updates a device registry configuration.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {google.cloud.iot.v1.DeviceRegistry} request.deviceRegistry
+   *   Required. The new values for the device registry. The `id` field must be empty, and
+   *   the `name` field must indicate the path of the resource. For example,
+   *   `projects/example-project/locations/us-central1/registries/my-registry`.
+   * @param {google.protobuf.FieldMask} request.updateMask
+   *   Required. Only updates the `device_registry` fields indicated by this mask.
+   *   The field mask must not be empty, and it must not contain fields that
+   *   are immutable or only set by the server.
+   *   Mutable top-level fields: `event_notification_config`, `http_config`,
+   *   `mqtt_config`, and `state_notification_config`.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [DeviceRegistry]{@link google.cloud.iot.v1.DeviceRegistry}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.update_device_registry.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_UpdateDeviceRegistry_async
+   */
+  updateDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  updateDeviceRegistry(
+    request: protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      | protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  updateDeviceRegistry(
+    request: protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      | protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  updateDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IDeviceRegistry,
+          | protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      | protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry,
+      protos.google.cloud.iot.v1.IUpdateDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        'device_registry.name': request.deviceRegistry!.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.updateDeviceRegistry(request, options, callback);
+  }
+  /**
+   * Deletes a device registry configuration.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device registry. For example,
+   *   `projects/example-project/locations/us-central1/registries/my-registry`.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [Empty]{@link google.protobuf.Empty}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.delete_device_registry.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_DeleteDeviceRegistry_async
+   */
+  deleteDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.protobuf.IEmpty,
+      protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  deleteDeviceRegistry(
+    request: protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.protobuf.IEmpty,
+      | protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  deleteDeviceRegistry(
+    request: protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest,
+    callback: Callback<
+      protos.google.protobuf.IEmpty,
+      | protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  deleteDeviceRegistry(
+    request?: protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.protobuf.IEmpty,
+          | protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.protobuf.IEmpty,
+      | protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.protobuf.IEmpty,
+      protos.google.cloud.iot.v1.IDeleteDeviceRegistryRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.deleteDeviceRegistry(request, options, callback);
+  }
+  /**
+   * Creates a device in a device registry.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The name of the device registry where this device should be created.
+   *   For example,
+   *   `projects/example-project/locations/us-central1/registries/my-registry`.
+   * @param {google.cloud.iot.v1.Device} request.device
+   *   Required. The device registration details. The field `name` must be empty. The server
+   *   generates `name` from the device registry `id` and the
+   *   `parent` field.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [Device]{@link google.cloud.iot.v1.Device}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.create_device.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_CreateDevice_async
+   */
+  createDevice(
+    request?: protos.google.cloud.iot.v1.ICreateDeviceRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.ICreateDeviceRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  createDevice(
+    request: protos.google.cloud.iot.v1.ICreateDeviceRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.ICreateDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  createDevice(
+    request: protos.google.cloud.iot.v1.ICreateDeviceRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.ICreateDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  createDevice(
+    request?: protos.google.cloud.iot.v1.ICreateDeviceRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IDevice,
+          protos.google.cloud.iot.v1.ICreateDeviceRequest | null | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.ICreateDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.ICreateDeviceRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.createDevice(request, options, callback);
+  }
+  /**
+   * Gets details about a device.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device. For example,
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   * @param {google.protobuf.FieldMask} request.fieldMask
+   *   The fields of the `Device` resource to be returned in the response. If the
+   *   field mask is unset or empty, all fields are returned. Fields have to be
+   *   provided in snake_case format, for example: `last_heartbeat_time`.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [Device]{@link google.cloud.iot.v1.Device}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.get_device.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_GetDevice_async
+   */
+  getDevice(
+    request?: protos.google.cloud.iot.v1.IGetDeviceRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IGetDeviceRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  getDevice(
+    request: protos.google.cloud.iot.v1.IGetDeviceRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IGetDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  getDevice(
+    request: protos.google.cloud.iot.v1.IGetDeviceRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IGetDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  getDevice(
+    request?: protos.google.cloud.iot.v1.IGetDeviceRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IDevice,
+          protos.google.cloud.iot.v1.IGetDeviceRequest | null | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IGetDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IGetDeviceRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.getDevice(request, options, callback);
+  }
+  /**
+   * Updates a device.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {google.cloud.iot.v1.Device} request.device
+   *   Required. The new values for the device. The `id` and `num_id` fields must
+   *   be empty, and the field `name` must specify the name path. For example,
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/device0`or
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   * @param {google.protobuf.FieldMask} request.updateMask
+   *   Required. Only updates the `device` fields indicated by this mask.
+   *   The field mask must not be empty, and it must not contain fields that
+   *   are immutable or only set by the server.
+   *   Mutable top-level fields: `credentials`, `blocked`, and `metadata`
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [Device]{@link google.cloud.iot.v1.Device}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.update_device.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_UpdateDevice_async
+   */
+  updateDevice(
+    request?: protos.google.cloud.iot.v1.IUpdateDeviceRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IUpdateDeviceRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  updateDevice(
+    request: protos.google.cloud.iot.v1.IUpdateDeviceRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IUpdateDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  updateDevice(
+    request: protos.google.cloud.iot.v1.IUpdateDeviceRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IUpdateDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  updateDevice(
+    request?: protos.google.cloud.iot.v1.IUpdateDeviceRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IDevice,
+          protos.google.cloud.iot.v1.IUpdateDeviceRequest | null | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IUpdateDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice,
+      protos.google.cloud.iot.v1.IUpdateDeviceRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        'device.name': request.device!.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.updateDevice(request, options, callback);
+  }
+  /**
+   * Deletes a device.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device. For example,
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [Empty]{@link google.protobuf.Empty}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.delete_device.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_DeleteDevice_async
+   */
+  deleteDevice(
+    request?: protos.google.cloud.iot.v1.IDeleteDeviceRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.protobuf.IEmpty,
+      protos.google.cloud.iot.v1.IDeleteDeviceRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  deleteDevice(
+    request: protos.google.cloud.iot.v1.IDeleteDeviceRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.protobuf.IEmpty,
+      protos.google.cloud.iot.v1.IDeleteDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  deleteDevice(
+    request: protos.google.cloud.iot.v1.IDeleteDeviceRequest,
+    callback: Callback<
+      protos.google.protobuf.IEmpty,
+      protos.google.cloud.iot.v1.IDeleteDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  deleteDevice(
+    request?: protos.google.cloud.iot.v1.IDeleteDeviceRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.protobuf.IEmpty,
+          protos.google.cloud.iot.v1.IDeleteDeviceRequest | null | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.protobuf.IEmpty,
+      protos.google.cloud.iot.v1.IDeleteDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.protobuf.IEmpty,
+      protos.google.cloud.iot.v1.IDeleteDeviceRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.deleteDevice(request, options, callback);
+  }
+  /**
+   * Modifies the configuration for the device, which is eventually sent from
+   * the Cloud IoT Core servers. Returns the modified configuration version and
+   * its metadata.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device. For example,
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   * @param {number} request.versionToUpdate
+   *   The version number to update. If this value is zero, it will not check the
+   *   version number of the server and will always update the current version;
+   *   otherwise, this update will fail if the version number found on the server
+   *   does not match this version number. This is used to support multiple
+   *   simultaneous updates without losing data.
+   * @param {Buffer} request.binaryData
+   *   Required. The configuration data for the device.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [DeviceConfig]{@link google.cloud.iot.v1.DeviceConfig}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.modify_cloud_to_device_config.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_ModifyCloudToDeviceConfig_async
+   */
+  modifyCloudToDeviceConfig(
+    request?: protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceConfig,
+      protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  modifyCloudToDeviceConfig(
+    request: protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceConfig,
+      | protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  modifyCloudToDeviceConfig(
+    request: protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IDeviceConfig,
+      | protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  modifyCloudToDeviceConfig(
+    request?: protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IDeviceConfig,
+          | protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IDeviceConfig,
+      | protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceConfig,
+      protos.google.cloud.iot.v1.IModifyCloudToDeviceConfigRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.modifyCloudToDeviceConfig(
+      request,
+      options,
+      callback
+    );
+  }
+  /**
+   * Lists the last few versions of the device configuration in descending
+   * order (i.e.: newest first).
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device. For example,
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   * @param {number} request.numVersions
+   *   The number of versions to list. Versions are listed in decreasing order of
+   *   the version number. The maximum number of versions retained is 10. If this
+   *   value is zero, it will return all the versions available.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [ListDeviceConfigVersionsResponse]{@link google.cloud.iot.v1.ListDeviceConfigVersionsResponse}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.list_device_config_versions.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_ListDeviceConfigVersions_async
+   */
+  listDeviceConfigVersions(
+    request?: protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IListDeviceConfigVersionsResponse,
+      protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  listDeviceConfigVersions(
+    request: protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IListDeviceConfigVersionsResponse,
+      | protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  listDeviceConfigVersions(
+    request: protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IListDeviceConfigVersionsResponse,
+      | protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  listDeviceConfigVersions(
+    request?: protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IListDeviceConfigVersionsResponse,
+          | protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IListDeviceConfigVersionsResponse,
+      | protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IListDeviceConfigVersionsResponse,
+      protos.google.cloud.iot.v1.IListDeviceConfigVersionsRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.listDeviceConfigVersions(
+      request,
+      options,
+      callback
+    );
+  }
+  /**
+   * Lists the last few versions of the device state in descending order (i.e.:
+   * newest first).
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device. For example,
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   * @param {number} request.numStates
+   *   The number of states to list. States are listed in descending order of
+   *   update time. The maximum number of states retained is 10. If this
+   *   value is zero, it will return all the states available.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [ListDeviceStatesResponse]{@link google.cloud.iot.v1.ListDeviceStatesResponse}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.list_device_states.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_ListDeviceStates_async
+   */
+  listDeviceStates(
+    request?: protos.google.cloud.iot.v1.IListDeviceStatesRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IListDeviceStatesResponse,
+      protos.google.cloud.iot.v1.IListDeviceStatesRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  listDeviceStates(
+    request: protos.google.cloud.iot.v1.IListDeviceStatesRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IListDeviceStatesResponse,
+      protos.google.cloud.iot.v1.IListDeviceStatesRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  listDeviceStates(
+    request: protos.google.cloud.iot.v1.IListDeviceStatesRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IListDeviceStatesResponse,
+      protos.google.cloud.iot.v1.IListDeviceStatesRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  listDeviceStates(
+    request?: protos.google.cloud.iot.v1.IListDeviceStatesRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IListDeviceStatesResponse,
+          | protos.google.cloud.iot.v1.IListDeviceStatesRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IListDeviceStatesResponse,
+      protos.google.cloud.iot.v1.IListDeviceStatesRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IListDeviceStatesResponse,
+      protos.google.cloud.iot.v1.IListDeviceStatesRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.listDeviceStates(request, options, callback);
+  }
+  /**
+   * Sets the access control policy on the specified resource. Replaces any
+   * existing policy.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.resource
+   *   REQUIRED: The resource for which the policy is being specified.
+   *   See the operation documentation for the appropriate value for this field.
+   * @param {google.iam.v1.Policy} request.policy
+   *   REQUIRED: The complete policy to be applied to the `resource`. The size of
+   *   the policy is limited to a few 10s of KB. An empty policy is a
+   *   valid policy but certain Cloud Platform services (such as Projects)
+   *   might reject them.
+   * @param {google.protobuf.FieldMask} request.updateMask
+   *   OPTIONAL: A FieldMask specifying which fields of the policy to modify. Only
+   *   the fields in the mask will be modified. If no mask is provided, the
+   *   following default mask is used:
+   *
+   *   `paths: "bindings, etag"`
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [Policy]{@link google.iam.v1.Policy}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.set_iam_policy.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_SetIamPolicy_async
+   */
+  setIamPolicy(
+    request?: protos.google.iam.v1.ISetIamPolicyRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.ISetIamPolicyRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  setIamPolicy(
+    request: protos.google.iam.v1.ISetIamPolicyRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.ISetIamPolicyRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  setIamPolicy(
+    request: protos.google.iam.v1.ISetIamPolicyRequest,
+    callback: Callback<
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.ISetIamPolicyRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  setIamPolicy(
+    request?: protos.google.iam.v1.ISetIamPolicyRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.iam.v1.IPolicy,
+          protos.google.iam.v1.ISetIamPolicyRequest | null | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.ISetIamPolicyRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.ISetIamPolicyRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        resource: request.resource || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.setIamPolicy(request, options, callback);
+  }
+  /**
+   * Gets the access control policy for a resource.
+   * Returns an empty policy if the resource exists and does not have a policy
+   * set.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.resource
+   *   REQUIRED: The resource for which the policy is being requested.
+   *   See the operation documentation for the appropriate value for this field.
+   * @param {google.iam.v1.GetPolicyOptions} request.options
+   *   OPTIONAL: A `GetPolicyOptions` object for specifying options to
+   *   `GetIamPolicy`.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [Policy]{@link google.iam.v1.Policy}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.get_iam_policy.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_GetIamPolicy_async
+   */
+  getIamPolicy(
+    request?: protos.google.iam.v1.IGetIamPolicyRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.IGetIamPolicyRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  getIamPolicy(
+    request: protos.google.iam.v1.IGetIamPolicyRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.IGetIamPolicyRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  getIamPolicy(
+    request: protos.google.iam.v1.IGetIamPolicyRequest,
+    callback: Callback<
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.IGetIamPolicyRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  getIamPolicy(
+    request?: protos.google.iam.v1.IGetIamPolicyRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.iam.v1.IPolicy,
+          protos.google.iam.v1.IGetIamPolicyRequest | null | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.IGetIamPolicyRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.iam.v1.IPolicy,
+      protos.google.iam.v1.IGetIamPolicyRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        resource: request.resource || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.getIamPolicy(request, options, callback);
+  }
+  /**
+   * Returns permissions that a caller has on the specified resource.
+   * If the resource does not exist, this will return an empty set of
+   * permissions, not a NOT_FOUND error.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.resource
+   *   REQUIRED: The resource for which the policy detail is being requested.
+   *   See the operation documentation for the appropriate value for this field.
+   * @param {string[]} request.permissions
+   *   The set of permissions to check for the `resource`. Permissions with
+   *   wildcards (such as '*' or 'storage.*') are not allowed. For more
+   *   information see
+   *   [IAM Overview](https://cloud.google.com/iam/docs/overview#permissions).
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [TestIamPermissionsResponse]{@link google.iam.v1.TestIamPermissionsResponse}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.test_iam_permissions.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_TestIamPermissions_async
+   */
+  testIamPermissions(
+    request?: protos.google.iam.v1.ITestIamPermissionsRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.iam.v1.ITestIamPermissionsResponse,
+      protos.google.iam.v1.ITestIamPermissionsRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  testIamPermissions(
+    request: protos.google.iam.v1.ITestIamPermissionsRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.iam.v1.ITestIamPermissionsResponse,
+      protos.google.iam.v1.ITestIamPermissionsRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  testIamPermissions(
+    request: protos.google.iam.v1.ITestIamPermissionsRequest,
+    callback: Callback<
+      protos.google.iam.v1.ITestIamPermissionsResponse,
+      protos.google.iam.v1.ITestIamPermissionsRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  testIamPermissions(
+    request?: protos.google.iam.v1.ITestIamPermissionsRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.iam.v1.ITestIamPermissionsResponse,
+          protos.google.iam.v1.ITestIamPermissionsRequest | null | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.iam.v1.ITestIamPermissionsResponse,
+      protos.google.iam.v1.ITestIamPermissionsRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.iam.v1.ITestIamPermissionsResponse,
+      protos.google.iam.v1.ITestIamPermissionsRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        resource: request.resource || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.testIamPermissions(request, options, callback);
+  }
+  /**
+   * Sends a command to the specified device. In order for a device to be able
+   * to receive commands, it must:
+   * 1) be connected to Cloud IoT Core using the MQTT protocol, and
+   * 2) be subscribed to the group of MQTT topics specified by
+   *    /devices/{device-id}/commands/#. This subscription will receive commands
+   *    at the top-level topic /devices/{device-id}/commands as well as commands
+   *    for subfolders, like /devices/{device-id}/commands/subfolder.
+   *    Note that subscribing to specific subfolders is not supported.
+   * If the command could not be delivered to the device, this method will
+   * return an error; in particular, if the device is not subscribed, this
+   * method will return FAILED_PRECONDITION. Otherwise, this method will
+   * return OK. If the subscription is QoS 1, at least once delivery will be
+   * guaranteed; for QoS 0, no acknowledgment will be expected from the device.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.name
+   *   Required. The name of the device. For example,
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/device0` or
+   *   `projects/p0/locations/us-central1/registries/registry0/devices/{num_id}`.
+   * @param {Buffer} request.binaryData
+   *   Required. The command data to send to the device.
+   * @param {string} request.subfolder
+   *   Optional subfolder for the command. If empty, the command will be delivered
+   *   to the /devices/{device-id}/commands topic, otherwise it will be delivered
+   *   to the /devices/{device-id}/commands/{subfolder} topic. Multi-level
+   *   subfolders are allowed. This field must not have more than 256 characters,
+   *   and must not contain any MQTT wildcards ("+" or "#") or null characters.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [SendCommandToDeviceResponse]{@link google.cloud.iot.v1.SendCommandToDeviceResponse}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.send_command_to_device.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_SendCommandToDevice_async
+   */
+  sendCommandToDevice(
+    request?: protos.google.cloud.iot.v1.ISendCommandToDeviceRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.ISendCommandToDeviceResponse,
+      protos.google.cloud.iot.v1.ISendCommandToDeviceRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  sendCommandToDevice(
+    request: protos.google.cloud.iot.v1.ISendCommandToDeviceRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.ISendCommandToDeviceResponse,
+      protos.google.cloud.iot.v1.ISendCommandToDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  sendCommandToDevice(
+    request: protos.google.cloud.iot.v1.ISendCommandToDeviceRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.ISendCommandToDeviceResponse,
+      protos.google.cloud.iot.v1.ISendCommandToDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  sendCommandToDevice(
+    request?: protos.google.cloud.iot.v1.ISendCommandToDeviceRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.ISendCommandToDeviceResponse,
+          | protos.google.cloud.iot.v1.ISendCommandToDeviceRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.ISendCommandToDeviceResponse,
+      protos.google.cloud.iot.v1.ISendCommandToDeviceRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.ISendCommandToDeviceResponse,
+      protos.google.cloud.iot.v1.ISendCommandToDeviceRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        name: request.name || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.sendCommandToDevice(request, options, callback);
+  }
+  /**
+   * Associates the device with the gateway.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The name of the registry. For example,
+   *   `projects/example-project/locations/us-central1/registries/my-registry`.
+   * @param {string} request.gatewayId
+   *   Required. The value of `gateway_id` can be either the device numeric ID or the
+   *   user-defined device identifier.
+   * @param {string} request.deviceId
+   *   Required. The device to associate with the specified gateway. The value of
+   *   `device_id` can be either the device numeric ID or the user-defined device
+   *   identifier.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [BindDeviceToGatewayResponse]{@link google.cloud.iot.v1.BindDeviceToGatewayResponse}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.bind_device_to_gateway.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_BindDeviceToGateway_async
+   */
+  bindDeviceToGateway(
+    request?: protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayResponse,
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  bindDeviceToGateway(
+    request: protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayResponse,
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  bindDeviceToGateway(
+    request: protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayResponse,
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  bindDeviceToGateway(
+    request?: protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IBindDeviceToGatewayResponse,
+          | protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayResponse,
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest | null | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayResponse,
+      protos.google.cloud.iot.v1.IBindDeviceToGatewayRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.bindDeviceToGateway(request, options, callback);
+  }
+  /**
+   * Deletes the association between the device and the gateway.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The name of the registry. For example,
+   *   `projects/example-project/locations/us-central1/registries/my-registry`.
+   * @param {string} request.gatewayId
+   *   Required. The value of `gateway_id` can be either the device numeric ID or the
+   *   user-defined device identifier.
+   * @param {string} request.deviceId
+   *   Required. The device to disassociate from the specified gateway. The value of
+   *   `device_id` can be either the device numeric ID or the user-defined device
+   *   identifier.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is an object representing [UnbindDeviceFromGatewayResponse]{@link google.cloud.iot.v1.UnbindDeviceFromGatewayResponse}.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#regular-methods)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.unbind_device_from_gateway.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_UnbindDeviceFromGateway_async
+   */
+  unbindDeviceFromGateway(
+    request?: protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse,
+      protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest | undefined,
+      {} | undefined
+    ]
+  >;
+  unbindDeviceFromGateway(
+    request: protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest,
+    options: CallOptions,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse,
+      | protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  unbindDeviceFromGateway(
+    request: protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest,
+    callback: Callback<
+      protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse,
+      | protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): void;
+  unbindDeviceFromGateway(
+    request?: protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | Callback<
+          protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse,
+          | protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest
+          | null
+          | undefined,
+          {} | null | undefined
+        >,
+    callback?: Callback<
+      protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse,
+      | protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest
+      | null
+      | undefined,
+      {} | null | undefined
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse,
+      protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayRequest | undefined,
+      {} | undefined
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.unbindDeviceFromGateway(
+      request,
+      options,
+      callback
+    );
+  }
+
+  /**
+   * Lists device registries.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The project and cloud region path. For example,
+   *   `projects/example-project/locations/us-central1`.
+   * @param {number} request.pageSize
+   *   The maximum number of registries to return in the response. If this value
+   *   is zero, the service will select a default size. A call may return fewer
+   *   objects than requested. A non-empty `next_page_token` in the response
+   *   indicates that more data is available.
+   * @param {string} request.pageToken
+   *   The value returned by the last `ListDeviceRegistriesResponse`; indicates
+   *   that this is a continuation of a prior `ListDeviceRegistries` call and
+   *   the system should return the next page of data.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is Array of [DeviceRegistry]{@link google.cloud.iot.v1.DeviceRegistry}.
+   *   The client library will perform auto-pagination by default: it will call the API as many
+   *   times as needed and will merge results from all the pages into this array.
+   *   Note that it can affect your quota.
+   *   We recommend using `listDeviceRegistriesAsync()`
+   *   method described below for async iteration which you can stop as needed.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
+   *   for more details and examples.
+   */
+  listDeviceRegistries(
+    request?: protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry[],
+      protos.google.cloud.iot.v1.IListDeviceRegistriesRequest | null,
+      protos.google.cloud.iot.v1.IListDeviceRegistriesResponse
+    ]
+  >;
+  listDeviceRegistries(
+    request: protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+    options: CallOptions,
+    callback: PaginationCallback<
+      protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+      | protos.google.cloud.iot.v1.IListDeviceRegistriesResponse
+      | null
+      | undefined,
+      protos.google.cloud.iot.v1.IDeviceRegistry
+    >
+  ): void;
+  listDeviceRegistries(
+    request: protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+    callback: PaginationCallback<
+      protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+      | protos.google.cloud.iot.v1.IListDeviceRegistriesResponse
+      | null
+      | undefined,
+      protos.google.cloud.iot.v1.IDeviceRegistry
+    >
+  ): void;
+  listDeviceRegistries(
+    request?: protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | PaginationCallback<
+          protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+          | protos.google.cloud.iot.v1.IListDeviceRegistriesResponse
+          | null
+          | undefined,
+          protos.google.cloud.iot.v1.IDeviceRegistry
+        >,
+    callback?: PaginationCallback<
+      protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+      | protos.google.cloud.iot.v1.IListDeviceRegistriesResponse
+      | null
+      | undefined,
+      protos.google.cloud.iot.v1.IDeviceRegistry
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDeviceRegistry[],
+      protos.google.cloud.iot.v1.IListDeviceRegistriesRequest | null,
+      protos.google.cloud.iot.v1.IListDeviceRegistriesResponse
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.listDeviceRegistries(request, options, callback);
+  }
+
+  /**
+   * Equivalent to `method.name.toCamelCase()`, but returns a NodeJS Stream object.
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The project and cloud region path. For example,
+   *   `projects/example-project/locations/us-central1`.
+   * @param {number} request.pageSize
+   *   The maximum number of registries to return in the response. If this value
+   *   is zero, the service will select a default size. A call may return fewer
+   *   objects than requested. A non-empty `next_page_token` in the response
+   *   indicates that more data is available.
+   * @param {string} request.pageToken
+   *   The value returned by the last `ListDeviceRegistriesResponse`; indicates
+   *   that this is a continuation of a prior `ListDeviceRegistries` call and
+   *   the system should return the next page of data.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Stream}
+   *   An object stream which emits an object representing [DeviceRegistry]{@link google.cloud.iot.v1.DeviceRegistry} on 'data' event.
+   *   The client library will perform auto-pagination by default: it will call the API as many
+   *   times as needed. Note that it can affect your quota.
+   *   We recommend using `listDeviceRegistriesAsync()`
+   *   method described below for async iteration which you can stop as needed.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
+   *   for more details and examples.
+   */
+  listDeviceRegistriesStream(
+    request?: protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+    options?: CallOptions
+  ): Transform {
+    request = request || {};
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    const defaultCallSettings = this._defaults['listDeviceRegistries'];
+    const callSettings = defaultCallSettings.merge(options);
+    this.initialize();
+    return this.descriptors.page.listDeviceRegistries.createStream(
+      this.innerApiCalls.listDeviceRegistries as gax.GaxCall,
+      request,
+      callSettings
+    );
+  }
+
+  /**
+   * Equivalent to `listDeviceRegistries`, but returns an iterable object.
+   *
+   * `for`-`await`-`of` syntax is used with the iterable to get response elements on-demand.
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The project and cloud region path. For example,
+   *   `projects/example-project/locations/us-central1`.
+   * @param {number} request.pageSize
+   *   The maximum number of registries to return in the response. If this value
+   *   is zero, the service will select a default size. A call may return fewer
+   *   objects than requested. A non-empty `next_page_token` in the response
+   *   indicates that more data is available.
+   * @param {string} request.pageToken
+   *   The value returned by the last `ListDeviceRegistriesResponse`; indicates
+   *   that this is a continuation of a prior `ListDeviceRegistries` call and
+   *   the system should return the next page of data.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Object}
+   *   An iterable Object that allows [async iteration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).
+   *   When you iterate the returned iterable, each element will be an object representing
+   *   [DeviceRegistry]{@link google.cloud.iot.v1.DeviceRegistry}. The API will be called under the hood as needed, once per the page,
+   *   so you can stop the iteration when you don't need more results.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.list_device_registries.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_ListDeviceRegistries_async
+   */
+  listDeviceRegistriesAsync(
+    request?: protos.google.cloud.iot.v1.IListDeviceRegistriesRequest,
+    options?: CallOptions
+  ): AsyncIterable<protos.google.cloud.iot.v1.IDeviceRegistry> {
+    request = request || {};
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    const defaultCallSettings = this._defaults['listDeviceRegistries'];
+    const callSettings = defaultCallSettings.merge(options);
+    this.initialize();
+    return this.descriptors.page.listDeviceRegistries.asyncIterate(
+      this.innerApiCalls['listDeviceRegistries'] as GaxCall,
+      request as unknown as RequestType,
+      callSettings
+    ) as AsyncIterable<protos.google.cloud.iot.v1.IDeviceRegistry>;
+  }
+  /**
+   * List devices in a device registry.
+   *
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The device registry path. Required. For example,
+   *   `projects/my-project/locations/us-central1/registries/my-registry`.
+   * @param {number[]} request.deviceNumIds
+   *   A list of device numeric IDs. If empty, this field is ignored. Maximum
+   *   IDs: 10,000.
+   * @param {string[]} request.deviceIds
+   *   A list of device string IDs. For example, `['device0', 'device12']`.
+   *   If empty, this field is ignored. Maximum IDs: 10,000
+   * @param {google.protobuf.FieldMask} request.fieldMask
+   *   The fields of the `Device` resource to be returned in the response. The
+   *   fields `id` and `num_id` are always returned, along with any
+   *   other fields specified in snake_case format, for example:
+   *   `last_heartbeat_time`.
+   * @param {google.cloud.iot.v1.GatewayListOptions} request.gatewayListOptions
+   *   Options related to gateways.
+   * @param {number} request.pageSize
+   *   The maximum number of devices to return in the response. If this value
+   *   is zero, the service will select a default size. A call may return fewer
+   *   objects than requested. A non-empty `next_page_token` in the response
+   *   indicates that more data is available.
+   * @param {string} request.pageToken
+   *   The value returned by the last `ListDevicesResponse`; indicates
+   *   that this is a continuation of a prior `ListDevices` call and
+   *   the system should return the next page of data.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Promise} - The promise which resolves to an array.
+   *   The first element of the array is Array of [Device]{@link google.cloud.iot.v1.Device}.
+   *   The client library will perform auto-pagination by default: it will call the API as many
+   *   times as needed and will merge results from all the pages into this array.
+   *   Note that it can affect your quota.
+   *   We recommend using `listDevicesAsync()`
+   *   method described below for async iteration which you can stop as needed.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
+   *   for more details and examples.
+   */
+  listDevices(
+    request?: protos.google.cloud.iot.v1.IListDevicesRequest,
+    options?: CallOptions
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice[],
+      protos.google.cloud.iot.v1.IListDevicesRequest | null,
+      protos.google.cloud.iot.v1.IListDevicesResponse
+    ]
+  >;
+  listDevices(
+    request: protos.google.cloud.iot.v1.IListDevicesRequest,
+    options: CallOptions,
+    callback: PaginationCallback<
+      protos.google.cloud.iot.v1.IListDevicesRequest,
+      protos.google.cloud.iot.v1.IListDevicesResponse | null | undefined,
+      protos.google.cloud.iot.v1.IDevice
+    >
+  ): void;
+  listDevices(
+    request: protos.google.cloud.iot.v1.IListDevicesRequest,
+    callback: PaginationCallback<
+      protos.google.cloud.iot.v1.IListDevicesRequest,
+      protos.google.cloud.iot.v1.IListDevicesResponse | null | undefined,
+      protos.google.cloud.iot.v1.IDevice
+    >
+  ): void;
+  listDevices(
+    request?: protos.google.cloud.iot.v1.IListDevicesRequest,
+    optionsOrCallback?:
+      | CallOptions
+      | PaginationCallback<
+          protos.google.cloud.iot.v1.IListDevicesRequest,
+          protos.google.cloud.iot.v1.IListDevicesResponse | null | undefined,
+          protos.google.cloud.iot.v1.IDevice
+        >,
+    callback?: PaginationCallback<
+      protos.google.cloud.iot.v1.IListDevicesRequest,
+      protos.google.cloud.iot.v1.IListDevicesResponse | null | undefined,
+      protos.google.cloud.iot.v1.IDevice
+    >
+  ): Promise<
+    [
+      protos.google.cloud.iot.v1.IDevice[],
+      protos.google.cloud.iot.v1.IListDevicesRequest | null,
+      protos.google.cloud.iot.v1.IListDevicesResponse
+    ]
+  > | void {
+    request = request || {};
+    let options: CallOptions;
+    if (typeof optionsOrCallback === 'function' && callback === undefined) {
+      callback = optionsOrCallback;
+      options = {};
+    } else {
+      options = optionsOrCallback as CallOptions;
+    }
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    this.initialize();
+    return this.innerApiCalls.listDevices(request, options, callback);
+  }
+
+  /**
+   * Equivalent to `method.name.toCamelCase()`, but returns a NodeJS Stream object.
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The device registry path. Required. For example,
+   *   `projects/my-project/locations/us-central1/registries/my-registry`.
+   * @param {number[]} request.deviceNumIds
+   *   A list of device numeric IDs. If empty, this field is ignored. Maximum
+   *   IDs: 10,000.
+   * @param {string[]} request.deviceIds
+   *   A list of device string IDs. For example, `['device0', 'device12']`.
+   *   If empty, this field is ignored. Maximum IDs: 10,000
+   * @param {google.protobuf.FieldMask} request.fieldMask
+   *   The fields of the `Device` resource to be returned in the response. The
+   *   fields `id` and `num_id` are always returned, along with any
+   *   other fields specified in snake_case format, for example:
+   *   `last_heartbeat_time`.
+   * @param {google.cloud.iot.v1.GatewayListOptions} request.gatewayListOptions
+   *   Options related to gateways.
+   * @param {number} request.pageSize
+   *   The maximum number of devices to return in the response. If this value
+   *   is zero, the service will select a default size. A call may return fewer
+   *   objects than requested. A non-empty `next_page_token` in the response
+   *   indicates that more data is available.
+   * @param {string} request.pageToken
+   *   The value returned by the last `ListDevicesResponse`; indicates
+   *   that this is a continuation of a prior `ListDevices` call and
+   *   the system should return the next page of data.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Stream}
+   *   An object stream which emits an object representing [Device]{@link google.cloud.iot.v1.Device} on 'data' event.
+   *   The client library will perform auto-pagination by default: it will call the API as many
+   *   times as needed. Note that it can affect your quota.
+   *   We recommend using `listDevicesAsync()`
+   *   method described below for async iteration which you can stop as needed.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
+   *   for more details and examples.
+   */
+  listDevicesStream(
+    request?: protos.google.cloud.iot.v1.IListDevicesRequest,
+    options?: CallOptions
+  ): Transform {
+    request = request || {};
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    const defaultCallSettings = this._defaults['listDevices'];
+    const callSettings = defaultCallSettings.merge(options);
+    this.initialize();
+    return this.descriptors.page.listDevices.createStream(
+      this.innerApiCalls.listDevices as gax.GaxCall,
+      request,
+      callSettings
+    );
+  }
+
+  /**
+   * Equivalent to `listDevices`, but returns an iterable object.
+   *
+   * `for`-`await`-`of` syntax is used with the iterable to get response elements on-demand.
+   * @param {Object} request
+   *   The request object that will be sent.
+   * @param {string} request.parent
+   *   Required. The device registry path. Required. For example,
+   *   `projects/my-project/locations/us-central1/registries/my-registry`.
+   * @param {number[]} request.deviceNumIds
+   *   A list of device numeric IDs. If empty, this field is ignored. Maximum
+   *   IDs: 10,000.
+   * @param {string[]} request.deviceIds
+   *   A list of device string IDs. For example, `['device0', 'device12']`.
+   *   If empty, this field is ignored. Maximum IDs: 10,000
+   * @param {google.protobuf.FieldMask} request.fieldMask
+   *   The fields of the `Device` resource to be returned in the response. The
+   *   fields `id` and `num_id` are always returned, along with any
+   *   other fields specified in snake_case format, for example:
+   *   `last_heartbeat_time`.
+   * @param {google.cloud.iot.v1.GatewayListOptions} request.gatewayListOptions
+   *   Options related to gateways.
+   * @param {number} request.pageSize
+   *   The maximum number of devices to return in the response. If this value
+   *   is zero, the service will select a default size. A call may return fewer
+   *   objects than requested. A non-empty `next_page_token` in the response
+   *   indicates that more data is available.
+   * @param {string} request.pageToken
+   *   The value returned by the last `ListDevicesResponse`; indicates
+   *   that this is a continuation of a prior `ListDevices` call and
+   *   the system should return the next page of data.
+   * @param {object} [options]
+   *   Call options. See {@link https://googleapis.dev/nodejs/google-gax/latest/interfaces/CallOptions.html|CallOptions} for more details.
+   * @returns {Object}
+   *   An iterable Object that allows [async iteration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).
+   *   When you iterate the returned iterable, each element will be an object representing
+   *   [Device]{@link google.cloud.iot.v1.Device}. The API will be called under the hood as needed, once per the page,
+   *   so you can stop the iteration when you don't need more results.
+   *   Please see the
+   *   [documentation](https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#auto-pagination)
+   *   for more details and examples.
+   * @example <caption>include:samples/generated/v1/device_manager.list_devices.js</caption>
+   * region_tag:cloudiot_v1_generated_DeviceManager_ListDevices_async
+   */
+  listDevicesAsync(
+    request?: protos.google.cloud.iot.v1.IListDevicesRequest,
+    options?: CallOptions
+  ): AsyncIterable<protos.google.cloud.iot.v1.IDevice> {
+    request = request || {};
+    options = options || {};
+    options.otherArgs = options.otherArgs || {};
+    options.otherArgs.headers = options.otherArgs.headers || {};
+    options.otherArgs.headers['x-goog-request-params'] =
+      gax.routingHeader.fromParams({
+        parent: request.parent || '',
+      });
+    const defaultCallSettings = this._defaults['listDevices'];
+    const callSettings = defaultCallSettings.merge(options);
+    this.initialize();
+    return this.descriptors.page.listDevices.asyncIterate(
+      this.innerApiCalls['listDevices'] as GaxCall,
+      request as unknown as RequestType,
+      callSettings
+    ) as AsyncIterable<protos.google.cloud.iot.v1.IDevice>;
+  }
+  // --------------------
+  // -- Path templates --
+  // --------------------
+
+  /**
+   * Return a fully-qualified device resource name string.
+   *
+   * @param {string} project
+   * @param {string} location
+   * @param {string} registry
+   * @param {string} device
+   * @returns {string} Resource name string.
+   */
+  devicePath(
+    project: string,
+    location: string,
+    registry: string,
+    device: string
+  ) {
+    return this.pathTemplates.devicePathTemplate.render({
+      project: project,
+      location: location,
+      registry: registry,
+      device: device,
+    });
+  }
+
+  /**
+   * Parse the project from Device resource.
+   *
+   * @param {string} deviceName
+   *   A fully-qualified path representing Device resource.
+   * @returns {string} A string representing the project.
+   */
+  matchProjectFromDeviceName(deviceName: string) {
+    return this.pathTemplates.devicePathTemplate.match(deviceName).project;
+  }
+
+  /**
+   * Parse the location from Device resource.
+   *
+   * @param {string} deviceName
+   *   A fully-qualified path representing Device resource.
+   * @returns {string} A string representing the location.
+   */
+  matchLocationFromDeviceName(deviceName: string) {
+    return this.pathTemplates.devicePathTemplate.match(deviceName).location;
+  }
+
+  /**
+   * Parse the registry from Device resource.
+   *
+   * @param {string} deviceName
+   *   A fully-qualified path representing Device resource.
+   * @returns {string} A string representing the registry.
+   */
+  matchRegistryFromDeviceName(deviceName: string) {
+    return this.pathTemplates.devicePathTemplate.match(deviceName).registry;
+  }
+
+  /**
+   * Parse the device from Device resource.
+   *
+   * @param {string} deviceName
+   *   A fully-qualified path representing Device resource.
+   * @returns {string} A string representing the device.
+   */
+  matchDeviceFromDeviceName(deviceName: string) {
+    return this.pathTemplates.devicePathTemplate.match(deviceName).device;
+  }
+
+  /**
+   * Return a fully-qualified location resource name string.
+   *
+   * @param {string} project
+   * @param {string} location
+   * @returns {string} Resource name string.
+   */
+  locationPath(project: string, location: string) {
+    return this.pathTemplates.locationPathTemplate.render({
+      project: project,
+      location: location,
+    });
+  }
+
+  /**
+   * Parse the project from Location resource.
+   *
+   * @param {string} locationName
+   *   A fully-qualified path representing Location resource.
+   * @returns {string} A string representing the project.
+   */
+  matchProjectFromLocationName(locationName: string) {
+    return this.pathTemplates.locationPathTemplate.match(locationName).project;
+  }
+
+  /**
+   * Parse the location from Location resource.
+   *
+   * @param {string} locationName
+   *   A fully-qualified path representing Location resource.
+   * @returns {string} A string representing the location.
+   */
+  matchLocationFromLocationName(locationName: string) {
+    return this.pathTemplates.locationPathTemplate.match(locationName).location;
+  }
+
+  /**
+   * Return a fully-qualified registry resource name string.
+   *
+   * @param {string} project
+   * @param {string} location
+   * @param {string} registry
+   * @returns {string} Resource name string.
+   */
+  registryPath(project: string, location: string, registry: string) {
+    return this.pathTemplates.registryPathTemplate.render({
+      project: project,
+      location: location,
+      registry: registry,
+    });
+  }
+
+  /**
+   * Parse the project from Registry resource.
+   *
+   * @param {string} registryName
+   *   A fully-qualified path representing Registry resource.
+   * @returns {string} A string representing the project.
+   */
+  matchProjectFromRegistryName(registryName: string) {
+    return this.pathTemplates.registryPathTemplate.match(registryName).project;
+  }
+
+  /**
+   * Parse the location from Registry resource.
+   *
+   * @param {string} registryName
+   *   A fully-qualified path representing Registry resource.
+   * @returns {string} A string representing the location.
+   */
+  matchLocationFromRegistryName(registryName: string) {
+    return this.pathTemplates.registryPathTemplate.match(registryName).location;
+  }
+
+  /**
+   * Parse the registry from Registry resource.
+   *
+   * @param {string} registryName
+   *   A fully-qualified path representing Registry resource.
+   * @returns {string} A string representing the registry.
+   */
+  matchRegistryFromRegistryName(registryName: string) {
+    return this.pathTemplates.registryPathTemplate.match(registryName).registry;
+  }
+
+  /**
+   * Terminate the gRPC channel and close the client.
+   *
+   * The client will no longer be usable and all future behavior is undefined.
+   * @returns {Promise} A promise that resolves when the client is closed.
+   */
+  close(): Promise<void> {
+    if (this.deviceManagerStub && !this._terminated) {
+      return this.deviceManagerStub.then(stub => {
+        this._terminated = true;
+        stub.close();
+      });
+    }
+    return Promise.resolve();
+  }
+}
diff --git a/src/v1/device_manager_client_config.json b/src/v1/device_manager_client_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..5ded0fd1cb34bb4cdb8dcd5a1330a97c8ff4704f
--- /dev/null
+++ b/src/v1/device_manager_client_config.json
@@ -0,0 +1,135 @@
+{
+  "interfaces": {
+    "google.cloud.iot.v1.DeviceManager": {
+      "retry_codes": {
+        "non_idempotent": [],
+        "idempotent": [
+          "DEADLINE_EXCEEDED",
+          "UNAVAILABLE"
+        ],
+        "deadline_exceeded_resource_exhausted_unavailable": [
+          "DEADLINE_EXCEEDED",
+          "RESOURCE_EXHAUSTED",
+          "UNAVAILABLE"
+        ]
+      },
+      "retry_params": {
+        "default": {
+          "initial_retry_delay_millis": 100,
+          "retry_delay_multiplier": 1.3,
+          "max_retry_delay_millis": 60000,
+          "initial_rpc_timeout_millis": 60000,
+          "rpc_timeout_multiplier": 1,
+          "max_rpc_timeout_millis": 60000,
+          "total_timeout_millis": 600000
+        },
+        "01d6d956b4dadd7e38ee9dec12ed8720e6e6f90c": {
+          "initial_retry_delay_millis": 1000,
+          "retry_delay_multiplier": 1.3,
+          "max_retry_delay_millis": 60000,
+          "initial_rpc_timeout_millis": 60000,
+          "rpc_timeout_multiplier": 1,
+          "max_rpc_timeout_millis": 60000,
+          "total_timeout_millis": 600000
+        }
+      },
+      "methods": {
+        "CreateDeviceRegistry": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "GetDeviceRegistry": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "UpdateDeviceRegistry": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "DeleteDeviceRegistry": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "ListDeviceRegistries": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "CreateDevice": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "GetDevice": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "UpdateDevice": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "DeleteDevice": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "ListDevices": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "ModifyCloudToDeviceConfig": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "deadline_exceeded_resource_exhausted_unavailable",
+          "retry_params_name": "01d6d956b4dadd7e38ee9dec12ed8720e6e6f90c"
+        },
+        "ListDeviceConfigVersions": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "ListDeviceStates": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "idempotent",
+          "retry_params_name": "default"
+        },
+        "SetIamPolicy": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "GetIamPolicy": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "TestIamPermissions": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "SendCommandToDevice": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "deadline_exceeded_resource_exhausted_unavailable",
+          "retry_params_name": "01d6d956b4dadd7e38ee9dec12ed8720e6e6f90c"
+        },
+        "BindDeviceToGateway": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        },
+        "UnbindDeviceFromGateway": {
+          "timeout_millis": 120000,
+          "retry_codes_name": "non_idempotent",
+          "retry_params_name": "default"
+        }
+      }
+    }
+  }
+}
diff --git a/src/v1/device_manager_proto_list.json b/src/v1/device_manager_proto_list.json
new file mode 100644
index 0000000000000000000000000000000000000000..95cf55973ec80e013c60df54dcec193526d6a4f6
--- /dev/null
+++ b/src/v1/device_manager_proto_list.json
@@ -0,0 +1,4 @@
+[
+  "../../protos/google/cloud/iot/v1/device_manager.proto",
+  "../../protos/google/cloud/iot/v1/resources.proto"
+]
diff --git a/src/v1/gapic_metadata.json b/src/v1/gapic_metadata.json
new file mode 100644
index 0000000000000000000000000000000000000000..28ab3c5db9b65cb6b9d9b43758c17ae883a75fdc
--- /dev/null
+++ b/src/v1/gapic_metadata.json
@@ -0,0 +1,221 @@
+{
+  "schema": "1.0",
+  "comment": "This file maps proto services/RPCs to the corresponding library clients/methods",
+  "language": "typescript",
+  "protoPackage": "google.cloud.iot.v1",
+  "libraryPackage": "@google-cloud/iot",
+  "services": {
+    "DeviceManager": {
+      "clients": {
+        "grpc": {
+          "libraryClient": "DeviceManagerClient",
+          "rpcs": {
+            "CreateDeviceRegistry": {
+              "methods": [
+                "createDeviceRegistry"
+              ]
+            },
+            "GetDeviceRegistry": {
+              "methods": [
+                "getDeviceRegistry"
+              ]
+            },
+            "UpdateDeviceRegistry": {
+              "methods": [
+                "updateDeviceRegistry"
+              ]
+            },
+            "DeleteDeviceRegistry": {
+              "methods": [
+                "deleteDeviceRegistry"
+              ]
+            },
+            "CreateDevice": {
+              "methods": [
+                "createDevice"
+              ]
+            },
+            "GetDevice": {
+              "methods": [
+                "getDevice"
+              ]
+            },
+            "UpdateDevice": {
+              "methods": [
+                "updateDevice"
+              ]
+            },
+            "DeleteDevice": {
+              "methods": [
+                "deleteDevice"
+              ]
+            },
+            "ModifyCloudToDeviceConfig": {
+              "methods": [
+                "modifyCloudToDeviceConfig"
+              ]
+            },
+            "ListDeviceConfigVersions": {
+              "methods": [
+                "listDeviceConfigVersions"
+              ]
+            },
+            "ListDeviceStates": {
+              "methods": [
+                "listDeviceStates"
+              ]
+            },
+            "SetIamPolicy": {
+              "methods": [
+                "setIamPolicy"
+              ]
+            },
+            "GetIamPolicy": {
+              "methods": [
+                "getIamPolicy"
+              ]
+            },
+            "TestIamPermissions": {
+              "methods": [
+                "testIamPermissions"
+              ]
+            },
+            "SendCommandToDevice": {
+              "methods": [
+                "sendCommandToDevice"
+              ]
+            },
+            "BindDeviceToGateway": {
+              "methods": [
+                "bindDeviceToGateway"
+              ]
+            },
+            "UnbindDeviceFromGateway": {
+              "methods": [
+                "unbindDeviceFromGateway"
+              ]
+            },
+            "ListDeviceRegistries": {
+              "methods": [
+                "listDeviceRegistries",
+                "listDeviceRegistriesStream",
+                "listDeviceRegistriesAsync"
+              ]
+            },
+            "ListDevices": {
+              "methods": [
+                "listDevices",
+                "listDevicesStream",
+                "listDevicesAsync"
+              ]
+            }
+          }
+        },
+        "grpc-fallback": {
+          "libraryClient": "DeviceManagerClient",
+          "rpcs": {
+            "CreateDeviceRegistry": {
+              "methods": [
+                "createDeviceRegistry"
+              ]
+            },
+            "GetDeviceRegistry": {
+              "methods": [
+                "getDeviceRegistry"
+              ]
+            },
+            "UpdateDeviceRegistry": {
+              "methods": [
+                "updateDeviceRegistry"
+              ]
+            },
+            "DeleteDeviceRegistry": {
+              "methods": [
+                "deleteDeviceRegistry"
+              ]
+            },
+            "CreateDevice": {
+              "methods": [
+                "createDevice"
+              ]
+            },
+            "GetDevice": {
+              "methods": [
+                "getDevice"
+              ]
+            },
+            "UpdateDevice": {
+              "methods": [
+                "updateDevice"
+              ]
+            },
+            "DeleteDevice": {
+              "methods": [
+                "deleteDevice"
+              ]
+            },
+            "ModifyCloudToDeviceConfig": {
+              "methods": [
+                "modifyCloudToDeviceConfig"
+              ]
+            },
+            "ListDeviceConfigVersions": {
+              "methods": [
+                "listDeviceConfigVersions"
+              ]
+            },
+            "ListDeviceStates": {
+              "methods": [
+                "listDeviceStates"
+              ]
+            },
+            "SetIamPolicy": {
+              "methods": [
+                "setIamPolicy"
+              ]
+            },
+            "GetIamPolicy": {
+              "methods": [
+                "getIamPolicy"
+              ]
+            },
+            "TestIamPermissions": {
+              "methods": [
+                "testIamPermissions"
+              ]
+            },
+            "SendCommandToDevice": {
+              "methods": [
+                "sendCommandToDevice"
+              ]
+            },
+            "BindDeviceToGateway": {
+              "methods": [
+                "bindDeviceToGateway"
+              ]
+            },
+            "UnbindDeviceFromGateway": {
+              "methods": [
+                "unbindDeviceFromGateway"
+              ]
+            },
+            "ListDeviceRegistries": {
+              "methods": [
+                "listDeviceRegistries",
+                "listDeviceRegistriesStream",
+                "listDeviceRegistriesAsync"
+              ]
+            },
+            "ListDevices": {
+              "methods": [
+                "listDevices",
+                "listDevicesStream",
+                "listDevicesAsync"
+              ]
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/v1/index.ts b/src/v1/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..49977b4065f1b4a84c384e52f9ab40da6144584b
--- /dev/null
+++ b/src/v1/index.ts
@@ -0,0 +1,19 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+export {DeviceManagerClient} from './device_manager_client';
diff --git a/system-test/fixtures/sample/src/index.js b/system-test/fixtures/sample/src/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..42d2b98dc901a1387dc903d8b748cd9e2370c2ae
--- /dev/null
+++ b/system-test/fixtures/sample/src/index.js
@@ -0,0 +1,26 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+/* eslint-disable node/no-missing-require, no-unused-vars */
+const iot = require('@google-cloud/iot');
+
+function main() {
+  const deviceManagerClient = new iot.DeviceManagerClient();
+}
+
+main();
diff --git a/system-test/fixtures/sample/src/index.ts b/system-test/fixtures/sample/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b3c0747089db5e70fab22a076f6c534c5a1e3d6
--- /dev/null
+++ b/system-test/fixtures/sample/src/index.ts
@@ -0,0 +1,32 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+import {DeviceManagerClient} from '@google-cloud/iot';
+
+// check that the client class type name can be used
+function doStuffWithDeviceManagerClient(client: DeviceManagerClient) {
+  client.close();
+}
+
+function main() {
+  // check that the client instance can be created
+  const deviceManagerClient = new DeviceManagerClient();
+  doStuffWithDeviceManagerClient(deviceManagerClient);
+}
+
+main();
diff --git a/system-test/install.ts b/system-test/install.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6dd1eaadafaa94fc14ab99baf9d8f6420d79b7d5
--- /dev/null
+++ b/system-test/install.ts
@@ -0,0 +1,51 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+import {packNTest} from 'pack-n-play';
+import {readFileSync} from 'fs';
+import {describe, it} from 'mocha';
+
+describe('📦 pack-n-play test', () => {
+  it('TypeScript code', async function () {
+    this.timeout(300000);
+    const options = {
+      packageDir: process.cwd(),
+      sample: {
+        description: 'TypeScript user can use the type definitions',
+        ts: readFileSync(
+          './system-test/fixtures/sample/src/index.ts'
+        ).toString(),
+      },
+    };
+    await packNTest(options);
+  });
+
+  it('JavaScript code', async function () {
+    this.timeout(300000);
+    const options = {
+      packageDir: process.cwd(),
+      sample: {
+        description: 'JavaScript user can use the library',
+        ts: readFileSync(
+          './system-test/fixtures/sample/src/index.js'
+        ).toString(),
+      },
+    };
+    await packNTest(options);
+  });
+});
diff --git a/test/gapic_device_manager_v1.ts b/test/gapic_device_manager_v1.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d2d77742070e847cc02b68e32ee4d0596318988d
--- /dev/null
+++ b/test/gapic_device_manager_v1.ts
@@ -0,0 +1,3136 @@
+// Copyright 2022 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
+//
+//     https://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.
+//
+// ** This file is automatically generated by gapic-generator-typescript. **
+// ** https://github.com/googleapis/gapic-generator-typescript **
+// ** All changes to this file may be overwritten. **
+
+import * as protos from '../protos/protos';
+import * as assert from 'assert';
+import * as sinon from 'sinon';
+import {SinonStub} from 'sinon';
+import {describe, it} from 'mocha';
+import * as devicemanagerModule from '../src';
+
+import {PassThrough} from 'stream';
+
+import {protobuf} from 'google-gax';
+
+function generateSampleMessage<T extends object>(instance: T) {
+  const filledObject = (
+    instance.constructor as typeof protobuf.Message
+  ).toObject(instance as protobuf.Message<T>, {defaults: true});
+  return (instance.constructor as typeof protobuf.Message).fromObject(
+    filledObject
+  ) as T;
+}
+
+function stubSimpleCall<ResponseType>(response?: ResponseType, error?: Error) {
+  return error
+    ? sinon.stub().rejects(error)
+    : sinon.stub().resolves([response]);
+}
+
+function stubSimpleCallWithCallback<ResponseType>(
+  response?: ResponseType,
+  error?: Error
+) {
+  return error
+    ? sinon.stub().callsArgWith(2, error)
+    : sinon.stub().callsArgWith(2, null, response);
+}
+
+function stubPageStreamingCall<ResponseType>(
+  responses?: ResponseType[],
+  error?: Error
+) {
+  const pagingStub = sinon.stub();
+  if (responses) {
+    for (let i = 0; i < responses.length; ++i) {
+      pagingStub.onCall(i).callsArgWith(2, null, responses[i]);
+    }
+  }
+  const transformStub = error
+    ? sinon.stub().callsArgWith(2, error)
+    : pagingStub;
+  const mockStream = new PassThrough({
+    objectMode: true,
+    transform: transformStub,
+  });
+  // trigger as many responses as needed
+  if (responses) {
+    for (let i = 0; i < responses.length; ++i) {
+      setImmediate(() => {
+        mockStream.write({});
+      });
+    }
+    setImmediate(() => {
+      mockStream.end();
+    });
+  } else {
+    setImmediate(() => {
+      mockStream.write({});
+    });
+    setImmediate(() => {
+      mockStream.end();
+    });
+  }
+  return sinon.stub().returns(mockStream);
+}
+
+function stubAsyncIterationCall<ResponseType>(
+  responses?: ResponseType[],
+  error?: Error
+) {
+  let counter = 0;
+  const asyncIterable = {
+    [Symbol.asyncIterator]() {
+      return {
+        async next() {
+          if (error) {
+            return Promise.reject(error);
+          }
+          if (counter >= responses!.length) {
+            return Promise.resolve({done: true, value: undefined});
+          }
+          return Promise.resolve({done: false, value: responses![counter++]});
+        },
+      };
+    },
+  };
+  return sinon.stub().returns(asyncIterable);
+}
+
+describe('v1.DeviceManagerClient', () => {
+  it('has servicePath', () => {
+    const servicePath = devicemanagerModule.v1.DeviceManagerClient.servicePath;
+    assert(servicePath);
+  });
+
+  it('has apiEndpoint', () => {
+    const apiEndpoint = devicemanagerModule.v1.DeviceManagerClient.apiEndpoint;
+    assert(apiEndpoint);
+  });
+
+  it('has port', () => {
+    const port = devicemanagerModule.v1.DeviceManagerClient.port;
+    assert(port);
+    assert(typeof port === 'number');
+  });
+
+  it('should create a client with no option', () => {
+    const client = new devicemanagerModule.v1.DeviceManagerClient();
+    assert(client);
+  });
+
+  it('should create a client with gRPC fallback', () => {
+    const client = new devicemanagerModule.v1.DeviceManagerClient({
+      fallback: true,
+    });
+    assert(client);
+  });
+
+  it('has initialize method and supports deferred initialization', async () => {
+    const client = new devicemanagerModule.v1.DeviceManagerClient({
+      credentials: {client_email: 'bogus', private_key: 'bogus'},
+      projectId: 'bogus',
+    });
+    assert.strictEqual(client.deviceManagerStub, undefined);
+    await client.initialize();
+    assert(client.deviceManagerStub);
+  });
+
+  it('has close method for the initialized client', done => {
+    const client = new devicemanagerModule.v1.DeviceManagerClient({
+      credentials: {client_email: 'bogus', private_key: 'bogus'},
+      projectId: 'bogus',
+    });
+    client.initialize();
+    assert(client.deviceManagerStub);
+    client.close().then(() => {
+      done();
+    });
+  });
+
+  it('has close method for the non-initialized client', done => {
+    const client = new devicemanagerModule.v1.DeviceManagerClient({
+      credentials: {client_email: 'bogus', private_key: 'bogus'},
+      projectId: 'bogus',
+    });
+    assert.strictEqual(client.deviceManagerStub, undefined);
+    client.close().then(() => {
+      done();
+    });
+  });
+
+  it('has getProjectId method', async () => {
+    const fakeProjectId = 'fake-project-id';
+    const client = new devicemanagerModule.v1.DeviceManagerClient({
+      credentials: {client_email: 'bogus', private_key: 'bogus'},
+      projectId: 'bogus',
+    });
+    client.auth.getProjectId = sinon.stub().resolves(fakeProjectId);
+    const result = await client.getProjectId();
+    assert.strictEqual(result, fakeProjectId);
+    assert((client.auth.getProjectId as SinonStub).calledWithExactly());
+  });
+
+  it('has getProjectId method with callback', async () => {
+    const fakeProjectId = 'fake-project-id';
+    const client = new devicemanagerModule.v1.DeviceManagerClient({
+      credentials: {client_email: 'bogus', private_key: 'bogus'},
+      projectId: 'bogus',
+    });
+    client.auth.getProjectId = sinon
+      .stub()
+      .callsArgWith(0, null, fakeProjectId);
+    const promise = new Promise((resolve, reject) => {
+      client.getProjectId((err?: Error | null, projectId?: string | null) => {
+        if (err) {
+          reject(err);
+        } else {
+          resolve(projectId);
+        }
+      });
+    });
+    const result = await promise;
+    assert.strictEqual(result, fakeProjectId);
+  });
+
+  describe('createDeviceRegistry', () => {
+    it('invokes createDeviceRegistry without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRegistryRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceRegistry()
+      );
+      client.innerApiCalls.createDeviceRegistry =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.createDeviceRegistry(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.createDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes createDeviceRegistry without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRegistryRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceRegistry()
+      );
+      client.innerApiCalls.createDeviceRegistry =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.createDeviceRegistry(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDeviceRegistry | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.createDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes createDeviceRegistry with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRegistryRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.createDeviceRegistry = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.createDeviceRegistry(request), expectedError);
+      assert(
+        (client.innerApiCalls.createDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes createDeviceRegistry with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRegistryRequest()
+      );
+      request.parent = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.createDeviceRegistry(request), expectedError);
+    });
+  });
+
+  describe('getDeviceRegistry', () => {
+    it('invokes getDeviceRegistry without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceRegistry()
+      );
+      client.innerApiCalls.getDeviceRegistry = stubSimpleCall(expectedResponse);
+      const [response] = await client.getDeviceRegistry(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.getDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes getDeviceRegistry without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceRegistry()
+      );
+      client.innerApiCalls.getDeviceRegistry =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.getDeviceRegistry(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDeviceRegistry | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.getDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes getDeviceRegistry with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.getDeviceRegistry = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.getDeviceRegistry(request), expectedError);
+      assert(
+        (client.innerApiCalls.getDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes getDeviceRegistry with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.getDeviceRegistry(request), expectedError);
+    });
+  });
+
+  describe('updateDeviceRegistry', () => {
+    it('invokes updateDeviceRegistry without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRegistryRequest()
+      );
+      request.deviceRegistry = {};
+      request.deviceRegistry.name = '';
+      const expectedHeaderRequestParams = 'device_registry.name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceRegistry()
+      );
+      client.innerApiCalls.updateDeviceRegistry =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.updateDeviceRegistry(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.updateDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes updateDeviceRegistry without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRegistryRequest()
+      );
+      request.deviceRegistry = {};
+      request.deviceRegistry.name = '';
+      const expectedHeaderRequestParams = 'device_registry.name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceRegistry()
+      );
+      client.innerApiCalls.updateDeviceRegistry =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.updateDeviceRegistry(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDeviceRegistry | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.updateDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes updateDeviceRegistry with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRegistryRequest()
+      );
+      request.deviceRegistry = {};
+      request.deviceRegistry.name = '';
+      const expectedHeaderRequestParams = 'device_registry.name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.updateDeviceRegistry = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.updateDeviceRegistry(request), expectedError);
+      assert(
+        (client.innerApiCalls.updateDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes updateDeviceRegistry with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRegistryRequest()
+      );
+      request.deviceRegistry = {};
+      request.deviceRegistry.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.updateDeviceRegistry(request), expectedError);
+    });
+  });
+
+  describe('deleteDeviceRegistry', () => {
+    it('invokes deleteDeviceRegistry without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.protobuf.Empty()
+      );
+      client.innerApiCalls.deleteDeviceRegistry =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.deleteDeviceRegistry(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.deleteDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes deleteDeviceRegistry without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.protobuf.Empty()
+      );
+      client.innerApiCalls.deleteDeviceRegistry =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.deleteDeviceRegistry(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.protobuf.IEmpty | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.deleteDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes deleteDeviceRegistry with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.deleteDeviceRegistry = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.deleteDeviceRegistry(request), expectedError);
+      assert(
+        (client.innerApiCalls.deleteDeviceRegistry as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes deleteDeviceRegistry with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRegistryRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.deleteDeviceRegistry(request), expectedError);
+    });
+  });
+
+  describe('createDevice', () => {
+    it('invokes createDevice without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.Device()
+      );
+      client.innerApiCalls.createDevice = stubSimpleCall(expectedResponse);
+      const [response] = await client.createDevice(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.createDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes createDevice without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.Device()
+      );
+      client.innerApiCalls.createDevice =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.createDevice(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDevice | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.createDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes createDevice with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.createDevice = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.createDevice(request), expectedError);
+      assert(
+        (client.innerApiCalls.createDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes createDevice with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.CreateDeviceRequest()
+      );
+      request.parent = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.createDevice(request), expectedError);
+    });
+  });
+
+  describe('getDevice', () => {
+    it('invokes getDevice without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.Device()
+      );
+      client.innerApiCalls.getDevice = stubSimpleCall(expectedResponse);
+      const [response] = await client.getDevice(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.getDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes getDevice without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.Device()
+      );
+      client.innerApiCalls.getDevice =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.getDevice(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDevice | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.getDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes getDevice with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.getDevice = stubSimpleCall(undefined, expectedError);
+      await assert.rejects(client.getDevice(request), expectedError);
+      assert(
+        (client.innerApiCalls.getDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes getDevice with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.GetDeviceRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.getDevice(request), expectedError);
+    });
+  });
+
+  describe('updateDevice', () => {
+    it('invokes updateDevice without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRequest()
+      );
+      request.device = {};
+      request.device.name = '';
+      const expectedHeaderRequestParams = 'device.name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.Device()
+      );
+      client.innerApiCalls.updateDevice = stubSimpleCall(expectedResponse);
+      const [response] = await client.updateDevice(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.updateDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes updateDevice without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRequest()
+      );
+      request.device = {};
+      request.device.name = '';
+      const expectedHeaderRequestParams = 'device.name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.Device()
+      );
+      client.innerApiCalls.updateDevice =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.updateDevice(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDevice | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.updateDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes updateDevice with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRequest()
+      );
+      request.device = {};
+      request.device.name = '';
+      const expectedHeaderRequestParams = 'device.name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.updateDevice = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.updateDevice(request), expectedError);
+      assert(
+        (client.innerApiCalls.updateDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes updateDevice with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UpdateDeviceRequest()
+      );
+      request.device = {};
+      request.device.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.updateDevice(request), expectedError);
+    });
+  });
+
+  describe('deleteDevice', () => {
+    it('invokes deleteDevice without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.protobuf.Empty()
+      );
+      client.innerApiCalls.deleteDevice = stubSimpleCall(expectedResponse);
+      const [response] = await client.deleteDevice(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.deleteDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes deleteDevice without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.protobuf.Empty()
+      );
+      client.innerApiCalls.deleteDevice =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.deleteDevice(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.protobuf.IEmpty | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.deleteDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes deleteDevice with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.deleteDevice = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.deleteDevice(request), expectedError);
+      assert(
+        (client.innerApiCalls.deleteDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes deleteDevice with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeleteDeviceRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.deleteDevice(request), expectedError);
+    });
+  });
+
+  describe('modifyCloudToDeviceConfig', () => {
+    it('invokes modifyCloudToDeviceConfig without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceConfig()
+      );
+      client.innerApiCalls.modifyCloudToDeviceConfig =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.modifyCloudToDeviceConfig(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.modifyCloudToDeviceConfig as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes modifyCloudToDeviceConfig without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.DeviceConfig()
+      );
+      client.innerApiCalls.modifyCloudToDeviceConfig =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.modifyCloudToDeviceConfig(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDeviceConfig | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.modifyCloudToDeviceConfig as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes modifyCloudToDeviceConfig with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.modifyCloudToDeviceConfig = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(
+        client.modifyCloudToDeviceConfig(request),
+        expectedError
+      );
+      assert(
+        (client.innerApiCalls.modifyCloudToDeviceConfig as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes modifyCloudToDeviceConfig with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ModifyCloudToDeviceConfigRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(
+        client.modifyCloudToDeviceConfig(request),
+        expectedError
+      );
+    });
+  });
+
+  describe('listDeviceConfigVersions', () => {
+    it('invokes listDeviceConfigVersions without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceConfigVersionsRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceConfigVersionsResponse()
+      );
+      client.innerApiCalls.listDeviceConfigVersions =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.listDeviceConfigVersions(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDeviceConfigVersions as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDeviceConfigVersions without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceConfigVersionsRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceConfigVersionsResponse()
+      );
+      client.innerApiCalls.listDeviceConfigVersions =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.listDeviceConfigVersions(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IListDeviceConfigVersionsResponse | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDeviceConfigVersions as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes listDeviceConfigVersions with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceConfigVersionsRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.listDeviceConfigVersions = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(
+        client.listDeviceConfigVersions(request),
+        expectedError
+      );
+      assert(
+        (client.innerApiCalls.listDeviceConfigVersions as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDeviceConfigVersions with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceConfigVersionsRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(
+        client.listDeviceConfigVersions(request),
+        expectedError
+      );
+    });
+  });
+
+  describe('listDeviceStates', () => {
+    it('invokes listDeviceStates without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceStatesRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceStatesResponse()
+      );
+      client.innerApiCalls.listDeviceStates = stubSimpleCall(expectedResponse);
+      const [response] = await client.listDeviceStates(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDeviceStates as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDeviceStates without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceStatesRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceStatesResponse()
+      );
+      client.innerApiCalls.listDeviceStates =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.listDeviceStates(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IListDeviceStatesResponse | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDeviceStates as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes listDeviceStates with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceStatesRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.listDeviceStates = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.listDeviceStates(request), expectedError);
+      assert(
+        (client.innerApiCalls.listDeviceStates as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDeviceStates with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceStatesRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.listDeviceStates(request), expectedError);
+    });
+  });
+
+  describe('setIamPolicy', () => {
+    it('invokes setIamPolicy without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.SetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.iam.v1.Policy()
+      );
+      client.innerApiCalls.setIamPolicy = stubSimpleCall(expectedResponse);
+      const [response] = await client.setIamPolicy(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.setIamPolicy as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes setIamPolicy without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.SetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.iam.v1.Policy()
+      );
+      client.innerApiCalls.setIamPolicy =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.setIamPolicy(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.iam.v1.IPolicy | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.setIamPolicy as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes setIamPolicy with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.SetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.setIamPolicy = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.setIamPolicy(request), expectedError);
+      assert(
+        (client.innerApiCalls.setIamPolicy as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes setIamPolicy with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.SetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.setIamPolicy(request), expectedError);
+    });
+  });
+
+  describe('getIamPolicy', () => {
+    it('invokes getIamPolicy without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.GetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.iam.v1.Policy()
+      );
+      client.innerApiCalls.getIamPolicy = stubSimpleCall(expectedResponse);
+      const [response] = await client.getIamPolicy(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.getIamPolicy as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes getIamPolicy without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.GetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.iam.v1.Policy()
+      );
+      client.innerApiCalls.getIamPolicy =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.getIamPolicy(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.iam.v1.IPolicy | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.getIamPolicy as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes getIamPolicy with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.GetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.getIamPolicy = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.getIamPolicy(request), expectedError);
+      assert(
+        (client.innerApiCalls.getIamPolicy as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes getIamPolicy with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.GetIamPolicyRequest()
+      );
+      request.resource = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.getIamPolicy(request), expectedError);
+    });
+  });
+
+  describe('testIamPermissions', () => {
+    it('invokes testIamPermissions without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.TestIamPermissionsRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.iam.v1.TestIamPermissionsResponse()
+      );
+      client.innerApiCalls.testIamPermissions =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.testIamPermissions(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.testIamPermissions as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes testIamPermissions without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.TestIamPermissionsRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.iam.v1.TestIamPermissionsResponse()
+      );
+      client.innerApiCalls.testIamPermissions =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.testIamPermissions(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.iam.v1.ITestIamPermissionsResponse | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.testIamPermissions as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes testIamPermissions with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.TestIamPermissionsRequest()
+      );
+      request.resource = '';
+      const expectedHeaderRequestParams = 'resource=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.testIamPermissions = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.testIamPermissions(request), expectedError);
+      assert(
+        (client.innerApiCalls.testIamPermissions as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes testIamPermissions with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.iam.v1.TestIamPermissionsRequest()
+      );
+      request.resource = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.testIamPermissions(request), expectedError);
+    });
+  });
+
+  describe('sendCommandToDevice', () => {
+    it('invokes sendCommandToDevice without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.SendCommandToDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.SendCommandToDeviceResponse()
+      );
+      client.innerApiCalls.sendCommandToDevice =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.sendCommandToDevice(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.sendCommandToDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes sendCommandToDevice without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.SendCommandToDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.SendCommandToDeviceResponse()
+      );
+      client.innerApiCalls.sendCommandToDevice =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.sendCommandToDevice(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.ISendCommandToDeviceResponse | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.sendCommandToDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes sendCommandToDevice with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.SendCommandToDeviceRequest()
+      );
+      request.name = '';
+      const expectedHeaderRequestParams = 'name=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.sendCommandToDevice = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.sendCommandToDevice(request), expectedError);
+      assert(
+        (client.innerApiCalls.sendCommandToDevice as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes sendCommandToDevice with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.SendCommandToDeviceRequest()
+      );
+      request.name = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.sendCommandToDevice(request), expectedError);
+    });
+  });
+
+  describe('bindDeviceToGateway', () => {
+    it('invokes bindDeviceToGateway without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.BindDeviceToGatewayRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.BindDeviceToGatewayResponse()
+      );
+      client.innerApiCalls.bindDeviceToGateway =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.bindDeviceToGateway(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.bindDeviceToGateway as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes bindDeviceToGateway without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.BindDeviceToGatewayRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.BindDeviceToGatewayResponse()
+      );
+      client.innerApiCalls.bindDeviceToGateway =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.bindDeviceToGateway(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IBindDeviceToGatewayResponse | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.bindDeviceToGateway as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes bindDeviceToGateway with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.BindDeviceToGatewayRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.bindDeviceToGateway = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.bindDeviceToGateway(request), expectedError);
+      assert(
+        (client.innerApiCalls.bindDeviceToGateway as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes bindDeviceToGateway with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.BindDeviceToGatewayRequest()
+      );
+      request.parent = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(client.bindDeviceToGateway(request), expectedError);
+    });
+  });
+
+  describe('unbindDeviceFromGateway', () => {
+    it('invokes unbindDeviceFromGateway without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UnbindDeviceFromGatewayResponse()
+      );
+      client.innerApiCalls.unbindDeviceFromGateway =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.unbindDeviceFromGateway(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.unbindDeviceFromGateway as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes unbindDeviceFromGateway without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UnbindDeviceFromGatewayResponse()
+      );
+      client.innerApiCalls.unbindDeviceFromGateway =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.unbindDeviceFromGateway(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IUnbindDeviceFromGatewayResponse | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.unbindDeviceFromGateway as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes unbindDeviceFromGateway with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.unbindDeviceFromGateway = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(
+        client.unbindDeviceFromGateway(request),
+        expectedError
+      );
+      assert(
+        (client.innerApiCalls.unbindDeviceFromGateway as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes unbindDeviceFromGateway with closed client', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.UnbindDeviceFromGatewayRequest()
+      );
+      request.parent = '';
+      const expectedError = new Error('The client has already been closed.');
+      client.close();
+      await assert.rejects(
+        client.unbindDeviceFromGateway(request),
+        expectedError
+      );
+    });
+  });
+
+  describe('listDeviceRegistries', () => {
+    it('invokes listDeviceRegistries without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceRegistriesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+      ];
+      client.innerApiCalls.listDeviceRegistries =
+        stubSimpleCall(expectedResponse);
+      const [response] = await client.listDeviceRegistries(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDeviceRegistries as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDeviceRegistries without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceRegistriesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+      ];
+      client.innerApiCalls.listDeviceRegistries =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.listDeviceRegistries(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDeviceRegistry[] | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDeviceRegistries as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes listDeviceRegistries with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceRegistriesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.listDeviceRegistries = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.listDeviceRegistries(request), expectedError);
+      assert(
+        (client.innerApiCalls.listDeviceRegistries as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDeviceRegistriesStream without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceRegistriesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+      ];
+      client.descriptors.page.listDeviceRegistries.createStream =
+        stubPageStreamingCall(expectedResponse);
+      const stream = client.listDeviceRegistriesStream(request);
+      const promise = new Promise((resolve, reject) => {
+        const responses: protos.google.cloud.iot.v1.DeviceRegistry[] = [];
+        stream.on(
+          'data',
+          (response: protos.google.cloud.iot.v1.DeviceRegistry) => {
+            responses.push(response);
+          }
+        );
+        stream.on('end', () => {
+          resolve(responses);
+        });
+        stream.on('error', (err: Error) => {
+          reject(err);
+        });
+      });
+      const responses = await promise;
+      assert.deepStrictEqual(responses, expectedResponse);
+      assert(
+        (client.descriptors.page.listDeviceRegistries.createStream as SinonStub)
+          .getCall(0)
+          .calledWith(client.innerApiCalls.listDeviceRegistries, request)
+      );
+      assert.strictEqual(
+        (
+          client.descriptors.page.listDeviceRegistries.createStream as SinonStub
+        ).getCall(0).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+
+    it('invokes listDeviceRegistriesStream with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceRegistriesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedError = new Error('expected');
+      client.descriptors.page.listDeviceRegistries.createStream =
+        stubPageStreamingCall(undefined, expectedError);
+      const stream = client.listDeviceRegistriesStream(request);
+      const promise = new Promise((resolve, reject) => {
+        const responses: protos.google.cloud.iot.v1.DeviceRegistry[] = [];
+        stream.on(
+          'data',
+          (response: protos.google.cloud.iot.v1.DeviceRegistry) => {
+            responses.push(response);
+          }
+        );
+        stream.on('end', () => {
+          resolve(responses);
+        });
+        stream.on('error', (err: Error) => {
+          reject(err);
+        });
+      });
+      await assert.rejects(promise, expectedError);
+      assert(
+        (client.descriptors.page.listDeviceRegistries.createStream as SinonStub)
+          .getCall(0)
+          .calledWith(client.innerApiCalls.listDeviceRegistries, request)
+      );
+      assert.strictEqual(
+        (
+          client.descriptors.page.listDeviceRegistries.createStream as SinonStub
+        ).getCall(0).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+
+    it('uses async iteration with listDeviceRegistries without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceRegistriesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.DeviceRegistry()),
+      ];
+      client.descriptors.page.listDeviceRegistries.asyncIterate =
+        stubAsyncIterationCall(expectedResponse);
+      const responses: protos.google.cloud.iot.v1.IDeviceRegistry[] = [];
+      const iterable = client.listDeviceRegistriesAsync(request);
+      for await (const resource of iterable) {
+        responses.push(resource!);
+      }
+      assert.deepStrictEqual(responses, expectedResponse);
+      assert.deepStrictEqual(
+        (
+          client.descriptors.page.listDeviceRegistries.asyncIterate as SinonStub
+        ).getCall(0).args[1],
+        request
+      );
+      assert.strictEqual(
+        (
+          client.descriptors.page.listDeviceRegistries.asyncIterate as SinonStub
+        ).getCall(0).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+
+    it('uses async iteration with listDeviceRegistries with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDeviceRegistriesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedError = new Error('expected');
+      client.descriptors.page.listDeviceRegistries.asyncIterate =
+        stubAsyncIterationCall(undefined, expectedError);
+      const iterable = client.listDeviceRegistriesAsync(request);
+      await assert.rejects(async () => {
+        const responses: protos.google.cloud.iot.v1.IDeviceRegistry[] = [];
+        for await (const resource of iterable) {
+          responses.push(resource!);
+        }
+      });
+      assert.deepStrictEqual(
+        (
+          client.descriptors.page.listDeviceRegistries.asyncIterate as SinonStub
+        ).getCall(0).args[1],
+        request
+      );
+      assert.strictEqual(
+        (
+          client.descriptors.page.listDeviceRegistries.asyncIterate as SinonStub
+        ).getCall(0).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+  });
+
+  describe('listDevices', () => {
+    it('invokes listDevices without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDevicesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+      ];
+      client.innerApiCalls.listDevices = stubSimpleCall(expectedResponse);
+      const [response] = await client.listDevices(request);
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDevices as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDevices without error using callback', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDevicesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+      ];
+      client.innerApiCalls.listDevices =
+        stubSimpleCallWithCallback(expectedResponse);
+      const promise = new Promise((resolve, reject) => {
+        client.listDevices(
+          request,
+          (
+            err?: Error | null,
+            result?: protos.google.cloud.iot.v1.IDevice[] | null
+          ) => {
+            if (err) {
+              reject(err);
+            } else {
+              resolve(result);
+            }
+          }
+        );
+      });
+      const response = await promise;
+      assert.deepStrictEqual(response, expectedResponse);
+      assert(
+        (client.innerApiCalls.listDevices as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions /*, callback defined above */)
+      );
+    });
+
+    it('invokes listDevices with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDevicesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedOptions = {
+        otherArgs: {
+          headers: {
+            'x-goog-request-params': expectedHeaderRequestParams,
+          },
+        },
+      };
+      const expectedError = new Error('expected');
+      client.innerApiCalls.listDevices = stubSimpleCall(
+        undefined,
+        expectedError
+      );
+      await assert.rejects(client.listDevices(request), expectedError);
+      assert(
+        (client.innerApiCalls.listDevices as SinonStub)
+          .getCall(0)
+          .calledWith(request, expectedOptions, undefined)
+      );
+    });
+
+    it('invokes listDevicesStream without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDevicesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+      ];
+      client.descriptors.page.listDevices.createStream =
+        stubPageStreamingCall(expectedResponse);
+      const stream = client.listDevicesStream(request);
+      const promise = new Promise((resolve, reject) => {
+        const responses: protos.google.cloud.iot.v1.Device[] = [];
+        stream.on('data', (response: protos.google.cloud.iot.v1.Device) => {
+          responses.push(response);
+        });
+        stream.on('end', () => {
+          resolve(responses);
+        });
+        stream.on('error', (err: Error) => {
+          reject(err);
+        });
+      });
+      const responses = await promise;
+      assert.deepStrictEqual(responses, expectedResponse);
+      assert(
+        (client.descriptors.page.listDevices.createStream as SinonStub)
+          .getCall(0)
+          .calledWith(client.innerApiCalls.listDevices, request)
+      );
+      assert.strictEqual(
+        (client.descriptors.page.listDevices.createStream as SinonStub).getCall(
+          0
+        ).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+
+    it('invokes listDevicesStream with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDevicesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedError = new Error('expected');
+      client.descriptors.page.listDevices.createStream = stubPageStreamingCall(
+        undefined,
+        expectedError
+      );
+      const stream = client.listDevicesStream(request);
+      const promise = new Promise((resolve, reject) => {
+        const responses: protos.google.cloud.iot.v1.Device[] = [];
+        stream.on('data', (response: protos.google.cloud.iot.v1.Device) => {
+          responses.push(response);
+        });
+        stream.on('end', () => {
+          resolve(responses);
+        });
+        stream.on('error', (err: Error) => {
+          reject(err);
+        });
+      });
+      await assert.rejects(promise, expectedError);
+      assert(
+        (client.descriptors.page.listDevices.createStream as SinonStub)
+          .getCall(0)
+          .calledWith(client.innerApiCalls.listDevices, request)
+      );
+      assert.strictEqual(
+        (client.descriptors.page.listDevices.createStream as SinonStub).getCall(
+          0
+        ).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+
+    it('uses async iteration with listDevices without error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDevicesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedResponse = [
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+        generateSampleMessage(new protos.google.cloud.iot.v1.Device()),
+      ];
+      client.descriptors.page.listDevices.asyncIterate =
+        stubAsyncIterationCall(expectedResponse);
+      const responses: protos.google.cloud.iot.v1.IDevice[] = [];
+      const iterable = client.listDevicesAsync(request);
+      for await (const resource of iterable) {
+        responses.push(resource!);
+      }
+      assert.deepStrictEqual(responses, expectedResponse);
+      assert.deepStrictEqual(
+        (client.descriptors.page.listDevices.asyncIterate as SinonStub).getCall(
+          0
+        ).args[1],
+        request
+      );
+      assert.strictEqual(
+        (client.descriptors.page.listDevices.asyncIterate as SinonStub).getCall(
+          0
+        ).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+
+    it('uses async iteration with listDevices with error', async () => {
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      const request = generateSampleMessage(
+        new protos.google.cloud.iot.v1.ListDevicesRequest()
+      );
+      request.parent = '';
+      const expectedHeaderRequestParams = 'parent=';
+      const expectedError = new Error('expected');
+      client.descriptors.page.listDevices.asyncIterate = stubAsyncIterationCall(
+        undefined,
+        expectedError
+      );
+      const iterable = client.listDevicesAsync(request);
+      await assert.rejects(async () => {
+        const responses: protos.google.cloud.iot.v1.IDevice[] = [];
+        for await (const resource of iterable) {
+          responses.push(resource!);
+        }
+      });
+      assert.deepStrictEqual(
+        (client.descriptors.page.listDevices.asyncIterate as SinonStub).getCall(
+          0
+        ).args[1],
+        request
+      );
+      assert.strictEqual(
+        (client.descriptors.page.listDevices.asyncIterate as SinonStub).getCall(
+          0
+        ).args[2].otherArgs.headers['x-goog-request-params'],
+        expectedHeaderRequestParams
+      );
+    });
+  });
+
+  describe('Path templates', () => {
+    describe('device', () => {
+      const fakePath = '/rendered/path/device';
+      const expectedParameters = {
+        project: 'projectValue',
+        location: 'locationValue',
+        registry: 'registryValue',
+        device: 'deviceValue',
+      };
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      client.pathTemplates.devicePathTemplate.render = sinon
+        .stub()
+        .returns(fakePath);
+      client.pathTemplates.devicePathTemplate.match = sinon
+        .stub()
+        .returns(expectedParameters);
+
+      it('devicePath', () => {
+        const result = client.devicePath(
+          'projectValue',
+          'locationValue',
+          'registryValue',
+          'deviceValue'
+        );
+        assert.strictEqual(result, fakePath);
+        assert(
+          (client.pathTemplates.devicePathTemplate.render as SinonStub)
+            .getCall(-1)
+            .calledWith(expectedParameters)
+        );
+      });
+
+      it('matchProjectFromDeviceName', () => {
+        const result = client.matchProjectFromDeviceName(fakePath);
+        assert.strictEqual(result, 'projectValue');
+        assert(
+          (client.pathTemplates.devicePathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+
+      it('matchLocationFromDeviceName', () => {
+        const result = client.matchLocationFromDeviceName(fakePath);
+        assert.strictEqual(result, 'locationValue');
+        assert(
+          (client.pathTemplates.devicePathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+
+      it('matchRegistryFromDeviceName', () => {
+        const result = client.matchRegistryFromDeviceName(fakePath);
+        assert.strictEqual(result, 'registryValue');
+        assert(
+          (client.pathTemplates.devicePathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+
+      it('matchDeviceFromDeviceName', () => {
+        const result = client.matchDeviceFromDeviceName(fakePath);
+        assert.strictEqual(result, 'deviceValue');
+        assert(
+          (client.pathTemplates.devicePathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+    });
+
+    describe('location', () => {
+      const fakePath = '/rendered/path/location';
+      const expectedParameters = {
+        project: 'projectValue',
+        location: 'locationValue',
+      };
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      client.pathTemplates.locationPathTemplate.render = sinon
+        .stub()
+        .returns(fakePath);
+      client.pathTemplates.locationPathTemplate.match = sinon
+        .stub()
+        .returns(expectedParameters);
+
+      it('locationPath', () => {
+        const result = client.locationPath('projectValue', 'locationValue');
+        assert.strictEqual(result, fakePath);
+        assert(
+          (client.pathTemplates.locationPathTemplate.render as SinonStub)
+            .getCall(-1)
+            .calledWith(expectedParameters)
+        );
+      });
+
+      it('matchProjectFromLocationName', () => {
+        const result = client.matchProjectFromLocationName(fakePath);
+        assert.strictEqual(result, 'projectValue');
+        assert(
+          (client.pathTemplates.locationPathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+
+      it('matchLocationFromLocationName', () => {
+        const result = client.matchLocationFromLocationName(fakePath);
+        assert.strictEqual(result, 'locationValue');
+        assert(
+          (client.pathTemplates.locationPathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+    });
+
+    describe('registry', () => {
+      const fakePath = '/rendered/path/registry';
+      const expectedParameters = {
+        project: 'projectValue',
+        location: 'locationValue',
+        registry: 'registryValue',
+      };
+      const client = new devicemanagerModule.v1.DeviceManagerClient({
+        credentials: {client_email: 'bogus', private_key: 'bogus'},
+        projectId: 'bogus',
+      });
+      client.initialize();
+      client.pathTemplates.registryPathTemplate.render = sinon
+        .stub()
+        .returns(fakePath);
+      client.pathTemplates.registryPathTemplate.match = sinon
+        .stub()
+        .returns(expectedParameters);
+
+      it('registryPath', () => {
+        const result = client.registryPath(
+          'projectValue',
+          'locationValue',
+          'registryValue'
+        );
+        assert.strictEqual(result, fakePath);
+        assert(
+          (client.pathTemplates.registryPathTemplate.render as SinonStub)
+            .getCall(-1)
+            .calledWith(expectedParameters)
+        );
+      });
+
+      it('matchProjectFromRegistryName', () => {
+        const result = client.matchProjectFromRegistryName(fakePath);
+        assert.strictEqual(result, 'projectValue');
+        assert(
+          (client.pathTemplates.registryPathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+
+      it('matchLocationFromRegistryName', () => {
+        const result = client.matchLocationFromRegistryName(fakePath);
+        assert.strictEqual(result, 'locationValue');
+        assert(
+          (client.pathTemplates.registryPathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+
+      it('matchRegistryFromRegistryName', () => {
+        const result = client.matchRegistryFromRegistryName(fakePath);
+        assert.strictEqual(result, 'registryValue');
+        assert(
+          (client.pathTemplates.registryPathTemplate.match as SinonStub)
+            .getCall(-1)
+            .calledWith(fakePath)
+        );
+      });
+    });
+  });
+});
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..c78f1c884ef69bad46c8c690ef5d3798e7385190
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,19 @@
+{
+  "extends": "./node_modules/gts/tsconfig-google.json",
+  "compilerOptions": {
+    "rootDir": ".",
+    "outDir": "build",
+    "resolveJsonModule": true,
+    "lib": [
+      "es2018",
+      "dom"
+    ]
+  },
+  "include": [
+    "src/*.ts",
+    "src/**/*.ts",
+    "test/*.ts",
+    "test/**/*.ts",
+    "system-test/*.ts"
+  ]
+}
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..ff027648874ff03cd576b8fc0d137f3c7d9d9b83
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,64 @@
+// Copyright 2021 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
+//
+//     https://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.
+
+const path = require('path');
+
+module.exports = {
+  entry: './src/index.ts',
+  output: {
+    library: 'iot',
+    filename: './iot.js',
+  },
+  node: {
+    child_process: 'empty',
+    fs: 'empty',
+    crypto: 'empty',
+  },
+  resolve: {
+    alias: {
+      '../../../package.json': path.resolve(__dirname, 'package.json'),
+    },
+    extensions: ['.js', '.json', '.ts'],
+  },
+  module: {
+    rules: [
+      {
+        test: /\.tsx?$/,
+        use: 'ts-loader',
+        exclude: /node_modules/,
+      },
+      {
+        test: /node_modules[\\/]@grpc[\\/]grpc-js/,
+        use: 'null-loader',
+      },
+      {
+        test: /node_modules[\\/]grpc/,
+        use: 'null-loader',
+      },
+      {
+        test: /node_modules[\\/]retry-request/,
+        use: 'null-loader',
+      },
+      {
+        test: /node_modules[\\/]https?-proxy-agent/,
+        use: 'null-loader',
+      },
+      {
+        test: /node_modules[\\/]gtoken/,
+        use: 'null-loader',
+      },
+    ],
+  },
+  mode: 'production',
+};