/iot-services-sdk

An SDK that wraps the device management APIs - as well as the REST and the MQTT Gateways of SAP IoT Services, Cloud Foundry Edition - in easy-to-use Python Code.

Primary LanguagePythonOtherNOASSERTION

Important Notice

This public repository is read-only and no longer maintained.

Table of Contents

Description

This package wraps the SAP IoT Services, Cloud Foundry Edition Device Management APIs as well as the REST and the MQTT Cloud Gateway APIs in easy-to-use Python code. You can find more information on the APIs here and here.

Features include:

  • Wrapper around every functionality of the Device Management API
  • Better error feedback
  • Wrapper around both Cloud Gateways
  • Both clients, REST and MQTT, are extended so that they work directly with the encrypted keys in the pem file
  • Better error handling and error feedback for REST and MQTT
    • The MQTT client has an on_error and an on_command callback which directly return the parsed message
    • The REST client parses the error for batched and single uploads and throws an error with the respective message
    • Both clients return the failed message to enable the user to retry easily

Requirements

You will need an instance of IoT Services, Cloud Foundry to use this SDK. You can find more information on how to activate the service here.

Installation

The package will be available at pip:

pip install iot-services-sdk

If you want to download it manually, please make sure to install paho-mqtt and requests into your Python environment.

How to obtain support

Please use GitHub Issues to file a bug.

License

Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the SAP Sample Code License except as noted otherwise in the LICENSE file.

Usage

Please refer to the API documentation in the PDF file for details. You can check the tests for sample code.

Here is a small example displaying the following functionality:

  • Creating capabilities, a sensor type, a sensor and a device.
  • Downloading the certificate and creating a MQTT client.
  • Publishing valid and invalid measures as well as publishing and receiving commands.
  • Deleting every entity which was created.
import os

from iot_services_sdk import CapabilityService
from iot_services_sdk import DeviceService
from iot_services_sdk import GatewayService
from iot_services_sdk import SensorTypeService
from iot_services_sdk import SensorService

from iot_services_sdk import MQTTClient

# Initialize services
device_service = DeviceService(instance = myinstance.eu10.cp.iot.sap, user = myuser, password = mypassword)
capability_service = CapabilityService(instance = myinstance.eu10.cp.iot.sap, user = myuser, password = mypassword)
gateway_service = GatewayService(instance = myinstance.eu10.cp.iot.sap, user = myuser, password = mypassword)
sensor_type_service = SensorTypeService(instance = myinstance.eu10.cp.iot.sap, user = myuser, password = mypassword)
sensor_service = SensorService(instance = myinstance.eu10.cp.iot.sap, user = myuser, password = mypassword)

# Turn requests debug functionality on
capability_service.debug_requests_on()
device_service.debug_requests_on()
gateway_service.debug_requests_on()
sensor_type_service.debug_requests_on()
sensor_service.debug_requests_on()

# Get Gateway
filters = ["status eq 'online'"]
gateways_response = gateway_service.get_gateways(filters=filters)
gateways = gateways_response.get_result()
mqtt_gateway = next(gateway for gateway in gateways if gateway['protocolId'] == 'mqtt')

# Create Measure Capability
properties = [
    {"name": "sdk_test_temp", "dataType": "double", "unitOfMeasure": "Celcius"}
]
create_response = capability_service.create_capability('sdk_test_measure_id', 'sdk_test_measure_cap', properties)

capability_measure_id = create_response.get_result().get('id')
capability_measure_alternate_id = create_response.get_result().get('alternateId')

# Create Command Capability
properties = [
    {"name": "sdk_test_cmd", "dataType": "string"}
]
create_response = capability_service.create_capability('sdk_test_cmd_id', 'sdk_test_cmd_cap', properties)

capability_cmd_id = create_response.get_result().get('id')
capability_cmd_alternate_id = create_response.get_result().get('alternateId')

# Create Device
create_response = device_service.create_device(mqtt_gateway['id'], 'sdk_device')

device = create_response.get_result()
device_id = device['id']
device_alternate_id = device['alternateId']

# Create Sensor Type
capabilities = [
    {'id': capability_measure_id, 'type': 'measure'},
    {'id': capability_cmd_id, 'type': 'command'}
]
create_response = sensor_type_service.create_sensor_type('123456', 'sdk_mqtt_test_type', capabilities)

sensor_type_id = create_response.get_result().get('id')
sensor_type_alternate_id = create_response.get_result().get('alternateId')

# Create Sensor
create_response = sensor_service.create_sensor(device_id, 'sdk-test-mqtt-sensor-id', 'sdk-test-mqtt-sensor-name', sensor_type_id)

sensor_id = create_response.get_result()['id']
sensor_alternate_id = create_response.get_result()['alternateId']

# Download Certificate
res = device_service.get_device_pem(device_id).get_result()

pem = res.get('pem')
secret = res.get('secret')
pem_filepath = 'cert.pem'

# Write Certificate to PEM file
pem_file = open(pem_filepath, 'w')
pem_file.write(pem)
pem_file.close()

# Get MQTT Client for Device
mqtt_client = device_service.get_mqtt_client(device_alternate_id, pem_filepath, secret)
mqtt_client.connect()
mqtt_client.loop_start()

# Publish a measure
measures = [
    {'sdk_test_temp': 30}
]
message_info_measures = mqtt_client.publish(capability_measure_alternate_id, sensor_alternate_id, measures, device_alternate_id)

# Read measures
get_measures_response = device_service.get_measures(device_id)
measures = get_measures_response.get_result()

# Publish invalid measure and receive error
def on_error(client, userdata, report):
    print('ERROR RECEIVED: ')
    print(report)

mqtt_client.on_error = on_error

measures = [
    {'i_am_invalid': 30}
]
message_info_measures = mqtt_client.publish(capability_measure_alternate_id, sensor_alternate_id, measures, device_alternate_id)

# Publish and receive command
def on_command(client, userdata, command):
    print('COMMAND RECEIVED: ')
    print(command)

mqtt_client.on_command = on_command

mqtt_client.subscribe(device_alternate_id)

command = {'sdk_test_cmd': 'I am a SDK!'}

send_command_res = device_service.send_command_to_device(device_id, capability_cmd_id, sensor_id, command)

# Stop MQTT loop
mqtt_client.loop_stop()

# Delete Sensor
delete_sensor_res = sensor_service.delete_sensor(sensor_id)

# Delete Device
delete_response = device_service.delete_device(device_id)

# Delete SensorType
delete_sensor_type_response = sensor_type_service.delete_sensor_type(sensor_type_id)

# Delete Measure Capability
delete_response = capability_service.delete_capability(capability_measure_id)

# Delete Command Capability
delete_response = capability_service.delete_capability(capability_cmd_id)

# Delete Certfile
try:
    os.remove(pem_filepath)
except OSError:
    pass

Test

To run the tests, you have to place a config.ini in the root directory. It has to contain the following information:

[IOTS]
INSTANCE=myinstance.eu10.cp.iot.sap
BASE_URI=/iot/core/api/v1
GATEWAY_URI=/iot/gateway
USER=myuser
PASSWORD=mypassword

Then, run

nosetests

in the root directory. The tests will clean up after themselves - there is no need to check your system afterwards.

Build Docs

Use Sphinx to build the documentation directly from the docstrings:

cd docs

sphinx-apidoc -f -o source/ ../sap_iot_services_sdk

make latexpdf

Copy the SAPIoTServicesSDK.pdf file into the root directory.