数据推送 Sensor Logger 在记录会话期间支持 HTTP 推送和 MQTT 发布。这可以通过点击 Logger 页面上的齿轮图标来启用。记录期间所有支持的传感器都将以 JSON 格式流式传输,每个可配置的批处理周期一次,通过指定的协议传输到指定的 Web 服务器/代理。 HTTP Push 和 MQTT 具有相同的架构、可配置的批处理周期和支持的传感器。唯一的区别是协议。HTTP 的设置更简单,支持范围更广。另一方面,MQTT 更轻量级,在 IoT 应用程序中更受欢迎。Sensor Logger 还支持同时进行 HTTP 推送和 MQTT 发布。 如果您想推送到 Sensor Logger 当前不支持的其他协议,许多托管式 MQTT 代理都支持开箱即用的数据转发到几乎任何内容。
Sensor Logger 在记录会话期间支持 HTTP 推送和 MQTT 发布。这可以通过点击 Logger 页面上的齿轮图标来启用。记录期间所有支持的传感器都将以 JSON 格式流式传输,每个可配置的批处理周期一次,通过指定的协议传输到指定的 Web 服务器/代理。
HTTP Push 和 MQTT 具有相同的架构、可配置的批处理周期和支持的传感器。唯一的区别是协议。HTTP 的设置更简单,支持范围更广。另一方面,MQTT 更轻量级,在 IoT 应用程序中更受欢迎。Sensor Logger 还支持同时进行 HTTP 推送和 MQTT 发布。
如果您想推送到 Sensor Logger 当前不支持的其他协议,许多托管式 MQTT 代理都支持开箱即用的数据转发到几乎任何内容。例如,EMQ X Cloud 数据集成支持将消息转发到 Kafka,以及 GCP PubSub 源。
对于 HTTP 推送,您必须设置 Web 服务器来接收消息。有关如何设置一个的更多信息和示例代码,请参阅 https://github.com/tszheichoi/awesome-sensor-logger?tab=readme-ov-file#live-data-streaming。
MQTT(消息队列遥测传输)是一种轻量级消息传递协议,广泛用于 IoT(物联网)应用程序。它比 HTTP 更轻量级,但需要更复杂的设置。
您可以运行自己的代理(例如 Mosquitto、EMQX、HiveMQ、RabbitMQ 和 VerneMQ),也可以使用托管的代理。
在此示例中,我们将使用 HiveMQ Cloud,它是免费使用的,不需要您在计算机上安装任何东西。
复制 Broker URL、Username 和 Password,如下所示。确保 Use TLS 已打开。您可以根据需要更改主题名称。默认值为 .sensor-logger

要测试连接,请导航到 HiveMQ 顶部的 Web 客户端。通过您刚刚创建的相同用户名和密码连接到客户端。然后,输入您在 Sensor Logger 上配置的主题。这是默认的。在 Sensor Logger 上,点击 “Tap to Test Publish”。如果成功,它应该显示 “Message Sent”。在 Web 客户端上,您应该会看到一条传入的测试消息。sensor-logger

启用 MQTT 发布后,您还可以通过此 Web 客户端在录制会话期间查看传入消息。
EMQX Cloud 的工作原理与 HiveHQ Cloud 非常相似,还提供了慷慨的免费套餐供您试用。
复制 Broker URL、Username 和 Password,如下所示。确保 Use TLS 已打开。您可以根据需要更改主题名称。默认值为 .sensor-logger

