node.js - 正确创建/解析 JSON
问题描述
我有一个能够读取温度和湿度的 ESP8266。我们的想法是将这些读数上传到 Firebase 数据库,一旦上传这些数据,就使用 Firebase 的函数触发器采取一些行动。
我有一个从 ESP8622 上传数据的 Arduino 代码。上传的数据是时间戳、传感器 ID、温度和湿度。如下:
void updateDatabase(String &temp, String &humidity, String &temp_feeling)
{
String path = "/Measurements";
String SensorID = "1";
timeClient.update();
// timeClient.setTimeOffset(3600);
long timeStamp = timeClient.getEpochTime();
json.clear().set("id",DEVICE_ID);
json.set("timestamp",(String)timeStamp);
json.set("temperature",temp_feeling);
json.set("humidity",humidity);
mostrarJSON(json);
if (Firebase.pushJSON(firebaseData, path,json))
{
Serial.println("PASSED");
Serial.println("PATH: " + firebaseData.dataPath());
Serial.println("TYPE: " + firebaseData.dataType());
Serial.println("ETag: " + firebaseData.ETag());
Serial.print("VALUE: ");
printResult(firebaseData);
Serial.println("------------------------------------");
Serial.println();
}
else
{
Serial.println("FAILED");
Serial.println("REASON: " + firebaseData.errorReason());
Serial.println("------------------------------------");
Serial.println();
}
}
此 JSON 上传到 Firebase 数据库。上传数据的结果如下:
Firebase 函数具有此代码来处理上传的最新测量值。
exports.onDataAdded = functions.database.ref('/Measurements').onWrite((change,context)=>{
const snapshot = change.after;
const val = snapshot.child("").val()
console.log(val)
const temperature = snapshot.child("").child("temperature").val()
const humidity = snapshot.child("").child("humidity").val()
console.log(`New data received : temp : ${temperature}, humidity : ${humidity}`)
takeActionSensorUpdate(temperature,humidity)
return null
})
Firebase 控制台上的代码结果如下:
- 我是否在 Arduino 代码上正确构建了 JSON 对象?我应该创建自己的节点名称,而不是为每个测量使用随机的唯一 ID?如果是这样,我该怎么做?
- 如果我仅在收到来自 ESP8266 的新上传时触发代码,为什么要打印多个数据库实例?
- 正如您在控制台上看到的那样,温度和湿度数据中的输出显示为空。我想这是因为我在 /Measurements 下添加的每个新测量都有一个自动随机 ID,因为它可以在上传到数据库的对象上看到。如何更改 Firebase 函数的代码以获得我想要的值,在这种情况下,温度和湿度?
非常感谢你!
解决方案
我不了解 Arduino,但我认为以下内容将回答您的问题。
我是否在 Arduino 代码上正确构建了 JSON 对象?我应该创建自己的节点名称,而不是为每个测量使用随机的唯一 ID?如果是这样,我该怎么做?
正如我所说,我无法从 Arduino Library 的角度回答(我猜你使用这个库),但是让数据库使用唯一键(即你的问题中的“节点名称”)生成一个新的子位置是非常标准的,因为在文档中解释(例如 JavaScript SDK),它是“将数据添加到项目集合的最常见模式”。
如果我仅在收到来自 ESP8266 的新上传时触发代码,为什么要打印多个数据库实例?
这是因为您在Measurements
节点级别触发了 Cloud Function。请参阅下文如何为Measurements
.
正如您在控制台上看到的那样,温度和湿度数据中的输出显示为空。我想这是因为我在 /Measurements 下添加的每个新测量都有一个自动随机 ID,因为它可以在上传到数据库的对象上看到。如何更改 Firebase 函数的代码以获得我想要的值,在这种情况下,温度和湿度?
同上:change.after
表示Measurements
节点的数据(触发事件后)。它不代表其中一个孩子的数据。此外,通过这样做snapshot.child("")
,您将获得一个undefined
值,因为您将一个空字符串传递给child()
. 这是一个可以解决问题的 Cloud Function 代码:
exports.onDataAdded = functions.database.ref('/Measurements/{pushId}').onWrite((change,context)=>{
const afterData = change.after.val();
console.log(afterData)
const temperature = afterData.temperature;
const humidity = afterData.humidity;
console.log(`New data received : temp : ${temperature}, humidity : ${humidity}`)
takeActionSensorUpdate(temperature,humidity) //Double check if this is not asynchronous. If yes you need to wait the asynchronous action is done before returning
return null
})
正如您将在文档中看到的那样,我们使用通配符(用大括号括起来)指定路径组件。换句话说ref('/Measurements/{pushId}')
,匹配/Measurements
.
推荐阅读
- terraform - Terraform:在 repo 中找不到舵图,但在 cli 中工作
- google-bigquery - BigQuery - 计划查询自动报告错误
- iphone - iPhone 在一台 Apache 服务器上播放 HTML5 视频,但不在另一台 Apache 服务器上播放
- ruby-on-rails - Ruby 仅检索数组中定义的特定哈希键
- azure - Azure Sql 服务器 dtu 超出时会发生什么?
- java - 类型不匹配 必需:LatencyReader.Companion 找到:LatencyReader
- jquery - 如何在继承第一行类的 DataTable 上附加 TR?
- javascript - 类型参数不可分配给 ObservableInput 类型
- mysql - 将所有哈希/盐密码从一个数据库复制粘贴到另一个数据库(Mysql)
- html - Ul 不适合导航