Close

Custom Scripts - Internet Speed Test

A project log for Project Stark Framework

This is a YET ANOTHER attempt at an "Iron Man" Jarvis-like system

robweberrobweber 07/13/2016 at 15:150 Comments

So far all the functionality I've shown has been based on the ability to write functionality into a StarkModule class that allows for actions to be run. This is the use case for the framework about 90% of the time, but what about those use cases where a Java based library isn't available, or really even necessary? Sometimes you just need a quick call out to a local script, or you want to monitor another program entirely via it's standard output.

Enter the Scripts Module. This module has one defined action, Script.Run().

As you can see in the screenshot there are a few arguments that the Run() method will accept. The two required are the command to run, and the event to trigger when the script completes. This uses the Java ProcessBuilder class to kick off another process and then return the output, generating the given event. The optional commands can further customize how this process runs.

Setting up this action in a job allows you to call out to custom written functions, or just external programs, to run tasks. When they complete the resulting message will be returned to the Stark Framework as an event.

Internet Speed Test

I've been having some issues with my ISP and my internet speed. The speed I'm paying for is often not the speed I get - by a lot. I wanted a quick way to test my internet speed without going to speedtest.net all the time - especially since I'm often not at home and want this done remotely. I found this awesome python script called speedtest-cli. It does exactly what it sounds like, runs the speed test via the CLI in a python wrapper and returns the result. Perfect.

Once I had this working I wanted to turn it into a Stark task using the Script.Run method. This took a little work. First I had to build a python wrapper for the script.

import subprocess
import json

#get the speed test data
cmd = ['python','speedtest_cli.py','--simple','--share']
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out,err = process.communicate()

#results returned as a series of newlines
output_array = out.splitlines()
result = {'message':'Internet speed test has completed, ' + output_array[1] + ' and ' + output_array[2],'data':{'media_picture_url':output_array[3][15:]}}

#return result to Stark
print(json.dumps(result))

Stark expects external scripts to return a JSON object so I needed to wrap the output that way. The returned result looks something like this (note the picture_url in the data, this can be used by Clients that can display pictures)

{"message": "Internet speed test has completed, Download: xxx Mbit/s and Upload: xxx Mbit/s", "data": {"media_picture_url" : "http://picuturl here" } }
So once this was working I setup the Stark Job using the Script.Run method and tested it using an instant messenger client. One of the many Stark Clients I've written is an integration with XMPP servers via the Smack library. In order to talk with the Stark Framework via this connection your IM username must be available as a field in the Stark User setup (more on users and security in a later post).

Looking at the IM window notice the phrase "let me know when that is done". This triggers a job I call the "Inferred One Time Monitor". The idea behind it is that Stark sets up a one time monitor for the event we expect, SpeedTest.Complete, and forwards the result to the "work" client group. This is because my IM client runs off my work computer - running this remote. Stark is able to infer all this based on the previously run command and then pull the event needed from that result. Once the event is triggered the monitor disappears. You could set up a permanent monitor for that event to a specific client - like a text message; but I prefer using the inferred command as I could run this from anywhere and then just get the message forwarded where I need it.

The Scripts Module is a very flexible module written to extend the Stark Framework into other areas without having to always write a custom StarkModule class. This is very useful for integrating with other libraries, or just accessing one-off bash scripts that you need to trigger on demand.

Discussions