GeekTalk.ai

As a proof-of-concept for integrating with ChatGPT and WordPress, I’ve implemented GeekTalk.ai. This is a website that provides a AI generated content and insights related to artificial intelligence (AI) and its various applications. It serves as a hub for AI enthusiasts, researchers, and professionals to see how AI generated content can work based on a variety of prompts. The website features a blog section where AI writes articles covering diverse Geeky topics, such as machine learning, natural language processing, computer vision, and robotics.

Source code for the website is available on GitHub at https://github.com/jfenner/geektalk.ai.

Information Analysis

Information Analysis is the study of information and what is represents.  You might also know it under the terms of data mining, information gathering, intelligence gathering, or intelligence assessment, just to name a few.

This blog entry focuses on a method for un-anonymizing celluar usage based on an actors tendency to use multiple devices for legitimate vs. illegitimate activities.

Scenario: The primary actor (PA) runs a legitimate business and uses cell phone 1 (CP1) for daily communication of business.  This phone is registered to PA.  This takes place in multiple locations through the city where PA lives.  PA also runs an illegal money laundering business and uses his legitimate business to cover for it.  In order to keep the two separate, he uses a prepaid cell phone (CP2) for all money laundering business.  The assumption is that by using a prepaid cell phone, it will not be able to be linked back to him.

Task: Given that we suspect the PA is conducting illegal activities, we want to be able to tie those activities back to PA2.

Solution: The solution lies in the use of cellular towers and the logging of information related to phone calls.  Assuming that cell phone activity for a given tower or set of towers can be obtained, a cross reference algorithm is devised which will link the activity of the PA between cell towers and phones.

For example, during any particular day, the PA makes calls on CP1 which is covered by cell sites 449, 2132, and 474.  Since we know that CP1 is registered to the PA, we can track these activities:

Date/TimeCell SiteOriginating NumberDestination NumberDuration (minutes)
2013-11-10 08:02:33449802-310-1234817-467-33115
2013-11-10 08:32:182132802-310-1234802-846-21115
2013-11-10 10:12:122132802-310-1234202-233-32325
2013-11-10 13:11:22474802-310-1234802-355-23145
2013-11-10 17:30:01449802-310-1234603-453-12345

Now to identify the CP2 usage, we focus on the cell sites that have been used by the PA during this day.  If we plot out the cell site usage, time, and location we can create a probability map of activity for the PA with the probability that they are within range of a certain cell site at any given time.  This is based solely on a linear distribution of probability between any two sites based on the progression of time, and the straight-line connectivity between the cell sites.

Once we have the probability map defined, then we can take a look at all of the other cell phone calls from those cell sites during the time period and prescribe a probability that one of those phones is CP2.

What the algorithm takes into consideration is based on the probability of time that the PA is within access to any one cell site, the phone calls from cell numbers to that site and that time will be assigned a probability.  If we look at the summed probabilities of the cell numbers across all the sites, then we can establish which other cell phones have a high probability of being CP2.

Once CP2 has been identified, a wiretap order can be executed to obtain the information required for prosecution.
Conclusion: This algorithm works best under the following scenarios:

  • The PA travels around enough to use multiple cell sites for both CP1 and CP2
  • The PA uses both cell phones multiple times during the day
  • The PA does not have both cell phones on all the time during the day

Of course, the alternative if both cell phones are on all the time during the day is to just cross-correlate registration of the cells phones with the local towers.  Any two that register at or near the same time have a high probability of being with the PA.While not a 100% solution, this algorithm provides a high probability of locating multiple linked cell phones for specific scenarios.

Website Security Tip

In hopes of sharing some of my knowledge in the Network and Security realm, I thought it would be fun to post tips.  

For anyone who runs a website, site security is something that you are going to have to address in one way or another.  This might be proactively looking at the site from an external user point of view, or responding to a security incident in which you site has been hacked or compromised in some fashion.

Like all security, be it network, physical, or personal, there is no one silver bullet that is going to handle all of your needs.  For site security, this means addressing things such as:

  1. Physical security of the system on which the website is housed
  2. Network security of how the system is connected to the outside world
  3. System security for the operating system that is is running on, including making sure security patches and subsystem components are up-to-date.
  4. Site compartmentalization, i.e., if someone breaks in to one part of the site, how much access might they easily gain to other parts (database, other servers, etc.).

This first tip focuses on what you can do about system security of your site.  Doing an online scan of your site will help determine if any malware or other malicious code is attached to your site in anyway.  This is a good indicator if your site has been compromised.  Some good online scanners include:

