Movid - An Alexa skill that provides Covid-19 symptom checking and real time information.
Tags: mulesofthackathon, alexa, servicenow
Published: 2020-11-29 20:05:23

#Introduction
As we all have experienced, 2020 has been unlike any other year. The pandemic has led to much change, fear and heartache, however trying to remain positive, the pandemic has also brought with it unprecedented innovation.
I wanted to use the Hackathon as an opportunity to 'hack' together a Proof of Concept for an Alexa skill that not only would provide real time localised Covid information, but also allow users to quickly check their symptoms for Covid-19.
#Inspiration:
The inspiration for this project comes from a conversation recently with my Sister. She works in a local retirement home, and she told me how hard Covid has impacted the lives of the elderly. Its often difficult for the elderly to get the latest Covid information or learn what are the current restrictions that might apply to them. The simplicity of Alexa's voice driven interface (in combination with the Mulesoft stack) makes it an ideal solution for this use case, where physical access to a computer is difficult or not possible.  
Of course this solution, could be useful for anyone of any age.  

 
So Introducing **Movid** - A Mulesoft powered Covid Alexa app (naming is not my strength :)


Quick Video Demo of Symptom checker:

{% youtube EwwfFqyD60A %}


##Features:
**Symptom Checker**
The core feature of the Movid app is its Symptom checker capability. 

Using an official Centers for Disease Control and Prevention(CDC) Covid-19 Algorithm , the Alexa skill will ask users a predefined set of questions on their health status, and a custom Mule Flow will determine the best course of action to take.
Disclaimer: As a proof of concept, please don't take the diagnosis as medical advice. Please don't sue me! 


 

