我正在做一个物联网项目,需要物联网设备将数据发送到网关设备,网关设备然后通过 mqtt 桥将此数据发布到 Google Pub/Sub 主题。 mqtt 桥代码是用 python 编写的,但我希望使用 Firebase Cloud Functions 将此数据存储在 Firebase Store 中。但是,每当将数据发布到 pub/sub 主题时,每当云函数尝试提取此数据时,我都会收到“语法错误:JSON.parse 位置 0 处的 JSON 中的意外标记 R”错误。 MQTT 代码使用函数调用客户端,如下所示:
def get_client(
project_id, cloud_region, registry_id, gateway_id, private_key_file,
algorithm, ca_certs, mqtt_bridge_hostname, mqtt_bridge_port,
jwt_expires_minutes):
"""Create our MQTT client. The client_id is a unique string that identifies
this device. For Google Cloud IoT Core, it must be in the format below."""
client = mqtt.Client(
client_id=('projects/{}/locations/{}/registries/{}/devices/{}'.format(
project_id,
cloud_region,
registry_id,
gateway_id)))
# With Google Cloud IoT Core, the username field is ignored, and the
# password field is used to transmit a JWT to authorize the device.
client.username_pw_set(
username='unused',
password=create_jwt(
project_id, private_key_file, algorithm, jwt_expires_minutes))
# Enable SSL/TLS support.
client.tls_set(ca_certs=ca_certs, tls_version=ssl.PROTOCOL_TLSv1_2)
# Register callbacks. https://eclipse.org/paho/clients/python/docs/
# describes additional callbacks that Paho supports. In this example,
# the callbacks just print to standard out.
client.on_connect = on_connect
client.on_publish = on_publish
client.on_disconnect = on_disconnect
client.on_message = on_message
client.on_subscribe = on_subscribe
# Connect to the Google MQTT bridge.
client.connect(mqtt_bridge_hostname, mqtt_bridge_port)
mqtt_topic = '/devices/{}/events'.format(gateway_id)
client.publish(mqtt_topic, 'RPI Gateway started.', qos=0)
return client
此代码在将数据发布到云发布/订阅主题的 main 函数中执行:
client = get_client(
args.project_id, args.cloud_region, args.registry_id, args.gateway_id,
args.private_key_file, args.algorithm, args.ca_certs,
args.mqtt_bridge_hostname, args.mqtt_bridge_port,
args.jwt_expires_minutes)
while True:
client.loop()
if gateway_state.connected is False:
print('connect status {}'.format(gateway_state.connected))
time.sleep(1)
continue
try:
data, client_addr = udpSerSock.recvfrom(BUFSIZE)
except socket.error:
continue
print('[{}]: From Address {}:{} receive data: {}'.format(
ctime(), client_addr[0], client_addr[1], data.decode("utf-8")))
command = json.loads(data.decode('utf-8'))
if not command:
print('invalid json command {}'.format(data))
continue
action = command["action"]
device_id = command["device"]
template = '{{ "device": "{}", "command": "{}", "status" : "ok" }}'
if action == 'event':
print('Sending telemetry event for device {}'.format(device_id))
payload = command["data"]
mqtt_topic = '/devices/{}/events'.format(device_id)
print('Publishing message to topic {} with payload \'{}\''.format(
mqtt_topic, payload))
_, event_mid = client.publish(mqtt_topic, payload, qos=0)
message = template.format(device_id, 'event')
udpSerSock.sendto(message.encode('utf8'), client_addr)
elif action == 'attach':
print('Sending telemetry event for device {}'.format(device_id))
attach_topic = '/devices/{}/attach'.format(device_id)
auth = '' # TODO: auth = command["jwt"]
attach_payload = '{{"authorization" : "{}"}}'.format(auth)
print('Attaching device {}'.format(device_id))
print(attach_topic)
response, attach_mid = client.publish(
attach_topic, attach_payload, qos=1)
message = template.format(device_id, 'attach')
udpSerSock.sendto(message.encode('utf8'), client_addr)
elif action == 'detach':
detach_topic = '/devices/{}/detach'.format(device_id)
print(detach_topic)
res, mid = client.publish(detach_topic, "{}", qos=1)
message = template.format(res, mid)
print('sending data over UDP {} {}'.format(client_addr, message))
udpSerSock.sendto(message.encode('utf8'), client_addr)
elif action == "subscribe":
print('subscribe config for {}'.format(device_id))
subscribe_topic = '/devices/{}/config'.format(device_id)
skip_next_sub = True
_, mid = client.subscribe(subscribe_topic, qos=1)
message = template.format(device_id, 'subscribe')
gateway_state.subscriptions[subscribe_topic] = client_addr
udpSerSock.sendto(message.encode('utf8'), client_addr)
else:
print('undefined action: {}'.format(action))
print('Finished.')
如何修改此代码,以便从发布/订阅主题中提取的数据采用适用于 Firebase Cloud Funciton 的正确 JSON 格式?