They all have free options for running them manually, which you can easily do on a regular basis.  Or, if you have a larger number of domains or want deeper scans for your websites, most have paid options as well.

An Alexa Skill for Integration with Weather Underground

When using Alexa with my Echo Dot, I found that the integrated weather forecast was not that accurate for my location.  Where I live, we have a significant microclimate, and getting the accurate forecast for my location is best done through Weather Underground.  I have my own personal weather station which provides a good forecast, and I wanted to link that in to my Alexa Flash briefing.  Unfortunately, there doesn’t appear to be a Skill for that at this time, so I went through the process of creating my own and wanted to share details of that here.

The basic steps to set this up are as follows:

  • Get a Weather Underground API key to get the forecast and alert data in JSON format
  • Setup an Amazon Lambda function to read the WU API and translate it into a format that Alexa can understand for the Flash Briefing
  • Create an Amazon API interface to call the Lambda function
  • Setup the Alexa Skill for a Flash Briefing item which uses the API interface just setup
  • Turn on the skill on your Amazon Echo Dot (or other Alexa device)

Get a Weather Underground API key 

Sign for weatherunderground.com if you haven’t already, and login to generate an API key.  The process is simple, and free for under 500 calls per month.  Just be sure and sign up for the “Cumulus” plan to get both forecast and alerts.  Once you have the API key, you’ll be using two of the API calls to get the information for Alexa.  These are:

http://api.wunderground.com/api/xxxxxxxxxxxxxxx/forecast/q/pws:KVTSTARK3.json

http://api.wunderground.com/api/xxxxxxxxxxxxxxx/alerts/q/pws:KVTSTARK3.json

where xxxxxxxxxxxxxxx will be your WU API key.  

For the actual location, you will want to replace q/pws:KVTSTARK3.json with the refined location for you via weather underground.  To get this, go to the weather underground home page and look at the full forecast for your location.  If you have a personal weather station, you can just substitute KVTSTART3 with your PWS station id.  If not, then look at the URL of the full forecast, which will be something like this:

https://www.wunderground.com/q/zmw:05487.1.99999?sp=KVTBRIST11

and then replace the part of the url including and after the q (q/zmw:05487.1.99999?sp=KVTBRIST11 in the above example) with q/pws:KVTSTARK3 where KVTSTARK3 is your PWS station id.

Test out the urls in your browser to make sure you’re getting back valid JSON, and then you’re ready to move on to the next step.

Setup an Amazon Lambda function

Amazon Lambda functions provide quick and easy ways to implement snippets of code that are only executed when called.  They are efficient ways to handle API implementations without having a full-blown server running, and are only charged on the per-usage basis.

