이 페이지에서는 게이트웨이가 연결된 기기에 대해 데이터를 전송하고 구성 메시지를 중계하는 방법을 설명합니다.
허브 데모 앱은 구성 메시지를 리슨하고 기기 대신 상태 정보를 전송하여 게이트웨이의 엔드 투 엔드 작동 방식을 보여줍니다. 이 앱은 기존 관리자 샘플 또는 로컬 함수를 사용해서 기기를 관리할 수 있으며 허브 샘플을 사용하여 결합된 기기를 관리하고 해당 기기 대신 MQTT 프로토콜 브리지에 연결합니다.
데모를 실행하면 다음과 비슷한 출력이 표시됩니다.
Running demo
Creating registry: test-registry-1541200612
Created registry
Creating gateway: test-device-RS256
Created gateway {u'gatewayConfig': {u'gatewayType': u'GATEWAY', u'gatewayAuthMethod': u'ASSOCIATION_ONLY'} ... }
Creating device to bind: test-device-noauthbind
Created Device {u'numId': u'2552202179450953', u'config': {u'version': u'1', u'cloudUpdateTime': u'2018-11-02T23:16:58.198419Z'}, u'id': u'test-device-noauthbind', u'gatewayConfig': {u'gatewayType': u'NON_GATEWAY', u'gatewayAuthMethod': u'ASSOCIATION_ONLY'} ...}
Binding device
Device Bound!
Listening for messages for 30 seconds
Try setting configuration in:
https://console.cloud.google.com/iot/locations/us-central1/registries/test-registry-1541200612?project=noun-verb-123
Press enter to continue
Creating JWT using RS256 from private key file resources/rsa_private.pem
Attaching: /devices/test-device-noauthbind/attach
Waiting for device to attach.
('on_connect', 'Connection Accepted.')
on_publish
on_subscribe
Received message 'device-config' on topic '/devices/test-device-noauthbind/config' with Qos 1
on_subscribe
Received message 'gateway-config' on topic '/devices/test-device-RS256/config' with Qos 1
Detaching: /devices/test-device-noauthbind/detach
Finished.
Publishing messages demo
Publishing: 15 messages
Creating JWT using RS256 from private key file resources/rsa_private.pem
Attaching: /devices/test-device-noauthbind/attach
Waiting for device to attach.
Starting HUB at: 1541200710.73
('on_connect', 'Connection Accepted.')
on_publish
Publishing message 1/15: 'test-registry-1541200612/test-device-RS256-test-device-noauthbind-payload-1' to /devices/test-device-noauthbind/state
...
on_publish
Publishing message 15/15: 'test-registry-1541200612/test-device-RS256-test-device-noauthbind-payload-15' to /devices/test-device-noauthbind/state
Detaching: /devices/test-device-noauthbind/detach
on_publish
Finished.
You can read the state messages for your device at this URL:
https://console.cloud.google.com/iot/locations/us-central1/registries/test-registry-1541200612/devices/test-device-noauthbind?project=noun-verb-1234
Device unbound: {}
Delete device
Delete device
Delete registry
다음 코드는 데모 스크립트의 전체 소스를 보여줍니다.
Python
import csv
import datetime
import io
import logging
import os
import time
from google.cloud import pubsub
# import manager # TODO(class) when feature exits beta, remove borrowed defs
import hub
logging.getLogger('googleapiclient.discovery_cache').setLevel(logging.CRITICAL)
cloud_region = 'us-central1'
device_id_template = 'test-device-{}'
gateway_id_template = 'test-gateway-{}'
topic_id = 'test-device-events-{}'.format(int(time.time()))
ca_cert_path = 'resources/roots.pem'
log_path = 'config_log.csv'
rsa_cert_path = 'resources/rsa_cert.pem'
rsa_private_path = 'resources/rsa_private.pem'
if ('GCLOUD_PROJECT' not in os.environ or
'GOOGLE_APPLICATION_CREDENTIALS' not in os.environ):
print(
'You must set GCLOUD_PROJECT and GOOGLE_APPLICATION_CREDENTIALS')
quit()
project_id = os.environ['GCLOUD_PROJECT']
service_account_json = os.environ['GOOGLE_APPLICATION_CREDENTIALS']
pubsub_topic = 'projects/{}/topics/{}'.format(project_id, topic_id)
registry_id = 'test-registry-{}'.format(int(time.time()))
base_url = 'https://console.cloud.google.com/iot/locations/{}'.format(
cloud_region)
edit_template = '{}/registries/{}?project={}'.format(
base_url, '{}', '{}')
device_url_template = '{}/registries/{}/devices/{}?project={}'.format(
base_url, '{}', '{}', '{}')
mqtt_bridge_hostname = 'mqtt.googleapis.com'
mqtt_bridge_port = 8883
num_messages = 15
jwt_exp_time = 20
listen_time = 30
def create_iot_topic(project, topic_name):
"""Creates a PubSub Topic and grants access to Cloud IoT Core."""
pubsub_client = pubsub.PublisherClient()
topic_path = pubsub_client.topic_path(project, topic_name)
topic = pubsub_client.create_topic(topic_path)
policy = pubsub_client.get_iam_policy(topic_path)
policy.bindings.add(
role='roles/pubsub.publisher',
members=['serviceAccount:cloud-iot@system.gserviceaccount.com'])
pubsub_client.set_iam_policy(topic_path, policy)
return topic
def create_registry(
service_account_json, project_id, cloud_region, pubsub_topic,
registry_id):
""" Creates a registry and returns the result. Returns an empty result if
the registry already exists."""
client = hub.get_client(service_account_json)
registry_parent = 'projects/{}/locations/{}'.format(
project_id,
cloud_region)
body = {
'eventNotificationConfigs': [{
'pubsubTopicName': pubsub_topic
}],
'id': registry_id
}
request = client.projects().locations().registries().create(
parent=registry_parent, body=body)
response = request.execute()
print('Created registry')
return response
def delete_registry(
service_account_json, project_id, cloud_region, registry_id):
"""Deletes the specified registry."""
print('Delete registry')
client = hub.get_client(service_account_json)
registry_name = 'projects/{}/locations/{}/registries/{}'.format(
project_id, cloud_region, registry_id)
registries = client.projects().locations().registries()
return registries.delete(name=registry_name).execute()
def create_device(
service_account_json, project_id, cloud_region, registry_id,
device_id, certificate_file):
"""Create a new device without authentication."""
registry_name = 'projects/{}/locations/{}/registries/{}'.format(
project_id, cloud_region, registry_id)
with io.open(certificate_file) as f:
certificate = f.read()
client = hub.get_client(service_account_json)
device_template = {
'id': device_id,
'credentials': [{
'publicKey': {
'format': 'RSA_X509_PEM',
'key': certificate
}
}]
}
devices = client.projects().locations().registries().devices()
return devices.create(parent=registry_name, body=device_template).execute()
def delete_device(
service_account_json, project_id, cloud_region, registry_id,
device_id):
"""Delete the device with the given id."""
print('Delete device')
client = hub.get_client(service_account_json)
registry_name = 'projects/{}/locations/{}/registries/{}'.format(
project_id, cloud_region, registry_id)
device_name = '{}/devices/{}'.format(registry_name, device_id)
devices = client.projects().locations().registries().devices()
return devices.delete(name=device_name).execute()
if __name__ == '__main__':
print("Running demo")
gateway_id = device_id_template.format('RS256')
device_id = device_id_template.format('noauthbind')
print('Creating registry: {}'.format(registry_id))
create_registry(
service_account_json, project_id, cloud_region, pubsub_topic,
registry_id)
print('Creating gateway: {}'.format(gateway_id))
hub.create_gateway(
service_account_json, project_id, cloud_region, registry_id,
None, gateway_id, rsa_cert_path, 'RS256')
print('Creating device to bind: {}'.format(device_id))
hub.create_device(
service_account_json, project_id, cloud_region, registry_id,
device_id)
print('Binding device')
hub.bind_device_to_gateway(
service_account_json, project_id, cloud_region, registry_id,
device_id, gateway_id)
print('Listening for messages for {} seconds'.format(listen_time))
print('Try setting configuration in: ')
print('\t{}'.format(edit_template.format(registry_id, project_id)))
try:
input("Press enter to continue")
except SyntaxError:
pass
def log_callback (client):
def log_on_message(unused_client, unused_userdata, message):
if not os.path.exists(log_path):
with open(log_path, 'w') as csvfile:
logwriter = csv.writer(csvfile, dialect='excel')
logwriter.writerow(['time', 'topic', 'data'])
with open(log_path, 'a') as csvfile:
logwriter = csv.writer(csvfile, dialect='excel')
logwriter.writerow([
datetime.datetime.now().isoformat(),
message.topic,
message.payload])
client.on_message = log_on_message
hub.listen_for_config_messages(
service_account_json, project_id, cloud_region, registry_id,
device_id, gateway_id, num_messages, rsa_private_path, 'RS256',
ca_cert_path, mqtt_bridge_hostname, mqtt_bridge_port,
jwt_exp_time, listen_time, log_callback)
print('Publishing messages demo')
print('Publishing: {} messages'.format(num_messages))
hub.send_data_from_bound_device(
service_account_json, project_id, cloud_region, registry_id,
device_id, gateway_id, num_messages, rsa_private_path, 'RS256',
ca_cert_path, mqtt_bridge_hostname, mqtt_bridge_port,
jwt_exp_time, "Hello from hub_demo.py")
print('You can read the state messages for your device at this URL:')
print('\t{}'.format(device_url_template).format(
registry_id, device_id, project_id))
try:
input('Press enter to continue after reading the messages.')
except SyntaxError:
pass
# Clean up
hub.unbind_device_from_gateway(
service_account_json, project_id, cloud_region, registry_id,
device_id, gateway_id)
delete_device(
service_account_json, project_id, cloud_region, registry_id,
device_id)
delete_device(
service_account_json, project_id, cloud_region, registry_id,
gateway_id)
delete_registry(
service_account_json, project_id, cloud_region, registry_id)
데모 스크립트는 다음 작업을 수행합니다.
데모 레지스트리 만들기
데모는 먼저 데모가 종료될 때 삭제되는 임시 기기 레지스트리를 만듭니다. 이 레지스트리에는 게이트웨이에서 관리되는 기기뿐만 아니라 특별한 기기 유형인 게이트웨이가 포함됩니다. 이를 수행하기 위해 레지스트리 만들기 샘플 코드가 사용됩니다.
다음 코드는 관리자 샘플로 기기 레지스트리를 만드는 방법을 보여줍니다.
레지스트리를 만든 후 이제 기기를 추가할 수 있습니다.
게이트웨이 만들기
레지스트리에 추가되는 첫 번째 기기는 게이트웨이라고 부르는 특별한 유형의 기기입니다. 이 기기는 연관된 자체 구성을 가질 수 있고 다른 기기를 결합하여 이에 대한 프록시로 작동할 수 있습니다.
생성된 후에는 게이트웨이 기기가 연관된 사용자 인증 정보를 사용해서 Cloud IoT Core 프로토콜 브리지에 연결할 수 있습니다.
다음 코드는 허브 샘플로 특별한 게이트웨이 기기를 만드는 방법을 보여줍니다.
결합할 기기 만들기
기기를 게이트웨이에 결합하려면 먼저 게이트웨이와 함께 레지스트리 내에 기기를 만들어야 합니다. 이 데모에서는 허브 샘플을 사용하여 기기를 만듭니다.
다음 코드는 허브 샘플로 결합할 기기를 만드는 방법을 보여줍니다.
게이트웨이에 기기 결합
기기 및 게이트웨이가 데모 레지스트리에 준비되었으면 이제 게이트웨이에 기기를 결합할 수 있습니다. 기기를 게이트웨이에 결합한 후에는 게이트웨이가 Cloud IoT Core 프로토콜 브리지에 대한 연결을 사용해서 기기를 연결 및 분리할 수 있습니다. 데모 앱은 허브 샘플을 사용해서 다음과 같이 이를 수행합니다.
다음 코드는 허브가 기기를 게이트웨이에 결합하는 방법을 보여줍니다.
구성 메시지 리슨
기기가 게이트웨이에 결합된 후 게이트웨이가 Cloud IoT Core 프로토콜 브리지에 연결하고, 기기를 연결한 후 해당 기기에 대해 구성 메시지를 수신할 수 있습니다. 이 데모는 허브 샘플의 도우미 함수를 사용해서 이를 수행합니다.
허브 샘플에서는 Paho MQTT 클라이언트를 사용하여 다음과 같이 프로토콜 브리지에 연결됩니다.
이 단계를 시작하기 전 샘플이 일시중지되어 리슨이 시작되기 전 Developer Console로 이동하여 게이트웨이 또는 결합된 기기에 대해 구성 데이터를 설정하고 최신 구성이 수신되는지 확인할 수 있습니다.
상태 데이터 전송
이 데모 앱은 게이트웨이 및 결합된 기기 대신 구성 메시지를 수신하는 방법을 보여준 후 연결된 기기 대신 상태 데이터를 전송합니다. 이를 위해 이 데모에서는 허브 샘플 앱의 도우미 함수를 사용합니다.
결합된 기기 대신 상태 데이터를 전송한 후 데모가 일시중지되므로 다음 단계에서 데모 레지스트리 및 기기가 삭제되기 전 Developer Console로 이동할 수 있습니다.
데모에 사용된 리소스 삭제
데모가 완료되면 처음에 할당되었던 기기 및 레지스트리가 삭제됩니다.
기기는 삭제되기 전 게이트웨이에서 결합 해제됩니다.
관리자 샘플의 도우미 함수를 사용하여 게이트웨이뿐만 아니라 결합된 기기를 모두 삭제합니다.
마지막으로 관리자 샘플의 도우미 함수를 사용하여 레지스트리를 삭제합니다.
지금까지 게이트웨이 기능의 엔드 투 엔드 작동 방식을 살펴봤습니다.