首页 > 解决方案 > @google-cloud/iot API 有真实的文档吗?

问题描述

JavaScript 模块“@google-cloud/iot”似乎与此处的文档(https://googleapis.dev/nodejs/iot/latest/index.html)不太相似。

例如,该函数client.sendCommandToDevice()被记录为返回类型SendCommandToDeviceResponse,而它实际上返回接口和未定义的复杂交集。我可以在模块内的命名空间嵌套中找到正确的类型,但即使这样我也无法从结果中获取我需要的数据。例如,...Response 类型有一个静态函数“toJSON()”,它接受一个响应并返回 JSON——但它不会接受实际的响应对象,我找不到任何方法来转换实际的响应对象响应对象转换为预期类型。

这不是唯一的此类错误。这可能是在没有检查它是否真的可以在 TypeScript 中使用的情况下将旧的 JavaScript API 过度仓促转换为 TypeScript 的产物吗?是否有一些关于旧 JavaScript API 的文档可供我比较?

这是一个代码片段(在编译之前):

// node 14.17.3, TypeScript 4.4.4, iot 2.5.1

import iot from "@google-cloud/iot";
// Yes, I did the credentials thing...
const client = new iot.v1.DeviceManagerClient();

function generateRequest(id: string, data: any) {
    const formattedName = client.devicePath("myproject", "us-central1", "myregistry", id);
    const binData = Buffer.from(JSON.stringify(data)).toString("base64");

    return {
        ok: true,
        name: formattedName,
        binData: binData,
    };
}

async function run() {
    const project = await client.getProjectId();
    const parent = client.locationPath(project, 'us-central1');

    const deviceId = "d99999995";
    const data = { get: [ "program" ] };
    const request = generateRequest(deviceId, data);

    let r = await client.sendCommandToDevice(request);
    // what is r here???

    /* Same issue with, e.g.:
    client.updateDevice();
    client.modifyCloudToDeviceConfig()
    */
    return {
        ok: true,
        result: r,
    };
}

run().catch((err) => { console.error(err); });

标签: node.jstypescriptgoogle-cloud-platformgoogle-apigoogle-cloud-iot

解决方案


即时反馈:您对评论者的回复表明您明显感到沮丧。我认为可以合理地假设人们不会花时间回答你的问题来让你感到沮丧。我不愿回复,不想也被责备,但我想像他们一样尝试帮助你......

该库的文档看起来是正确的,但我既不是 TypeScript 也不是 JavaScript 大师。我非常熟悉 GCP 及其服务和编写客户端代码。

谷歌一直在改进其服务,以反映其内部对 gRPC 的广泛使用。在我看来,这种向更多 gRPC 原生服务的转变正在渗入其 SDK(即 protobuf 消息的优势),我发现这很令人困惑,特别是因为我还没有看到它完全解释。

在方法的情况下,@google-cloud/iot请参考 protobuf 消息。所以,你的sendCommandToDevice方法有一个签名,它接受 aSendCommandToDeviceRequest并返回一个 Promised SendCommandToDeviceResponse

正如我所说,我不熟悉 TypeScript,但是在 JavaScript(原文如此)中,我想知道您是否必须使用SendCommandToDeviceRequest构造函数来创建请求:

function generateRequest(id, data) {
    const formattedName = client.devicePath("myproject", "us-central1", "myregistry", id);
    const binaryData = Buffer.from(JSON.stringify(data)).toString("base64");

    return {
        name: formattedName,
        binaryData: binaryData,
    };
}

const rqst = new iot.protos.google.cloud.iot.v1.SendCommandToDeviceRequest(
  generateRequest(deviceId, data)
);

注意该属性binaryData不是binData

然后,因为它是await'ed,我认为您的响应类型将是SendCommandToDeviceResponse

const resp = await client.sendCommandToDevice(rqst);

@Ash_max 在评论中引用了这种类型。虽然构造函数列在页面顶部,但页面下方是toJSON(). 所以你应该能够:

console.log(`response: ${resp.toJSON()}`);

也许JSON.stringify(resp.toJSON())

我今天没有时间尝试这个,但明天我会尝试重现您的体验并更新此线程。

更新

我创建了一个 GCP 项目、注册表和设备。

我运行了上面列出的 Node.JS 代码,返回类型令人困惑;我得到了一个包含 3 个对象的数组,其中第一个看起来是 proto 但不支持toJSON,我也无法得到它toString()

因此,我查看了APIs Explorer并根据它sendCommandToDevice(我认为这是确定的),成功时响应正文将为空。

迷茫中,我写了一个等价的 Golang 程序:

package main

import (
    "context"
    b64 "encoding/base64"
    "fmt"
    "log"
    "os"

    "google.golang.org/api/cloudiot/v1"
)

func main() {
    ctx := context.Background()
    client, err := cloudiot.NewService(ctx)
    if err != nil {
        log.Fatal(err)
    }

    rqst := &cloudiot.SendCommandToDeviceRequest{
        BinaryData: b64.StdEncoding.EncodeToString([]byte("Hello Freddie")),
    }

    name := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s",
        os.Getenv("PROJECT"),
        os.Getenv("REGION"),
        os.Getenv("REGISTRY"),
        os.Getenv("DEVICE"),
    )

    devices := client.Projects.Locations.Registries.Devices
    resp, err := devices.SendCommandToDevice(name, rqst).Do()
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("%+v", resp)
}

resp肯定是类型SendCommandToDeviceResponse,并且包含ServerResponse其中包括HTTPStatusCode

&{
  ServerResponse:{
    HTTPStatusCode:200
    Header:map[
      Cache-Control:[private]
      Content-Type:[application/json; charset=UTF-8]
      Date:[Wed, 20 Oct 2021 00:20:00 GMT]
      Server:[ESF] Vary:[Origin X-Origin Referer]
      X-Content-Type-Options:[nosniff]
      X-Frame-Options:[SAMEORIGIN]
      X-Xss-Protection:[0]
    ]
  }
}

因此,JavaScript(Node.JS|TypeScript)代码应该以某种方式(!)也能够ServerResponseSendCommandToDeviceResponse.

该文档似乎是正确的。


推荐阅读