我有一个树莓派,并设置了一个天气(和土壤湿度(设备。
我找到了这个指南:https://codelabs.developers.google.com/codelabs/iot-data-pipeline我遵循了它,并在第6-7步左右陷入困境。
据我所知,当我向PubSub发送数据时,什么也没发生。在Raspberry End上,我有点认为数据正在被发送,但它不会被传递到BigQuery中。我在不同的地方做了一些打印声明,试图看看它在哪里卡住了。
当我试图找到错误时,我慢慢地回溯到步骤5(创建云函数(。步骤5以及我复制的相关代码可以在这里看到:https://codelabs.developers.google.com/codelabs/iot-data-pipeline/#4
在GCP中,我点击进入云功能->函数weatherPubSubToBQ->测试(选项卡(
在"触发事件"标题下,我填写了下面的JSON:
{
"sensorID":"Raspberry",
"timecollected":"2020-09-11 06:45:19",
"zipcode":"00000",
"latitude":"0.0",
"longitude":"0.0",
"temperature":"-273",
"humidity":"-1",
"dewpoint":"-273",
"pressure":"0"
}
当我点击-测试功能-输出如下
**Error: function execution failed. Details:
Cannot read property 'data' of undefined**
JSON和错误消息的截屏
我猜是这两件事中的一件造成了问题。event.data或PubSubMessage.dataTR
我试着对代码做一些修改,但我只是在黑暗中拍摄。
我想知道是否:
- 我做错了什么,这意味着可能还有其他事情其他地方的问题
- 这本指南有点旧,有有一些更新使得指南中的旧代码没有根据需要发挥作用。(指南中的步骤/图像与截至2020年9月,我在网上看到(
- 如果有人知道代码,并且能够让我知道如何解决它非常感谢
提前感谢。
TLDR:教程已经过时,不要使用它,除非你想面对多个问题并想以艰难的方式学习
我完成了教程,我能够复制这个问题。。以及更多。正如你已经提到的,本教程已经过时,很多事情都发生了变化,你可以通过查看图像并注意到UI甚至有所不同来推断,所以我不会向任何刚接触GCP的人推荐本教程。
第一期:
**Error: function execution failed. Details: Cannot read property 'data' of undefined**
可以通过查看发布/子消息的预期结构来轻松解决:
{
"data": string,
"attributes": {
string: string,
...
},
"messageId": string,
"publishTime": string,
"orderingKey": string
}
这么简单吧?然而,一旦你像我一样用自己的变量模拟消息的结构:
{
"data": "",
"attributes": {
"sensorID":"Raspberry",
"timecollected":"2020-09-11 06:45:19",
"zipcode":"00000",
"latitude":"0.0",
"longitude":"0.0",
"temperature":"-273",
"humidity":"-1",
"dewpoint":"-273",
"pressure":"0"
},
"messageId": "id_1",
"publishTime": "2014-10-02T15:01:23Z",
"orderingKey": ""
}
您将得到一个关于JSON:的错误
SyntaxError: Unexpected token ' in JSON at position 1
这个错误是由于在变量incomingData
内构造JSON时使用了'
,所以您必须更改第一个变量声明,我使用模板文字:
const incomingData = PubSubMessage.data ? Buffer.from(PubSubMessage.data, 'base64').toString() : `{"sensorID": "na","timecollected":"01/01/1970 00:00:00","zipcode":"00000","latitude":"0.0","longitude":"0.0","temperature":"-273","humidity":"-1","dewpoint":"-273","pressure":"0"}`;
但问题还没有结束,在尝试插入BigQuery时进行了一些测试后,我得到了一个关于插入的错误,但没有得到真正发生了什么的线索,所以我在一个外部脚本中隔离了咨询,发现错误处理是错误的,我建议您首先更改package.json
中的BigQuery
版本:
"@google-cloud/bigquery": "^0.9.6"
进入
"@google-cloud/bigquery": "5.2.0"
这是写这个答案时的最后一个版本。下一部分是将使用BigQuery
构造函数的方式重新定义为:
const bigquery = new BigQuery({
projectId: projectId
});
经过多次测试,我发现catch
并没有像预期的那样完成它的工作,所以必须将该部分重写为:
bigquery
.dataset(datasetId)
.table(tableId)
.insert(rows)
.then((foundErrors) => {
rows.forEach((row) => console.log('Inserted: ', row));
if (foundErrors && foundErrors.insertErrors != undefined) {
foundErrors.forEach((err) => {
console.log('Error: ', err);
})
}
})
.catch((err) => {
bigquery
.dataset(datasetId)
.table(tableId)
.insert(rows)
.then((foundErrors) => {
rows.forEach((row) => console.log('Inserted: ', row));
if (foundErrors && foundErrors.insertErrors != undefined) {
foundErrors.forEach((err) => {
console.log('Error: ', err);
})
}
})
.catch((err) => {
if(err.name=='PartialFailureError'){
if (err && err.response.insertErrors != undefined) {
err.response.insertErrors.forEach((errors) => {
console.log(errors);
})
}
}else{
console.log("GENERIC ERROR:",err)
}
});
});
在此之后,您将最终注意到错误是由于(再次(incomingData
变量:
Could not parse '01/01/1970 00:00:00' as a timestamp. Required format is YYYY-MM-DD HH:MM[:SS[.SSSSSS]]'
您必须将日期从01/01/1970 00:00:00
更改为1970-01-01 00:00:00
。
还和我在一起吗?还有一个错误来自于在CF末尾使用callback
:
这是因为云函数现在需要三个参数,回调是最后一个,所以将函数声明更改为:
exports.subscribe = function (event, context, callback)
在完成所有这些之后,您可以将数据插入BigQuery,但我们使用的是局部变量,而不是来自pub/sub的数据,此时我放弃了,因为我实际上需要重写整个函数,以便使用Attributes而不是data
使其工作。
如前所述,如果你刚开始学习GCP,请不要遵循本教程。