The assumption here is that you’ve already setup an AWS account.  From the AWS console, go to the Lambda service (https://console.aws.amazon.com/lambda/home).  You’ll want to create a blank lambda function without any triggers at this time.  Call it something like getWUForecast and use the Node.js 4.3 runtime.    For the inline code, you can use the following code snippet:

'use strict';
console.log('Loading function');

exports.handler = (event, context, callback) => {

    var http = require('http');

    var alertsurl = "http://api.wunderground.com/api/xxxxxxxxxx/alerts/q/pws:KVTSTARK3.json"

    var forecasturl = "http://api.wunderground.com/api/xxxxxxxxxx/forecast/q/pws:KVTSTARK3.json"

    // Get alerts first

    http.get(alertsurl, function(res) {

        res.setEncoding('utf8');

        var rawData = "";

        res.on('data', (chunk) => {

            rawData += chunk;

        });

        res.on('end', () => {

            var alert = JSON.parse(rawData);

            // Now do the forecast portion
            var obj = doForecast(http, forecasturl, alert, function(obj) {

                callback(null, obj);

            });

        });

    }).on('error', function(e) {

        console.log("Got error: " + e.message);

        context.done(null, 'FAILURE');

    });      

};

// Handle forecast API call
function doForecast(http, url, alert, callback) {

    // Add in the alert to the beginning of the flash message     
    var alertObj = null;

    if (alert.alerts.length > 0) {

        console.log(alert.alerts[0].description);

        console.log(alert.alerts[0].message);

        alertObj = {

                "uid": "00000000-0000-1000-0000-000000000001",

                "updateDate":  new Date().toISOString(),

                "titleText": alert.alerts[0].description,

                "mainText": alert.alerts[0].message,

                "redirectionUrl": "https://www.weatherunderground.com"

        }

    }

    // Get the info from Weather Underground

    http.get(url, function(res) {

        res.setEncoding('utf8');

        var rawData = "";

        res.on('data', (chunk) => {

            rawData += chunk;

        });

        res.on('end', () => {

            var forecast = JSON.parse(rawData);

            // Put together all the next 4 forecast periods
            // TBD: Ideally we should check to make sure we have 4 items in the array

            var curForecast = "The current forecast for " + forecast.forecast.txt_forecast.forecastday[0].title;

            curForecast += " calls for ";

            curForecast += forecast.forecast.txt_forecast.forecastday[0].fcttext + " ";

            curForecast += "For " + forecast.forecast.txt_forecast.forecastday[1].title;

            curForecast += " " + forecast.forecast.txt_forecast.forecastday[1].fcttext + " ";

            curForecast += "For " + forecast.forecast.txt_forecast.forecastday[2].title;

            curForecast += " " + forecast.forecast.txt_forecast.forecastday[2].fcttext + " ";

            curForecast += "For " + forecast.forecast.txt_forecast.forecastday[3].title;

            curForecast += " " + forecast.forecast.txt_forecast.forecastday[3].fcttext + " ";

            // Setup the results for Alexa feed

            var forecastObj = {

                "uid": "00000000-0000-1000-0000-000000000002",

                "updateDate":  new Date().toISOString(),

                "titleText": forecast.forecast.txt_forecast.forecastday[0].title,

                "mainText": curForecast,

                "redirectionUrl": "https://www.weatherunderground.com"

               };

            var obj = null;

            if (alertObj !== null) {

                obj = [alertObj, forecastObj];

            } else {

                obj = [forecastObj];

            }

            callback(obj); 

        });

    }).on('error', function(e) {

        console.log("Got error: " + e.message);

    });

    console.log('end request to ' + url);   

}


After you’ve got the inline code, you also need to setup some config info.  Under Role, select to Create new role from template(s).  Give the role a name, such as WULambaRole and choose Simple Microservice Permissions as the template.  Everything else you can leave as defaults and then Next and Create Function.

You’re now ready to integrate the lambda function to the API.

Create an Amazon API interface

Go to the Amazon console and navigate to the API Gateway services.  From there select Create API and give it a name such as WeatherUndergroundAPI.  Select Create API to create it.  Now select the root of the API (/) and under Action, select Create Method.  Select a GET method, a Lambda region where you created your Lambda function (probably us-east-1 if you didn’t specify anything different before).  Enter your Lambda function name you created above (getWUForecast in the example) and save it.

Once the saving is complete, click on the GET method and then the TEST button to test it out.  If all is well you’ll get a 200 status code and a JSON response that is formatted for Alexa.

Now you’ll need to deploy the API.  Click on Actions, Deploy API.  Give it a new stage name of Production and then Deploy it.  Make not of the Invoke URL which will be something like this:

Invoke URL: https://xxxxxx.execute-api.us-east-1.amazonaws.com/Production

You’ll need that URL to link to the Alexa Skill.

Setup the Alexa Skill

Now you’ll need an Amazon Developer Account to create the Alexa skill in.  Go to the developer Alexa skills page and Add A New Skill.  You’ll want to select a Skill Type of Flash Briefing Skill API and then give it a name, such as Weather Underground Skill.  Next through until you get to the Configuration tab and enter a custom error message.  Something like “The Weather Underground Skill is not currently available”.

Now click on Add A New Feed  and a preamble to describe the feed, such as “Here is your weather briefing for Starksboro, VT”.  Name the feed WeatherUnderground with content type of Text.  Select a genre of Weather and then enter the API Invoke URL you have from above in the URL field.  Click on Save and it will validate the link and continue on.

Next on the Test tab, flip the switch to ON so that you can integrate it with your Alexa.  Next on through and Save your skill.

Don’t worry about publishing the skill, as this is just setting it up for your own personal use.  If you publish it, you run the risk of using up your Weather Underground API calls pretty quickly, as everyone will be using your API key then.

Turn on the skill

Finally, you need to turn the skill on in Alexa.  Go to the Alexa and navigate to Skills and then Your Skills.  The new skill will show up in the list, just click on it and then enable it.  After it’s enabled, you can go to Manage in Flash Briefing to turn it on and set the order it shows up.  When it’s ready, you can just go to Alexa and say “Give me my Flash Briefing” and it should all work.

That’s it.  Hope this helps you in setting up a simple Alexa skill and doing some integration to Weather Underground!