Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Measurement simulator demo in Python #3

Merged
merged 3 commits into from
Dec 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

.project
.pydevproject
*.pyc
52 changes: 29 additions & 23 deletions devicecreation/IoTDeviceCreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
from requests.auth import HTTPBasicAuth
import json

host = 'https://humblescience.us.cumulocity.com'
username = 'testuser@softwareag.com'
password = 'test123!'

host = 'https://TENANT.cumulocity.com'
username = 'testuser'
password = 'password'

auth = HTTPBasicAuth(username, password)
session = requests.Session()
Expand Down Expand Up @@ -55,11 +56,16 @@

# Check whether device is already registered.
def isDeviceRegistered(deviceIdPath, deviceId):
url = host + deviceIdPath + deviceId
return getInternalDeviceId(deviceIdPath, deviceId) != None

def getInternalDeviceId(deviceId):
url = host + '/identity/externalIds/c8y_Serial/' + deviceId
response = session.get(url)
#print ('Response -> ' + str(response.json()))
print ('Response -> ' + str(response.status_code))
return response.status_code == 200
#print ('Response -> ' + str(response.status_code))
if response.status_code == 200:
jsonResponse = response.json()
return jsonResponse['managedObject']['id']
return None

# Create the device from template
def createDevice(deviceName, deviceType, deviceId):
Expand All @@ -70,10 +76,10 @@ def createDevice(deviceName, deviceType, deviceId):
deviceDescriptionJson['c8y_Hardware']['serialNumber'] = deviceId
print (json.dumps(deviceDescriptionJson, indent = 4))
response = session.post(url, json=deviceDescriptionJson)
print ('Response -> ' + str(response.status_code))
#print ('Response -> ' + str(response.status_code))
if (response.status_code == 201):
newDeviceDetails = response.json()
print ("New device created [id=%s]" % newDeviceDetails['id'])
#print ("New device created [id=%s]" % newDeviceDetails['id'])
return newDeviceDetails;
return None
# print ('Response -> ' + json.dumps(response.json(), indent = 4))
Expand All @@ -90,28 +96,28 @@ def registerDevice(deviceId, newDeviceDetails):
}""")
associateDescriptionJson['externalId'] = deviceId
response = session.post(url, json=associateDescriptionJson)
print ('Response -> ' + str(response.status_code))
print(response.text)
# print ('Response -> ' + str(response.status_code))
#print(response.text)
if (response.status_code == 201):
newDeviceAssoc = response.json()
print ("New device [id=%s] associated with external id ['c8y_serial'=%s]" % (newDeviceAssoc['managedObject']['id'], newDeviceAssoc['externalId']))
print ("New device [id=%s] associated with external id ['c8y_Serial'=%s]" % (newDeviceAssoc['managedObject']['id'], newDeviceAssoc['externalId']))
# print ('Response -> ' + json.dumps(response.json(), indent = 4))



def checkAndRegisterDevice(deviceName, deviceType, deviceId):
if isDeviceRegistered('/identity/externalIds/c8y_Serial/', deviceId):
print('Device [id=%s] already registered.' % deviceId)
def checkAndRegisterDevice(deviceName, deviceType, externalId):
internalDeviceId = getInternalDeviceId(externalId)
if internalDeviceId != None:
print('Managed object [external id=%s] already registered with internal id=%s.' % (externalId, internalDeviceId))
return internalDeviceId
else:
print('Device [id=%s] not registered, registering as new device ...' % deviceId)
newDeviceDetails = createDevice(deviceName, deviceType, deviceId)
print('Managed object [id=%s] not registered, registering as new device ...' % externalId)
newDeviceDetails = createDevice(deviceName, deviceType, externalId)
if (newDeviceDetails != None):
registerDevice(deviceId, newDeviceDetails)
registerDevice(externalId, newDeviceDetails)
return newDeviceDetails['id']
else:
print("Error creating new device! [id=%s]"%deviceId)



print("Error creating new device! [id=%s]", externalId)
return None

if __name__ == "__main__":
checkAndRegisterDevice('MyDevice', 'MyDeviceType', 'my-device-1')
Expand Down
104 changes: 104 additions & 0 deletions measurement_generation/IoTDeviceSimulator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'''
This script aims to showcase how to generate measurements for Cumulocity devices.
In this example, we demonstrate necessary steps to generate simulated sensor readings through Cumulocity's REST API.
This example automatically creates devices that host the generated readings.

Please refer to the documentation for further details on the API:
https://cumulocity.com/guides/reference/rest-implementation/

Created on Dec 10, 2019

@author: JHUM
'''

import requests
from requests.auth import HTTPBasicAuth
import json
import datetime
import random
from threading import Thread
from time import sleep

# Get the session information from the IoTDeviceCreation module
import sys
sys.path.append('../devicecreation')
from IoTDeviceCreation import checkAndRegisterDevice, host, session

SENSOR_READING_TIME_DELAY = 10.0
INITIAL_SENSOR_VALUE = 100.0
POSITIVE_CHANGE_PROBABILITY = 0.5

class DeviceDescription:

c8y_id = "" # this will be given when we create and register device

def __init__(self, name, type, measurementType, measurementName, measurementUnit):
self.name = name
self.type = type
self.measurementType = measurementType
self.measurementName = measurementName
self.measurementUnit = measurementUnit


sensorDevices = [ DeviceDescription("TempSensor-1", "TemperatureSensor", "c8y_Temperature", "T", "C"),
DeviceDescription("PressureSensor-1", "PressureSensor", "c8y_Pressure", "P", "Pa") ]


def createDevice(name, id, measurementName):
return

def createMeasurement(deviceDescription, value):
measurementData = {}
measurementData['source'] = { "id" : deviceDescription.c8y_id }
measurementData['time'] = formatTimestamp(datetime.datetime.utcnow())
measurementData['type'] = deviceDescription.measurementType
measurementData[deviceDescription.measurementType] = { deviceDescription.measurementName : { "value": value, "unit" : deviceDescription.measurementUnit } }
#print (json.dumps(measurementData, indent = 4))
status = submitMeasurement(measurementData)
print("Measurement submitted for deviceId='%s' value='%s' ... result -> %s"%(deviceDescription.c8y_id, value, status))

def sensorLifecycle(deviceDescription):
value = INITIAL_SENSOR_VALUE*random.random()
while True:
delta = (INITIAL_SENSOR_VALUE * 0.10)*random.random()
sleep(SENSOR_READING_TIME_DELAY)

if POSITIVE_CHANGE_PROBABILITY > random.random():
value += delta
else:
value -= delta
createMeasurement(deviceDescription, value)

def generateSimulatedMeasurements():

for deviceDescription in sensorDevices:
if deviceDescription.c8y_id == None:
print("Ignoring device with no managed object -> " + deviceDescription.name)
continue

thread = Thread(target=sensorLifecycle, args=(deviceDescription, ))
thread.start()
print ("Lifecycle for sensor '%s' with id='%s' started."% (deviceDescription.name, deviceDescription.c8y_id))


def formatTimestamp(timestamp):
return timestamp.isoformat(timespec='milliseconds')


def submitMeasurement(measurementJson):
session.headers.update({
'Content-Type': 'application/json',
'Accept': 'application/vnd.com.nsn.cumulocity.measurement+json'
})
url = host + '/measurement/measurements'
response = session.post(url, json=measurementJson)
#print(str(response.text))
return response.status_code


if __name__ == "__main__":
for deviceDescription in sensorDevices:
deviceDescription.c8y_id = checkAndRegisterDevice(deviceDescription.name, deviceDescription.type, deviceDescription.name)

generateSimulatedMeasurements()

Binary file added measurement_generation/c8y-screenshot-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added measurement_generation/c8y-screenshot-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions measurement_generation/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# IoT Device Simulator

This script aims to showcase how to generate measurements for Cumulocity devices.
In this example, we demonstrate necessary steps to generate simulated sensor readings through
Cumulocity's REST API. This example automatically creates devices that host the generated readings.

If you haven't done so, please review the previous example [devicecreation](../devicecreation/readme.md) to understand how the devices in this demo script are generated.

Please refer to the [online documentation](https://cumulocity.com/guides/reference/rest-implementation) for further details on the API.


## Setup

Pre-requisites:
- Python (tested on Python 3.6+)
- 'json' and 'requests' packages installed (e.g. pip install xxx)
- Cumulocity tenant with Basic Authentication enabled and your user role allows for creation of new managed objects.
- devicecreation/IoTDeviceCreation.py script to automatically create sample devices in your tenant.

Open the IoTDeviceCreation.py script, and modify the host, name, and password.

## Running

- Run the python script though your console, ensuring the Python environment and required packages are available in the path.

```
>> python ./IoTDeviceSimulator.py
```

This will create two new devices: one temperature sensor device and one pressure sensor device. Note that if the devices already exist, they won't be created again. Navigate to the 'Device Management' section of your tenant and open 'All Devices'. You should see the new device created and registered.

![trigger](./c8y-screenshot-3.png)

You should also see a menu section for your devices called 'measurements'. Select this to show the current measurements being generated for each of the devices.

![trigger](./c8y-screenshot-4.png)