Created
February 27, 2018 10:08
-
-
Save averagehuman/c66e95ff01f9b8a3473970649c228c2c to your computer and use it in GitHub Desktop.
Register an IoT device with IBM Watson IoT using curl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
command -v jq >/dev/null 2>&1 || { | |
echo >&2 "ERROR: jq is not installed. This is required for parsing json responses."; exit 1; | |
} | |
if [ $(id -u) != 0 ] || [ ! -w /etc ]; then | |
echo "ERROR: Requires root privileges (or write permissions to /etc). Try again with sudo." | |
exit 1 | |
fi | |
function usage_and_exit() { | |
cat <<EOF | |
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
Register an IoT device with the IBM Watson IoT service. | |
If no specific device id is given, then the identifier in /etc/machine-id is | |
used if that file exists, otherwise a hash is generated from the concatenation | |
of all the mac addresses of any network interface returned by ifconfig. | |
Usage | |
----- | |
ibm-iot-register-device <orgId> <deviceType> <deviceTypeDescription> [deviceId] | |
Example | |
------- | |
ibm-iot-register-device "skynet" "coffee-maker" "A self-aware espresso machine." | |
Api Credentials | |
--------------- | |
The script calls the IBM IoT api via curl and this requires valid api | |
credentials to be passed in each request. These credentials must be in file: | |
/etc/watson/<orgId>/.credentials | |
This should contain variables 'apiKey' and 'apiToken' as follows: | |
apiKey="x-yyyyyy-zzzzz" | |
apiToken="not-a-secret" | |
Device Config | |
------------- | |
If successful, a configuration file for the device is written to: | |
/etc/watson/<orgId>/devices/<deviceType>/<deviceId>.cfg | |
This configuration file is suitable for use by ibmiotf, the ibm-watson-iot | |
python client. | |
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
EOF | |
exit 1 | |
} | |
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
# Setup | |
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
orgId="$1" | |
deviceType="$2" | |
deviceTypeDesc="$3" | |
deviceId="$4" | |
deviceConfigFile= | |
credentials= | |
apiKey= | |
apiToken= | |
rootUrl= | |
addDeviceTypeUrl= | |
addDeviceUrl= | |
[[ -n "$orgId" ]] || usage_and_exit | |
[[ -n "$deviceType" ]] || usage_and_exit | |
[[ -n "$deviceTypeDesc" ]] || usage_and_exit | |
# If no fourth parameter was passed, determine a unique device id from the system | |
[[ -n "$deviceId" ]] || deviceId="$(grep -o -m 1 '^.\+' /etc/machine-id)" | |
[[ -n "$deviceId" ]] || deviceId="$(ifconfig | grep -oP 'HWaddr \K.*' | sed 's/://g' | sha256sum | cut -c -24)" | |
[[ -n "$deviceId" ]] || { echo "ERROR: couldn't determine the device id.";exit 1; } | |
deviceConfigFile="/etc/watson/$orgId/devices/$deviceType/$deviceId.cfg" | |
credentials="/etc/watson/$orgId/.credentials" | |
# Don't clobber existing config file | |
[[ ! -e $deviceConfigFile ]] || { echo "ERROR: a configuration already exists for this device type ($deviceConfigFile)";exit 1; } | |
# Credentials file must exist and contain the required fields | |
[[ -s $credentials ]] || { echo "ERROR: credentials file does not exist or is empty ($credentials).";exit 1; } | |
apiKey=$(grep -Po -m 1 '(?<=^apiKey=).*$' "$credentials" | sed "s/[\"\']//g") | |
apiToken=$(grep -Po -m 1 '(?<=^apiToken=).*$' "$credentials" | sed "s/[\"\']//g") | |
[[ -n "$apiKey" ]] || { echo "ERROR: missing credentials field - apiKey"; exit 1; } | |
[[ -n "$apiToken" ]] || { echo "ERROR: missing credentials field - apiToken"; exit 1;} | |
# Construct api endpoints | |
rootUrl="https://$orgId.internetofthings.ibmcloud.com/api/v0002" | |
addDeviceTypeUrl="$rootUrl/device/types" | |
addDeviceUrl="$rootUrl/bulk/devices/add" | |
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
# Create Device Type | |
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
payload='{ | |
"id": "'"$deviceType"'", | |
"description": "'"$deviceTypeDesc"'", | |
"classId": "Device" | |
}' | |
statusCode=$(curl -X "POST" \ | |
-H "Content-Type: application/json" \ | |
-u "$apiKey:$apiToken" \ | |
-d "$payload" \ | |
-s \ | |
-o /dev/null \ | |
-w "%{http_code}" \ | |
$addDeviceTypeUrl) | |
if [ $statusCode = "201" ]; then | |
echo "Created device type $deviceType." | |
elif [ $statusCode = "409" ]; then | |
echo "Device type $deviceType already exists. Continuing." | |
else | |
echo "ERROR: Unexpected error when creating device type. Error status was $statusCode." | |
exit 1 | |
fi | |
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
# Create Device | |
#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | |
payload='[ | |
{ | |
"typeId": "'"$deviceType"'", | |
"deviceId": "'"$deviceId"'" | |
} | |
]' | |
response=$(curl -X "POST" \ | |
-H "Content-Type: application/json" \ | |
-u "$apiKey:$apiToken" \ | |
-d "$payload" \ | |
-s \ | |
$addDeviceUrl) | |
# The expected response body is a json list with one item: | |
# | |
# [{"typeId":"screenly-server","deviceId":"test","success":true,"authToken":"olc6ChFpuhEz"}] | |
# | |
# Response if a device of that type and id already exists: | |
# | |
# [{"typeId":"screenly-server","deviceId":"test","success":false}] | |
# | |
# Parse the response with jq in order to get success status and auth token. | |
success=$(echo $response | jq '.[0].success') | |
authToken=$(echo $response | jq '.[0].authToken' | sed 's/"//g') | |
if [[ $success = "true" && $authToken != "null" ]]; then | |
mkdir -p $(dirname $deviceConfigFile) | |
(cat <<EOF | |
[device] | |
domain=internetofthings.ibmcloud.com | |
port=8883 | |
org=$orgId | |
type=$deviceType | |
id=$deviceId | |
auth-method=token | |
auth-token=$authToken | |
clean-session=true | |
EOF | |
) > $deviceConfigFile && echo "SUCCESS: wrote config file for device - $deviceConfigFile" | |
else | |
echo "ERROR: Unable to create device $orgId:$deviceType:$deviceId. It may already exist." | |
exit 1 | |
fi | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment