Skip to content
Open
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
19 changes: 19 additions & 0 deletions ibm-iotsdk/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM python:3.7-alpine3.9

# Add the required dependencies to install psutil that are missing from alpine
# See: https://github.com/giampaolo/psutil/issues/872#issuecomment-272248943
RUN apk add gcc linux-headers libc-dev

# Begin the install proper
RUN python3 -m pip install --no-cache --upgrade pip
RUN python3 -m pip install wiotp-sdk==0.10.0 psutil
ADD ibm-iotsdk/ /opt/ibm/iotpsutil/
RUN chmod +x /opt/ibm/iotpsutil/*.py

RUN mkdir -p /config
RUN mkdir -p /ibm-iotsdk

WORKDIR /
COPY ibm-iotsdk/* /ibm-iotsdk/

ENTRYPOINT ["/ibm-iotsdk/start.sh"]
4 changes: 4 additions & 0 deletions ibm-iotsdk/config/ibm.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
WIOTP_IDENTITY_ORGID='rmboq4'
WIOTP_IDENTITY_TYPEID='RPi3B'
WIOTP_IDENTITY_DEVICEID='0001'
WIOTP_AUTH_TOKEN=XXXXXXXXXX
15 changes: 15 additions & 0 deletions ibm-iotsdk/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ibm-iotsdk/docker-compose.yml
version: "3"
services:
ibm-iotsdk:
image: hub.foundries.io/<YOUR_FACTORY_NAME>/ibm-iotsdk:latest
tmpfs:
- /run
- /var/lock
- /var/log
volumes:
- /var/run/secrets:/config
tty: true
network_mode: "host"
privileged: true
restart: always
181 changes: 181 additions & 0 deletions ibm-iotsdk/ibm-iotsdk/psutilApp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#!/usr/bin/env python

# *****************************************************************************
# Copyright (c) 2014, 2019 IBM Corporation and other Contributors.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
# *****************************************************************************

import getopt
import signal
import sys

try:
import wiotp.sdk.application
except ImportError:
# This part is only required to run the sample from within the samples
# directory when the module itself is not installed.
#
# If you have the module installed, just use "import wiotp.sdk"
import os
import inspect

cmd_subfolder = os.path.realpath(
os.path.abspath(os.path.join(os.path.split(inspect.getfile(inspect.currentframe()))[0], "../../src"))
)
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
import wiotp.sdk.application


def interruptHandler(signal, frame):
client.disconnect()
sys.exit(0)


def usage():
print(
"commandSender: Basic application connected to the IBM Internet of Things Cloud service."
+ "\n"
+ "\n"
+ "Options: "
+ "\n"
+ " -h, --help Display help information"
+ "\n"
+ " -c, --config Load application configuration file (ignore -o, -i, -k, -t options)"
+ "\n"
+ " -T, --typeId Restrict subscription to events from devices of the specified type"
+ "\n"
+ " -I, --deviceId Restrict subscription to events from devices of the specified id"
+ "\n"
)


connectedDevices = {}


def myStatusCallback(status):
global connectedDevices
if status.action == "Disconnect":
if status.device in connectedDevices:
del connectedDevices[status.device]
else:
connectedDevices[status.device] = {"type": status.typeId, "id": status.deviceId}


def printOptions():
global typeId, deviceId
print("Command List:")
print(" 1. Change target device")
if typeId == None or deviceId == None:
pass
else:
print(" 2. Set publish rate of %s:%s" % (typeId, deviceId))
print(" 3. Send message to console of %s:%s" % (typeId, deviceId))
print("(Ctrl+C to disconnect)")


def setTarget():
global typeId, deviceId, connectedDevices
deviceList = []
deviceList.append(None)
n = 0

print("Device Selection:")
print(" 0. Manually enter type and ID")
for key, device in connectedDevices.items():
deviceList.append(device)
n += 1
print(" " + str(n) + ". " + device["id"] + ":" + device["type"])

i = int(input("Choose Device >"))
print("")
if i == 0:
setTargetType()
setTargetId()
print("")
else:
typeId = deviceList[i]["type"]
deviceId = deviceList[i]["id"]


def setTargetType():
global typeId
typeId = input("Enter Device Type >")


def setTargetId():
global deviceId
deviceId = input("Enter Device Id >")


def changePublishRate():
global client, typeId, deviceId
interval = int(input("Enter Interval (seconds) >"))
print("")
client.publishCommand(typeId, deviceId, "setInterval", {"interval": interval})


def sendMessage():
global client, typeId, deviceId
message = input("Enter message to be displayed >")
print("")
client.publishCommand(typeId, deviceId, "print", "json", {"message": message})


if __name__ == "__main__":
signal.signal(signal.SIGINT, interruptHandler)

try:
opts, args = getopt.getopt(sys.argv[1:], "hc:T:I:", ["help", "config=", "typeId=", "deviceId="])
except getopt.GetoptError as err:
print(str(err))
usage()
sys.exit(2)

configFilePath = None
typeId = None
deviceId = None

for o, a in opts:
if o in ("-c", "--cfg"):
configFilePath = a
elif o in ("-T", "--typeId"):
typeId = a
elif o in ("-I", "--deviceid"):
deviceId = a
elif o in ("-h", "--help"):
usage()
sys.exit()
else:
assert False, "unhandled option" + o

client = None
options = wiotp.sdk.application.parseConfigFile(configFilePath)

try:
client = wiotp.sdk.application.ApplicationClient(options)
client.deviceStatusCallback = myStatusCallback
client.connect()
client.subscribeToDeviceStatus()
except Exception as e:
print(str(e))
sys.exit(1)

while True:
printOptions()
try:
option = int(input("%s:%s>" % (typeId, deviceId)))
print("")
if option == 1:
setTarget()
elif option == 2:
changePublishRate()
elif option == 3:
sendMessage()
except KeyboardInterrupt:
client.disconnect()
sys.exit()
154 changes: 154 additions & 0 deletions ibm-iotsdk/ibm-iotsdk/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env python

# *****************************************************************************
# Copyright (c) 2014, 2019 IBM Corporation and other Contributors.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
# *****************************************************************************

import argparse
import time
import sys
import psutil
import platform
import json
import signal
from uuid import getnode as get_mac


try:
import wiotp.sdk.device
except ImportError:
# This part is only required to run the sample from within the samples
# directory when the module itself is not installed.
#
# If you have the module installed, just use "import wiotp.sdk"
import os
import inspect

cmd_subfolder = os.path.realpath(
os.path.abspath(os.path.join(os.path.split(inspect.getfile(inspect.currentframe()))[0], "../../../src"))
)
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
import wiotp.sdk.device


def interruptHandler(signal, frame):
client.disconnect()
sys.exit(0)


def commandProcessor(cmd):
global interval
print("Command received: %s" % cmd.data)
if cmd.commandId == "setInterval":
if "interval" not in cmd.data:
print("Error - command is missing required information: 'interval'")
else:
try:
interval = int(cmd.data["interval"])
except ValueError:
print("Error - interval not an integer: ", cmd.data["interval"])
elif cmd.commandId == "print":
if "message" not in cmd.data:
print("Error - command is missing required information: 'message'")
else:
print(cmd.data["message"])


if __name__ == "__main__":
signal.signal(signal.SIGINT, interruptHandler)

# Seconds to sleep between readings
interval = 5

# Initialize the properties we need
parser = argparse.ArgumentParser(
description="IBM Watson IoT Platform PSUtil device client. For more information see https://github.com/ibm-watson-iot/iot-python/samples/psutil",
epilog="If neither the quickstart or cfg parameter is provided the device will attempt to parse the configuration from environment variables.",
)
parser.add_argument(
"-n", "--name", required=False, default=platform.node(), help="Defaults to platform.node() if not set"
)
parser.add_argument("-q", "--quickstart", required=False, action="store_true", help="Connect device to quickstart?")
parser.add_argument(
"-c",
"--cfg",
required=False,
default=None,
help="Location of device configuration file (ignored if quickstart mode is enabled)",
)
parser.add_argument("-v", "--verbose", required=False, action="store_true", help="Enable verbose log messages?")
args, unknown = parser.parse_known_args()

client = None
try:
if args.quickstart:
options = {
"identity": {
"orgId": "quickstart",
"typeId": "sample-iotpsutil",
"deviceId": str(hex(int(get_mac())))[2:],
}
}
elif args.cfg is not None:
options = wiotp.sdk.device.parseConfigFile(args.cfg)
else:
options = wiotp.sdk.device.parseEnvVars()

client = wiotp.sdk.device.DeviceClient(options)
client.commandCallback = commandProcessor
client.connect()
except Exception as e:
print(str(e))
sys.exit(1)

if args.quickstart:
print(
"Welcome to IBM Watson IoT Platform Quickstart, view a vizualization of live data from this device at the URL below:"
)
print(
"https://quickstart.internetofthings.ibmcloud.com/#/device/%s/sensor/" % (options["identity"]["deviceId"])
)

print("(Press Ctrl+C to disconnect)")

# Take initial reading
psutil.cpu_percent(percpu=False)
before_ts = time.time()
ioBefore = psutil.net_io_counters()
diskBefore = psutil.disk_io_counters()
psutil.disk_io_counters(perdisk=False, nowrap=True)
while True:
time.sleep(interval)
after_ts = time.time()
ioAfter = psutil.net_io_counters()
diskAfter = psutil.disk_io_counters()
# Calculate the time taken between IO checks
duration = after_ts - before_ts

data = {
"name": args.name,
"cpu": psutil.cpu_percent(percpu=False),
"mem": psutil.virtual_memory().percent,
"network": {
"up": round((ioAfter.bytes_sent - ioBefore.bytes_sent) / (duration * 1024), 2),
"down": round((ioAfter.bytes_recv - ioBefore.bytes_recv) / (duration * 1024), 2),
},
"disk": {
"read": round((diskAfter.read_bytes - diskBefore.read_bytes) / (duration * 1024), 2),
"write": round((diskAfter.write_bytes - diskBefore.write_bytes) / (duration * 1024), 2),
},
}
if args.verbose:
print("Datapoint = " + json.dumps(data))

client.publishEvent("psutil", "json", data)
# Update timestamp and data ready for next loop
before_ts = after_ts
ioBefore = ioAfter
diskBefore = diskAfter
Loading