如何使用 c# 在谷歌云注册表中添加设备? 更新 2020-12-31

问题描述

enter image description here

你好想问一下如何使用谷歌云物联网核心和C#在谷歌云注册表中添加设备

我已经尝试了谷歌控制台上提供的以下代码,用于将设备添加注册表但出现错误 “Google.Apis.Requests.Request 错误调用没有权限 [403]”

public static CloudiotService CreateAuthorizedClient()
{
    

GoogleCredential credential =
            GoogleCredential.GetApplicationDefaultAsync().Result;
        // Inject the Cloud IoT Core Service scope
        if (credential.IsCreateScopedrequired)
        {
            credential = credential.CreateScoped(new[]
            {
                CloudiotService.Scope.Cloudplatform // Used for IoT + PubSub + IAM
                //CloudiotService.Scope.Cloudiot // Can be used if not accessing Pub/Sub
            });
        }
        return new CloudiotService(new BaseClientService.Initializer
        {
            HttpClientinitializer = credential,GZipEnabled = false
        });
    }

public static object CreateRsaDevice(string projectId,string cloudRegion,string registryId,string deviceid,string keyPath)
    {
        keyPath = @"E:\Downloads\thermostat-289211-bb93742bc12f.json";
        projectId= "thermostat - 289211";
        cloudRegion = "us-central1";
        registryId = "testregistry";
        deviceid = "C418B9962BC91";
        var cloudiot = CreateAuthorizedClient();
        var parent = $"projects/{projectId}/locations/{cloudRegion}/registries/{registryId}";

        try
        {
            //var credentials = GoogleCredential.FromFile(keyPath);
            //String keyText = File.ReadAllText(keyPath);
            Device body = new Device()
            {
                Id = deviceid
            };
            body.Credentials = new List<DeviceCredential>();
            body.Credentials.Add(new DeviceCredential()
            {
                PublicKey = new PublicKeyCredential()
                {
                    Key = "here i am entering my public key",Format = "RSA_X509_PEM"
                },});

            var device = cloudiot.Projects.Locations.Registries.Devices.Create(body,parent).Execute();
            Console.WriteLine("Device created: ");
            Console.WriteLine($"{device.Id}");
            Console.WriteLine($"\tBlocked: {device.Blocked == true}");
            Console.WriteLine($"\tConfig version: {device.Config.Version}");
            Console.WriteLine($"\tName: {device.Name}");
            Console.WriteLine($"\tState:{device.State}");
        }
        catch (Google.GoogleApiException e)
        {
            Console.WriteLine(e.Message);
            if (e.Error != null) return e.Error.Code;
            return -1;
        }
        return 0;
    }

在我是管理员页面上用黄色突出显示的角色图片是我正在使用的当前帐户

解决方法

见:https://cloud.google.com/iot/docs/samples/device-manager-samples#iot-core-create-rs256-csharp

QUESTION="65413853"
PROJECT="dazwilkin-$(date +%y%m%d)-${QUESTION}"
REGION="us-central1"
REGISTRY="test"

BILLING=$(\
  gcloud alpha billing accounts list \
  --format="value(name)")

gcloud projects create ${PROJECT}
gcloud beta billing projects link ${PROJECT} \
--billing-account=${BILLING}

# Enable Cloud IOT
gcloud services enable cloudiot.googleapis.com \
--project=${PROJECT}

# Create Registry
gcloud iot registries create ${REGISTRY} \
--region=${REGION} \
--project=${PROJECT}

# Create Service Account with permissions for IoT
ROBOT="dellian"
EMAIL="${ROBOT}@${PROJECT}.iam.gserviceaccount.com"

gcloud iam service-accounts create ${ROBOT} \
--project=${PROJECT}

gcloud iam service-accounts keys create ./${ROBOT}.json \
--iam-account=${EMAIL}

gcloud projects add-iam-policy-binding ${PROJECT} \
--member=serviceAccount:${EMAIL} \
--role=roles/cloudiot.provisioner

