为什么我的树莓PI不能连接到谷歌云物联网? [英] Why won't my Raspberry Pi connect to Google Cloud IoT?

本文介绍了为什么我的树莓PI不能连接到谷歌云物联网?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将rsa_private.pem添加到项目的certs目录中,并在IOT核心控制台中将相应的rsa_cert.pem公钥添加到我的设备。

我还从certs目录中运行了wget https://pki.google.com/roots.pem

我不明白的是,现在生成的roots.pem文件有多个-

----BEGIN CERTIFICATE-----
// RS256_X509 encoded cert here
-----END CERTIFICATE-----

包含各种Operating CA:Comodo GroupGoDaddyDigiCertEntrust DatacardGlobalSignGoogle Trust Services LLC,这是我第一次生成原始root.pem时的内容。

我尝试将root.pem添加到控制台中CA CERTIFICATES下的my-registry,但出现错误,显示Certificate value is too big `

当我运行node gcloud.js时,如果我在传递给mqtt.connect()connectionArgs中包含protocolId: 'MQIsdp',则我会在终端中得到connecting...后跟多个closeping,或者如果我省略它,我会得到Error: Connection refused: Not authorized

gcloud.js

const fs = require('fs')
const jwt = require('jsonwebtoken')
const mqtt = require('mqtt')
const exec = require('child_process').exec

const projectId = 'my-project'
const cloudRegion = 'us-central1'
const registryId = 'my-registry'
const mqttHost = 'mqtt.googleapis.com'
const mqttPort = 8883
const privateKeyFile = './certs/rsa_private.pem'
const algorithm = 'RS256'
var messageType = 'events'// or event

function createJwt (projectId, privateKeyFile, algorithm) {
  var token = {
    iat: parseInt(Date.now() / 1000),
    exp: parseInt(Date.now() / 1000) + 86400 * 60, // 1 day
    aud: projectId
  }
  const privateKey = fs.readFileSync(privateKeyFile)
  return jwt.sign(token, privateKey, {
    algorithm: algorithm
  })
}

function fetchData () {}
async function configureDevice () { 
  // Get the device's serial number
  await exec('cat /proc/cpuinfo | grep Serial', (error, stdout, stderr) => {
    if (error) {
      console.error(`exec error: ${error}`)
      return
    }
    // Concat serial number w/ project name to meet device id naming requirement starting w/ a letter 
    const deviceId = `my-project${stdout.split(' ')[1].split('
')[0]}` 
    var mqttClientId = 'projects/' + projectId + '/locations/' + cloudRegion + '/registries/' + registryId + '/devices/' + deviceId
    var mqttTopic = '/devices/' + deviceId + '/' + messageType
    var connectionArgs = {
      // protocolId: 'MQIsdp' if I add this property I see "connecting..." get logged in the console 
      // followed by "close" repeatedly being logged. If I don't add it I get
      // "Error: Connection refused: Not authorized" 
      host: mqttHost,
      port: mqttPort,
      clientId: mqttClientId,
      username: 'unused',
      password: createJwt(projectId, privateKeyFile, algorithm),
      protocol: 'mqtts',
      secureProtocol: 'TLSv1_2_method'
    }
    console.log('connecting...')
    var client = mqtt.connect(connectionArgs)
    // Subscribe to the /devices/{device-id}/config topic to receive config updates.
    client.subscribe('/devices/' + deviceId + '/config')

    client.on('connect', function (success) {
      if (success) {
        console.log('Client connected...')
        sendData()
      } else {
        console.log('Client not connected...')
      }
    })

    client.on('close', function () {
      debugger
      console.log('close')
    })
     client.on('error', function (err) {
      debugger
      console.log('error', err)
    })

    client.on('message', function (topic, message, packet) {
      console.log(topic, 'message received: ', Buffer.from(message, 'base64').toString('ascii'))
    })

    function sendData () {
      var payload = fetchData()

      payload = JSON.stringify(payload)
      console.log(mqttTopic, ': Publishing message:', payload)
      client.publish(mqttTopic, payload, { qos: 1 })

      console.log('Transmitting in 30 seconds')
      setTimeout(sendData, 30000)
    }
  })
}

configureDevice()

推荐答案

所以首先,只需注意roots.pem。这里有多个证书,因为如果/当Google轮换授权证书时,roots.pem会覆盖自己。因此,它包括一组允许roots.pem更长时间有效的包,仅此而已。如果您能识别哪个是活动证书(它可能每三个月或四个月更改一次?)您实际上可以删除所有其他证书,只保留一个活动证书。我不得不这样做了一段时间,当我在一个严重受限的MC上工作时,上面只有200K的空间。roots.pem太大了,占用了我在设备上的大部分存储空间。此处有更多信息:https://cloud.google.com/iot/docs/how-tos/mqtt-bridge#using_a_long-term_mqtt_domain有关我们设置的长期域,以便能够对长期域使用较小的根证书。

而且您不想/不需要将roots.pem添加到注册表级证书中,因为只有当您希望使用自己的证书颁发机构针对正在注册的新设备进行验证时才需要这样做。这有点令人困惑,但它与设备注册后的授权无关,而是要防止有人入侵您的项目并注册他们自己的设备。

至于代码不起作用的原因:您的JWT是无效的,因为您的过期标记是:exp: parseInt(Date.now() / 1000) + 86400 * 60, // 1 day,它的长度超过了JWT的有效长度。86400秒*60等于1,440小时.超过24小时的JWT将被拒绝。所以这是一条糟糕的错误消息。我的意思是,它在技术上是正确的,因为密码是JWT,这是无效的,所以它是一个无效的PW…但它可能会更好。我将带回团队,但尝试将86400*60更改为仅86400,应该可以。

下面的每个注释:它也是设备名称。因为它是动态生成的,所以缺少一个字符(破折号而不是下划线)。

旧答案: 至于睡觉,我没有看到任何明显的东西,但是如果移除异步/等待包装器,并同步运行它会发生什么呢?另外,只需验证您的SSL密钥是使用相同的协议(RSA,使用或不使用X509包装器)创建和注册的。我以前在以一种方式注册时遇到过问题,但实际上密钥是以另一种方式注册的。

这篇关于为什么我的树莓PI不能连接到谷歌云物联网?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