Firebase 更新物联网设备配置时出现谷歌云功能错误(权限被拒绝)

Firebase 更新物联网设备配置时出现谷歌云功能错误(权限被拒绝),firebase,google-cloud-firestore,google-cloud-functions,Firebase,Google Cloud Firestore,Google Cloud Functions,所以,我需要做的基本上是,当我在Google Cloud Firestore中更改一个值时,它会触发一个云函数将该值发送到IoT设备。以下是我所做的: 我为此特定任务创建了一个服务帐户。我授予它以下权限: cloudiot.admin(用于管理谷歌云物联网设备) firebase.sdkAdminServiceAgent(用于管理Firestore) 所有者(临时所有者,用于调试) 我创建了一个物联网设备注册表,并在此注册表上创建了一个设备 创建了云函数,并将其服务帐户设置为我创建的帐户 以下

所以,我需要做的基本上是,当我在Google Cloud Firestore中更改一个值时,它会触发一个云函数将该值发送到IoT设备。以下是我所做的:

  • 我为此特定任务创建了一个服务帐户。我授予它以下权限:
  • cloudiot.admin(用于管理谷歌云物联网设备)
  • firebase.sdkAdminServiceAgent(用于管理Firestore)
  • 所有者(临时所有者,用于调试)
  • 我创建了一个物联网设备注册表,并在此注册表上创建了一个设备
  • 创建了云函数,并将其服务帐户设置为我创建的帐户
  • 以下是云函数的代码:

    const functions=require(“firebase函数”);
    const admin=require(“firebase管理员”);
    const-iot=require(“@google-cloud/iot”);
    const app=admin.initializeApp();
    const firestore=app.firestore();
    const client=new iot.v1.DeviceManager客户端();
    设置({timestampsInSnapshots:true});
    exports.deviceConfigs=functions.firestore
    .document(“设备配置/{device}”)
    .onWrite(异步(更改、上下文)=>{
    const deviceId=context.params.device;
    如果(!change.after.存在){
    functions.logger.error(`deviceconfigurationremovedfor${deviceId}`);
    返回;
    }
    const config=change.after.data();
    const formattedName=client.devicePath(
    process.env.GCLOUD_项目,
    functions.config().iot.core.region,
    functions.config().iot.core.registry,
    设备ID
    );
    常量请求={
    名称:formattedName,
    binaryData:Buffer.from(JSON.stringify(config)).toString(“base64”),
    };  
    等待client.modifyCloudToDeviceConfig(请求);
    });
    
    因此,每当我在集合“device configs”中的文档上写入时,就会触发该功能,并向IoT设备发送授权请求,通知配置更改。它是经过身份验证的,因为它直接从google后端运行,因为它是一个云功能,所以它应该作为我创建的服务帐户进行身份验证

    但是,每次触发时,它都会在最后一行失败。以下是错误:

    错误:7权限被拒绝:调用者在Object.onReceiveStatus(/workspace/node_modules/@grpc/grpc js/build/src/call.js:31:26)的Object.callerRomStatus(/workspace/node_modules/@grpc/grpc js/build/src/client.js:176:52)处没有权限(/workspace/node_modules/@grpc/grpc js/build/src/client interceptors.js:336:141)at Object.onReceiveStatus(/workspace/node_modules/@grpc/grpc js/build/src/client interceptors.js:299:181)at/workspace/node_modules/@grpc/grpc js/build/src/call stream.js:145:78 at process和拒绝(内部/进程/任务队列:79:11)

    我真的不知道该怎么办了。我曾尝试在模拟器上本地运行它,使用服务密钥作为身份验证,但它仍然返回相同的错误。我试图找到一种方法来记录Google Cloud接收到的所有api请求,以查看头上是否存在身份验证,但我找不到这样做的方法

    编辑 好的,我不知道这是否有帮助,但我还有另一个云功能,可以侦听PubSub主题上的新消息,并相应地更新Firestore数据库。该功能工作正常。代码如下:

    const functions=require(“firebase函数”);
    const admin=require(“firebase管理员”);
    const-iot=require(“@google-cloud/iot”);
    const app=admin.initializeApp();
    const firestore=app.firestore();
    const client=new iot.v1.DeviceManager客户端();
    设置({timestampsInSnapshots:true});
    exports.deviceState=functions.pubsub
    .主题(“设备事件”)
    .onPublish(异步(消息)=>{
    functions.logger.warn(“mensage:,{message});
    const deviceId=message.attributes.deviceId;
    const deviceRef=firestore.doc(`device state/${deviceId}`);
    试一试{
    等待设备更新({
    状态:message.json,
    在线:没错,
    });
    functions.logger.log(“设备更新成功”);
    }捕获(错误){
    函数.logger.error(错误);
    }
    });
    
    const-app=admin.initializeApp()

    将此更改为

    const serviceAccount = require("./serviceAccountKey.json");
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://YOURPROJECTNAME.firebaseio.com"
    });
    
    从firebase下载ServiceAccountKey并将其添加到该文件所在的同一文件夹中,然后添加数据库url

    确定,找到解决方案!
    基本上,请确保三四次检查项目和注册表名称!逐个字符检查。这件事花了我尴尬的4天时间才解决。

    谢谢Tasnuva。因为我没有使用实时数据库,所以我没有指定数据库URL。它返回了相同的错误在firebase帐户中创建firestore DB并添加您的项目t name确保firebase帐户中的firestore规则是读写真实的相同错误。我认为问题不在于firestore,因为我可以在数据库上很好地读写。我认为问题在于云功能和物联网核心之间。你是否从云启用谷歌云计算?你有默认的服务帐户吗?很好