Making of weather-alert (1): Create Azure Functions with Visual Studio Code

weather-alert

weather-alert analyzes and tweets if the local weather conditions are favorable for outdoor activities on the next day.

Steps:

  1. Checks the weather forecast on OpenWeatherMap
  2. Analyze the weather conditions for outdoors activities
  3. Posts a tweet if the weather conditions are favorable

VSCode setup

Install the Azure Functions extension in VS Code and sign in to Azure, as described in the extension page.

Install the Azure Functions Core Tools, version 1.x or 2.x (in preview).

npm i -g azure-functions-core-tools

GetWeather function with Timer trigger

The GetWeather function will retrieve the weather forecast by calling the Open Weather Map API.

Using the extension UI

Functions_VSCode

Create a new function project using the folder icon, a function project groups multiple functions together. Create a new function using the lighting icon.

Using the terminal

Run the following command to create the functions project:

func init weather-alert

Warning: unable to find git on the path

Change directory to this folder and run the following command to create the function:

func new --name GetWeather --language JavaScript --template "Timer Trigger" --name WeatherTimerTrigger

This command will create a function named “GetWeather” in JavaScript that is triggered by a timer.

Here is a detailed description about the folder structure.

By default, the timer triggers the function every 5 minutes. The schedule format is in CRON expression and I will use the CRON Maker to change this default setting. I want to trigger it once a day in the morning so I change the “schedule” in function.json to “0 0 7 * * *”.

PostAlert function with HTTP trigger

If the weather is favorable for the next day, the PostAlert function will tweet a message.

So let’s create the new function.

func new --name PostAlert --language JavaScript --template "HTTP Trigger" --name TwitterHTTPTrigger

This command will create a function named “PostAlert” in JavaScript that is triggered by HTTP.

Debug the functions locally with VS Code

Run the following command to debug the function in VSCode:

func host start --debug vscode

Error: Missing value for AzureWebJobsStorage in local.settings.json. This is required for all triggers other than HTTP. You can run ‘func azure functionapp fetch-app-settings ‘ or specify a connection string in local.settings.json.

This command will not work because I do not have a storage set up on Azure yet:

func azure functionapp fetch-app-settings weather-alert

Error: Sequence contains no elements

AzureWebJobsStorage

The Azure Functions runtime uses this storage account connection string for all functions except for HTTP triggered functions. The storage account must be a general-purpose one that supports blobs, queues, and tables. See Storage account and Storage account requirements.

Key Sample value
AzureWebJobsStorage DefaultEndpointsProtocol=https;AccountName=[name];AccountKey=[key]

Here is a more detailed description about the local settings file.

Missing AzureWebJobsStorage error

To solve this problem, I can either install the storage emulator or use the Azure Storage, as described in this post. I chose to use the storage emulator. Here is a more detailed description about the storage emulator, including how to install and use it.

I install the storage emulator, start the emulator and initialize the storage instance:

AzureStorageEmulator.exe init /server <SQLServerInstance>

SqlError: System.Data.SqlClient.SqlError: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)
No available SQL Instance was found.
One or more initialization actions have failed. Resolve these errors before attempting to run the storage emulator again.
Error: No available SQL Instance was found.

The problem is that I do not have any SQL instance on my machine so I chose the easy way: install VS2017 Community Edition and select SQL Express localDB. After restarting the computer and starting the emulator, the instance is found, a new dayabase AzureStorageEmulator55 is created, the access rights are granted and the emulator is successfully started.

Finally, I change the setting AzureWebJobsStorage in local.settings.json to “UseDevelopmentStorage=true”. Running the command again starts the host, finds the functions in the project and the debugger is listening.

[01-Jun-18 04:25:18 PM] Reading host configuration file 'C:\_Repo\weather-alert\host.json'
[01-Jun-18 04:25:18 PM] Host configuration file read:
[01-Jun-18 04:25:18 PM] {}
[01-Jun-18 04:25:18 PM] Starting Host (HostId=xxx-1863931837, Version=1.0.11702.0, InstanceId=0d641a92-6409-4231-b371-ac9501366c49, ProcessId=9760, AppDomainId=1, Debug=False, ConsecutiveErrors=0, StartupCount=1,
FunctionsExtensionVersion=)
Listening on http://localhost:7071/
Hit CTRL-C to exit...
[01-Jun-18 04:25:19 PM] Loaded custom extension 'BotFrameworkConfiguration'
[01-Jun-18 04:25:19 PM] Loaded custom extension 'SendGridConfiguration'
[01-Jun-18 04:25:19 PM] Loaded custom extension 'EventGridExtensionConfig'
[01-Jun-18 04:25:19 PM] Host secret 'eventgridextensionconfig_extension' for 'systemkeys' Created.
[01-Jun-18 04:25:19 PM] registered EventGrid Endpoint = http://localhost:7071/admin/extensions/EventGridExtensionConfig
[01-Jun-18 04:25:19 PM] Generating 2 job function(s)
[01-Jun-18 04:25:19 PM] Found the following functions:
[01-Jun-18 04:25:19 PM] Host.Functions.GetWeather
[01-Jun-18 04:25:19 PM] Host.Functions.PostAlert
[01-Jun-18 04:25:19 PM]
[01-Jun-18 04:25:19 PM] Host initialized (1297ms)
[01-Jun-18 04:25:20 PM] Executing HTTP request: {
[01-Jun-18 04:25:20 PM] "requestId": "40ce515c-7311-4c4b-8089-853a0c758156",
[01-Jun-18 04:25:20 PM] "method": "GET",
[01-Jun-18 04:25:20 PM] "uri": "/"
[01-Jun-18 04:25:20 PM] }
[01-Jun-18 04:25:20 PM] Executed HTTP request: {
[01-Jun-18 04:25:20 PM] "requestId": "40ce515c-7311-4c4b-8089-853a0c758156",
[01-Jun-18 04:25:20 PM] "method": "GET",
[01-Jun-18 04:25:20 PM] "uri": "/",
[01-Jun-18 04:25:20 PM] "authorizationLevel": "Anonymous",
[01-Jun-18 04:25:20 PM] "status": "OK"
[01-Jun-18 04:25:20 PM] }

Http Functions:

PostAlert: http://localhost:7071/api/PostAlert

launch.json for VSCode configured.
Debugger listening on [::]:5858
[01-Jun-18 04:25:25 PM] The next 5 occurrences of the schedule will be:
[01-Jun-18 04:25:25 PM] 02-Jun-18 07:00:00 AM
[01-Jun-18 04:25:25 PM] 03-Jun-18 07:00:00 AM
[01-Jun-18 04:25:25 PM] 04-Jun-18 07:00:00 AM
[01-Jun-18 04:25:25 PM] 05-Jun-18 07:00:00 AM
[01-Jun-18 04:25:25 PM] 06-Jun-18 07:00:00 AM
[01-Jun-18 04:25:25 PM]
[01-Jun-18 04:25:25 PM] Host started (7034ms)
[01-Jun-18 04:25:25 PM] Job host started
[01-Jun-18 04:25:28 PM] Host lock lease acquired by instance ID '00000000000000000000000007ABE90E'.

The next 5 occurrences of the schedule for the timer-triggered GetWeather function is displayed. The HTTP-triggered PostAlert function is available on http://localhost:7071/api/PostAlert.

Source code

The source code can be found here on GitHub.

To be continued…

Next up we are going to implement the functions to call the weather API, analyze the weather and post a tweet. Blog post coming soon. 🙂