![Screenshot 2020-11-29 at 15.37.17](https://dev-to-uploads.s3.amazonaws.com/i/2oqmk8u2kmcon847t027.png)

**Record symptoms**
Once the Movid app has collected your symptoms, a user can ask the app to 'log my symptoms'. This will prompt the app to save your symptoms as a record in ServiceNow.
The use case for ServiceNow was for a scenario where users can log their symptoms quickly, and a covid response team from your company can monitor the Covid symptoms of staff etc
Really I wanted to explore the Mulesoft ServiceNow connector, as we have recently begun using this platform for IT tickets. 

**State Restriction Information**
I wanted to use the Hackathon as an opportunity to use the new Mulesoft Covid data APIs. Mulesoft has put alot of work into building an easy to use Covid API that unifies data from multiple trusted sources.
Using the policy API I was able to quickly add a feature that provides users with current restrictions for a particular state.

![Screenshot 2020-11-29 at 15.33.35](https://dev-to-uploads.s3.amazonaws.com/i/xviu1dwksums84h313ck.png)
 

**State Information**
IIn my research of APIs that could provide Covid information, I came across an interesting resource called CovidActNow.org that provides detailed state information on the US Covid situation.
With this API, I was able to bring in information on Current cases per state, infection rates and risk levels.

#Architecture
 
The approach was to use Alexa as the front end, which uses sophisticated Machine learning to understand voice commands and then translate those commands into Actions (or intents in Alexa speak).
The Mulesoft platform is then used as the glue between the Alexa skill and the various third party APIs.
The Architecture follows a standard api-led approach. Essentially all functionality is exposed via Restful endpoints. Of course by developing an api first approach makes integrating with solutions such as AWS Alexa and Servicenow much simpler.

![Screenshot 2020-11-29 at 15.48.00](https://sftpdemopoh.s3.amazonaws.com/Screenshot+2020-11-29+at+15.48.00.png)
Hi Res Img: https://sftpdemopoh.s3.amazonaws.com/Screenshot+2020-11-29+at+15.48.00.png

I have built the main logic and endpoints as a Single Cloudhub API for simplicity, rather than a microservice approach. However this architecture should meet the needs of this Proof of Concept.
 

#Implementation
**1. Check Symptoms feature:**
A user utters a command such as 'Check my symptoms', Alexa will then trigger the appropriate Intent handler for that command. 
In the Check symptoms scenario, the Alexa skill intent will ask the user a series of questions to capture their current health situation. 
Once the Movid app has captured the required information, this data will then be forwarded to the Mulesoft Cloudhub API, which will then gather the data and based on a CDC Algorithm will make a determination , which will be returned back to the user via the Alexa app.

I made the decision to encapsulate the CDC Covid algorithm logic into a separate Java class to simplify the Mule flow, and using the very convenient 'Invoke Static ' component to interact with the class.

![Screenshot 2020-11-29 at 10.48.23](https://dev-to-uploads.s3.amazonaws.com/i/xxzqbgo9fofzkhe9gh4v.png)
 
The flow is very straightforward. A 'listener' component takes the request, and a 'Transform Message' component will then collect the data from the queryparams, and this data is passed as a Json payload to the 'Invoke static' component. In this case, a static method called processSymptoms in class ProcessSymptoms.java.
Note: Beware of spaghetti code in this method, which needs to be refactored. Still I hope using the CDC Algorithm  in combination with the code,makes following the flow possible.


![Screenshot 2020-11-29 at 11.27.00](https://dev-to-uploads.s3.amazonaws.com/i/qr5aw3o4jhrotg88wxe2.png)

Full link to CDC Covid-19 protocol algorithm: https://github.com/CDCgov/covid19healthbot/blob/master/screening_protocols/latest/covid_19_protocol_algorithm.pdf   

 **2.Record Symptoms:**

The user triggers this Alexa intent by saying 'log my symptoms'. Alexa will route this intent to the lambda handler 'ReportSymptomsIntentHandler' . 
This handler will first check that the user has completed the 'Check symptoms' flow by checking for session attributes (ie if empty, means the symptom check has not been performed) If symptoms are available to send, the handler will invoke the Movid Cloudhub api, where a listener in a flow called 'RecordSymptomsFlow' will run.

![Screenshot 2020-11-29 at 18.06.47](https://dev-to-uploads.s3.amazonaws.com/i/oby9dt6e4g13i4hq78e0.png)
 


Using the Mulesoft **ServiceNow** connector, we can easily integrate with the ServiceNow platform. Using the standard pattern of configuring the ServiceNow connections details ie 

![Screenshot 2020-11-29 at 11.37.48](https://dev-to-uploads.s3.amazonaws.com/i/x08ihoxn9m5sqt8hojqt.png)

and select the 'incident' service with the insert operation ie 

![Screenshot 2020-11-29 at 11.38.32](https://dev-to-uploads.s3.amazonaws.com/i/eqv2kfasdd0gl73323dh.png)

Note: In the prior Transform Message component we need to use the ServiceNow xml format for sending data:

![Screenshot 2020-11-29 at 11.40.46](https://dev-to-uploads.s3.amazonaws.com/i/ht13qoltyf8w145zhol1.png)

Here we are taking all the symptom data, and assigning to the description variable.

Screenshot of data stored in ServiceNow: 

![Screenshot 2020-11-29 at 11.42.40](https://dev-to-uploads.s3.amazonaws.com/i/6q63bsbwpoublgkz9j61.png)

**3.Check Restrictions for State flow:**

For the Restrictions feature I use the Mulesoft State Policy API, which can provide data as to the latest restrictions for that state, such as gathering restrictions, domestic travel restrictions etc.
Note: Check out the API: https://covid-19.mulesoft-crisis-response.com/s/communityapi/a084R000037BxSeQAK/covid19-resource-portalcovid19datatrackingapi

Flow:
![Screenshot 2020-11-29 at 18.11.40](https://dev-to-uploads.s3.amazonaws.com/i/e7laezrhr8q1bnvyj6n8.png)


The flow begins by the user saying 'Check restrictions for {state}' ie Indiana.
A custom Alexa skill intent 'StateRestrictionsCheckIntent' extracts the State name from the users spoken command. This information is then passed to the AWS lambda function, finds the appropriate handler for the intent ie 'StateRestrictionsCheckIntentHandler' which then calls the custom Movid Cloudhub API passing the State Code ie IN for Indiana.

A listener component then receives the incoming GET request with the Statecode parameter, and then uses the Request component to call the Mule Covid-19 Policy API.
This API returns a json payload of State restrictions which needs to be unpacked and converted to something more human sounding for Alexa to output to the user. So using the 'Invoke static' component a method in StateRestrictions.java processes the data, and outputs those restrictions as plaintext, which the Transform component returns back to the Alexa device as output for the user to hear.

There is no complicated logic in the Java class, its main design goal is to take a list of restrictions and produce a single sentence with those restrictions.

ie Mulesoft response from : `https://localcoviddata.com/covid19/v1/high-level-policy?country=USA&state=IN`

```
{
  "Disclaimer": "The following is provided as of 2020-11-16, reported by KFF",
  "Community_regulations": {
    "Gathering_Restriction_Code": "New Limit on Large Gatherings in Place",
    "School_Closure_Code": null,
    "Non_Essential_Business_Closure_Code": "All Non-Essential Businesses Permitted to Reopen",
    "Social_Distancing_Requirement_Code": null,
    "Face_Covering_Policy_Code": "Required for General Public",
    "Bar_Restrictions_Code": "Reopened",
    "Reopening_Plan_Code": "New Restrictions Imposed",
    "Stay_at_Home_Requirement_Code": "Lifted",
    "Domestic_Travel_Restrictions_Code": "-",
    "Restaurant_Restrictions_Code": "Reopened to Dine-in Service "
  },
  "Source": "Kaiser Family Foundation"
}
```

`https://movid.us-e2.cloudhub.io/api/stateRestrictions?stateCode=IN` returns: 

```
{
  "message": "Gathering Restrictions are currently: New Limit on Large Gatherings in Place. Non essential businesses are currently: All Non-Essential Businesses Permitted to Reopen. Face Covering Policy is currently: Required for General Public. Bar Restrictions are currently: Reopened. Reopening Plans are currently: New Restrictions Imposed. The Stay at Home requirement is currently: Lifted. The Restaurant restriction requirement is currently: Reopened to Dine-in Service . "
}

```

![Screenshot 2020-11-29 at 20.02.05](https://dev-to-uploads.s3.amazonaws.com/i/a7feiu1h3mzdppjjkjhm.png)
 

***4. Information for state/ Infection level for state/ Risk levels for state.***

Using data from the CovidActNow API, a user can ask the Movid app for the latest state information, or what is the infection rate for a state.

Note: The API is free for non-commercial use, but you must request an API Key to use the API. I have included my apiKey in the source, but if you are using the CovidActNow API for other projects, please request your own key.

Again the flow is triggered by a user asking for covid information on a state, or infection levels for a state. Depending on which intent is picked up by the skill, the relevant handler is chosen in lambda. Ultimately each Alexa lambda skill will call a separate Mule Cloudhub listener.
Each of those flows will then call the covidactnow api, which returns a json payload with data corresponding to the 5 metrics. Again this data is transformed in the Movid Cloudhub API and returned back to the Alexa device, to be outputted to the user. 

Flow Diagram:

![Screenshot 2020-11-29 at 18.25.06](https://dev-to-uploads.s3.amazonaws.com/i/xwaxkflczzqckod8usth.png)

![Screenshot 2020-11-29 at 20.01.49](https://dev-to-uploads.s3.amazonaws.com/i/jrd0mczreuosn2lxz0fx.png)
 
 

CovidActNow response:
![Screenshot 2020-11-29 at 11.43.46](https://dev-to-uploads.s3.amazonaws.com/i/767tk1n8go630lj84h9a.png)


#Build It!

Github link to project: `https://github.com/pohora/MulesoftHackathon2020/tree/master/mulesofthackathon2020`
The source is broken into 2 sections , the Alexa frontend project and the backend Mule application.

To build Alexa skills you will need to create a developer account.

From the Alexa Dev console `https://developer.amazon.com/alexa/console/ask` after logging in, you will need to create a new Alexa skill.

![Screenshot 2020-11-29 at 19.02.07](https://dev-to-uploads.s3.amazonaws.com/i/opgnrsifioei9348rbt8.png)

Select Custom skill, and Alexa-hosted(python). This will create an empty skill project, with a basic Python lambda function.

From the project source, locate the file: en-US.json. 

Click on the JSON Editor menu item on the Alexa developer console, and Drag and drop the en-US.json file into the json editor.

![Screenshot 2020-11-29 at 19.05.38](https://dev-to-uploads.s3.amazonaws.com/i/mjcx58br12ktdb5yu27m.png)

You should see the Intents and Slot values for the Movid app. Be sure to Save Model and Build Model to update your project.

Next click on the Code tab:
You will need to create the following folder structure, and upload the appropriate files:

![Screenshot 2020-11-29 at 19.08.43](https://dev-to-uploads.s3.amazonaws.com/i/qtvwsg1x8uvdlprjk4p8.png)


The most important file is lambda_function.py, which is responsible for taking input from the Alexa device and firing the correct Intent. You can copy and paste from the local lambda_function.py file, or delete and replace with the local version.

Once your project code has been updated. You should be able to Save the code and then deploy the code.

#Test

Open the Test tab.
Make sure to turn on Skill testing. Ensure locale is **English(US)**

Start the Alexa simulator by entering 'open movid app'

Quickstart commands:

Check my symptoms
log my symptoms
information for {state} ie Indiana
restrictions for {state} ie Indiana

To build the Movid backend. Open the project in Anypoint Studio. Configure settings in the dev.properties file ie Servicenow account 
Deploy to Cloudhub directly from Anypoint Studio.


  

#Limitations:
Note: Even tho Im from Ireland, this app currently provides only US State data. I hope in the future to expand the app to offer data for other countries.

#Final thoughts
I really enjoyed my first Hackathon. Note to self. Dont leave the documentation until the last minute!