要测试连接,请导航到侧边栏中的 Online Test 部分,然后输入与 Sensor Logger 中配置的主题相同的主题。然后单击 Subscribe。在 Sensor Logger 上,点击 “Tap to Test Publish”。如果成功,它应该显示 “Message Sent”。在 Web 客户端上,您应该会看到一条传入的测试消息。
如果您不想使用其中一种托管云服务,您也可以在本地运行 EMQX。在这种情况下,除非您公开 IP 地址,否则 Sensor Logger 应与您的计算机位于同一本地网络上。
docker pull emqx/emqx:5.6.0docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx:5.6.0http://localhost:18083/``admin``public+ Createsensor-logger设置代理后,您可以像往常一样打开“启用 MQTT 发布”并启动录制会话。已发布的 MQTT 消息的 JSON 架构与 HTTP 推送消息相同,即:
{ messageId: 0, sessionId: "identifier", deviceId: "identifier", payload: [ { "name": "accelerometer", "time": 1698501144401773000, <other fields depending on sensor> }, { "name": "location", "time": 1698501145514000000, <other fields depending on sensor> }, ], }
对于发送的每条消息,该 将递增。对于单个录制中的所有消息,以及来自单个设备的所有消息,都是相同的。该时间以 UTC 纪元纳秒为单位。messageId``sessionId``deviceId
此外,请注意以下事项:
一旦您的测量到达 Broker,就由您决定如何使用这些消息。通常,您将设置另一个客户端来使用这些消息。例如,您可以通过 Python 执行此操作。
然后,您可以根据您的使用案例调整以下 Python 脚本。
import paho.mqtt.client as mqtt BROKER_URL = "your_broker.com" BROKER_PORT = 8884 USERNAME = "your_username" PASSWORD = "your_password" def on_connect(*args): print(f"Connected with result code {args[3]}") client.subscribe("sensor-logger") def on_message(client, userdata, msg): print(f"msg: {msg.topic} {msg.payload}") client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, transport="websockets") client.username_pw_set(username=USERNAME, password=PASSWORD) client.on_connect = on_connect client.on_message = on_message client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLSv1_2) client.connect(BROKER_URL, BROKER_PORT, 60) client.loop_forever()
有关如何使用 Plotly Dash 实时绘制传感器数据的示例,请参阅 HTTP 推送文档。
无论您使用的是 MQTT 还是 HTTP Push,都可以使用以下 Typescript 定义。
type Message = { messageId: number; sessionId: string; deviceId: string; payload: SensorReading[]; }; type SensorReading = | MicrophoneReading | LocationReading | XYZReading | OrientationReading | BarometerReading | BrightnessReading | NetworkReading | BatteryReading | BluetoothReading | BluetoothMetadataReading | WristMotionReading | PedometerReading | HeadphoneReading | AnnotationReading; type MicrophoneReading = { name: "microphone"; time: number; values: { dBFS: number; }; }; type LocationReading = { name: "location"; time: number; values: { altitude: number; speedAccuracy: number; bearingAccuracy: number; latitude: number; altitudeAboveMeanSeaLevel: number; bearing: number; horizontalAccuracy: number; verticalAccuracy: number; longitude: number; speed: number; }; }; type XYZReading = { name: | "magnetometeruncalibrated" | "gyroscopeuncalibrated" | "accelerometeruncalibrated" | "magnetometer" | "gyroscope" | "accelerometer" | "gravity" | "magnetometer"; time: number; values: { z: number; y: number; x: number; }; accuracy?: number; }; type OrientationReading = { name: "orientation"; time: number; values: { yaw: number; qx: number; qz: number; roll: number; qw: number; qy: number; pitch: number; }; }; type BarometerReading = { name: "barometer"; time: number; values: { relativeAltitude: number; pressure: number; }; }; type BrightnessReading = { name: "brightness"; time: number; values: { brightness: number; }; }; type NetworkReading = { name: "network"; time: number; values: { type?: string; isConnected?: boolean; isInternetReachable?: boolean; isWifiEnabled?: boolean; isConnectionExpensive?: boolean; ssid?: string; bssid?: string; strength?: number; ipAddress?: string; frequency?: number; cellularGeneration?: string; carrier?: string; }; }; type BatteryReading = { name: "battery"; time: number; values: { batteryLevel: number; batteryState: "unknown" | "unplugged" | "charging" | "full"; lowPowerMode: boolean; }; }; type BluetoothReading = { name: "bluetooth"; time: number; values: { id: string; rssi: number | null; txPowerLevel?: number; manufacturerData?: string; }; }; type BluetoothMetadataReading = { name: "bluetoothmetadata"; time: number; values: { id: string; name: string; isConnectable: number; localName?: string; serviceUUIDs?: string; }; }; type WristMotionReading = { name: "wrist motion"; time: number; values: { rotationRateX: number; rotationRateY: number; rotationRateZ: number; gravityX: number; gravityY: number; gravityZ: number; accelerationX: number; accelerationY: number; accelerationZ: number; quaternionW: number; quaternionX: number; quaternionY: number; quaternionZ: number; }; }; type PedometerReading = { name: "pedometer"; time: number; values: { steps: number; }; }; type HeadphoneReading = { name: "headphone"; time: number; values: { devicelocation: "left" | "right"; roll: number; yaw: number; pitch: number; rotationRateX: number; rotationRateY: number; rotationRateZ: number; quaternionW: number; quaternionX: number; quaternionY: number; quaternionZ: number; gravityX: number; gravityY: number; gravityZ: number; accelerationX: number; accelerationY: number; accelerationZ: number; }; }; type AnnotationReading = { name: "annotation"; time: number; values: { text: string; millisecond_press_duration: number; }; };