# Create RSA key
openssl req -x509 -nodes \
-newkey rsa:2048 \
-keyout rsa_private.pem \
-out rsa_cert.pem \
-subj /CN=cloudiot

docker run \
--interactive --tty \
--env=PROJECT=${PROJECT} \
--env=REGION=${REGION} \
--env=REGISTRY=${REGISTRY} \
--volume=${PWD}/app:/app \
--volume=${PWD}/${ROBOT}.json:/secrets/${ROBOT}.json \
--env=GOOGLE_APPLICATION_CREDENTIALS=/secrets/${ROBOT}.json \
--workdir=/app mcr.microsoft.com/dotnet/sdk:5.0 bash

那么:

使用app.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Google.Apis.Auth" Version="1.49.0" />
    <PackageReference Include="Google.Apis.CloudIot.v1" Version="1.49.0.2161" />
  </ItemGroup>

</Project>

和:

using Google.Apis.Auth.OAuth2;
using Google.Apis.CloudIot.v1;
using Google.Apis.CloudIot.v1.Data;
using Google.Apis.Services;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace IoTSample
{
    public class IoTExample
    {
        public static void Main(string[] args){

            string projectId = Environment.GetEnvironmentVariable("PROJECT");
            string region = Environment.GetEnvironmentVariable("REGION");
            string registryId = Environment.GetEnvironmentVariable("REGISTRY");
            string deviceId = Environment.GetEnvironmentVariable("DEVICE");
            string keyPath = Environment.GetEnvironmentVariable("KEY");

            GoogleCredential credential = GoogleCredential.GetApplicationDefaultAsync().Result;
            if (credential.IsCreateScopedRequired) {
                credential = credential.CreateScoped(new[]{
                    CloudIotService.Scope.CloudPlatform // Used for IoT + PubSub + IAM
                    //CloudIotService.Scope.Cloudiot // Can be used if not accessing Pub/Sub
                });
            }
            CloudIotService service = new CloudIotService(new BaseClientService.Initializer{
                HttpClientInitializer = credential,GZipEnabled = false
            });

            var parent = $"projects/{projectId}/locations/{region}/registries/{registryId}";
            var keyText = File.ReadAllText(keyPath);

            try
            {
                Device body = new Device()
                {
                    Id = deviceId
                };
                body.Credentials = new List<DeviceCredential>();
                body.Credentials.Add(new DeviceCredential()
                {
                    PublicKey = new PublicKeyCredential()
                    {
                        Key = keyText,Format = "RSA_X509_PEM"
                    },});

                var device = service.Projects.Locations.Registries.Devices.Create(body,parent).Execute();
                Console.WriteLine("Device created: ");
                Console.WriteLine($"{device.Id}");
                Console.WriteLine($"\tBlocked: {device.Blocked == true}");
                Console.WriteLine($"\tConfig version: {device.Config.Version}");
                Console.WriteLine($"\tName: {device.Name}");
                Console.WriteLine($"\tState:{device.State}");
            }
            catch (Google.GoogleApiException e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

您的 Cloud IoT 注册表(在本例中为 test)必须存在于项目中。

见:https://cloud.google.com/iot/docs/how-tos/credentials/keys#generating_an_rsa_key_with_a_self-signed_x509_certificate

export DEVICE="device-01"
export KEY="rsa_cert.pem"

dotnet run

产量:

Device created: 
test
    Blocked: False
    Config version: 1
    Name: projects/.../devices/2553842783141685
    State:

和:

gcloud iot devices list \
--registry=test \
--region=us-central1 \
--project=${PROJECT}

ID     NUM_ID            BLOCKED
test   2553842783141685

更新 2020-12-31

您也可以使用命令行创建设备。这将是一个有用的测试,可确保您已正确配置所有内容:

DEVICE="test-02"
KEY="${PWD}/app/rsa_cert.pem"

gcloud iot devices create ${DEVICE} \
--registry=${REGISTRY} \
--public-key=path=${KEY},type=RSA-X509-PEM \
--region=${REGION} \
--project=${PROJECT}

应该屈服:

Created device [${DEVICE}].