SmellsLikeML

Bots for Good

1/24/18

Bluetooth, Botnets, Networks, Alexa Skills, Home Automation, IoT

I've been on a home automation kick this winter, hacking the raspberry pi while learning about communications under the context of security. Hackster.io has been a great platform for getting creative in building home automation solutions under the constraints of embedded hardware. Recently, Amazon and Arduino have paired up to host the Smart Home Challenge.

Alexa seems particularly well-suited to voice controlled information retrieval applications. And so, for our next project, we considered situations where Alexa might help us out of a jam with info. A natural context could be helping to find a missing item. We will need more information available to Alexa to pull this off.

In some recent work, I've explored issuing commands to a botnet. Furthermore, we considered communications over Bluetooth. Here, I want to combine these ideas to provide Alexa the needed information to help me find my keys.

This idea relies on a couple facts: Bluetooth RSSI can be used as a proxy for distance, many people have multiple computers spread throughout their home, things we care about can be tagged with a low energy Bluetooth beacon. This idea is nothing new, consider where this group has taken it.

So the idea is to issue commands to all machines on the network to sniff for bluetooth signals and return the RSSI corresponding to a particular device identifier (BD_ADDR). Below is a simple top-level script using parallel-ssh and linux bluetooth utilities. The results list the average RSSI signal strength from each host in the botnet.


import sys
from pssh.pssh_client import ParallelSSHClient

pwd = input('>>')
addr = sys.argv[1]
usr = sys.argv[2]
hosts = ['192.168.1.3', '192.168.1.4', '192.168.1.5']
client = ParallelSSHClient(hosts, user=usr, password=pwd)

output = client.run_command('btmgmt find | 
                             grep {}'.format(addr), sudo=True)

for host in output:
    stdin = output[host].stdin
    stdin.write(pwd + '\n')
    stdin.flush()
client.join(output)

for host, host_output in output.items():
    read_lst = []
    for reading in host_output.stdout:
        if 'rssi' in reading:
            reading = str(reading).split('rssi ')[1]
            reading = reading.split(' flags')[0]
            read_lst.append(int(reading))
    try:
        print('Host: {} reading: {}'.format(host,
               sum(read_lst) / len(read_lst)))
    except:
        print('Host: {} reading: N/A'.format(host))

Now that we know we can get a noisy estimate of distance from the host, we want to consider voice control using Alexa. This post offers a good starting point for configuring Alexa to query information from other Amazon Web Services. Configure your skill to use IAM like this. From this point, we use DynamoDB and run a lambda function looking like this:


import boto3
from operator import itemgetter

dynamodb = boto3.resource('dynamodb', region_name='us-east-1')

def build_speechlet_response(title, output, reprompt_text, 
                             should_end_session):
    return {
        'outputSpeech': {
            'type': 'PlainText',
            'text': output
        },
        'card': {
            'type': 'Simple',
            'title': "SessionSpeechlet - " + title,
            'content': "SessionSpeechlet - " + output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }

def build_response(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }

def get_loc():
    table= dynamodb.Table('key_loc')
    itms = table.scan()['Items']
    location = sorted(itms, key=itemgetter('tmstmp'), 
                      reverse=True)[0]['loc']
    return location
    
def lambda_handler(event, context):
    intent_name = event['request']['intent']['name']
    if intent_name == "findkeys":
        loc = get_loc()
        message = "Your keys are in the " + loc
    else:
        message = "Unknown"
        
    speechlet = build_speechlet_response(
                      "Keys Status", message, "", "true")
    return build_response({}, speechlet)

Configuring Alexa might include sample utterances like: Find my keys, where are my keys?... and the like. Then the bluetooth sniffing botnet can create DynamoDB table items with device ID, timestamp, and estimated location.

The challenge has been reduced to pairing a device and mapping a home for reliable location estimation. For this, we will turn to building a web application similar to what is used to set up your TP-Link smart plugs. We will also be looking for ways that an arduino can be harnessed for this or related problems. Find the repo here.