diff --git a/4-manufacturing/lessons/2-check-fruit-from-device/README.md b/4-manufacturing/lessons/2-check-fruit-from-device/README.md index 1de30bf0..69e92f0f 100644 --- a/4-manufacturing/lessons/2-check-fruit-from-device/README.md +++ b/4-manufacturing/lessons/2-check-fruit-from-device/README.md @@ -66,7 +66,7 @@ When you are happy with an iteration, you can publish it to make it available to Iterations are published from the Custom Vision portal. -1. Launch the Custom Vision portal at [CustomVision.ai](https://customvision.ai) and sign in if you don't have it open already. +1. Launch the Custom Vision portal at [CustomVision.ai](https://customvision.ai) and sign in if you don't have it open already. Then open your `fruit-detector` project. 1. Select the **Performance** tab from the options at the top diff --git a/6-consumer/lessons/2-language-understanding/README.md b/6-consumer/lessons/2-language-understanding/README.md index a217a0c8..fc987b71 100644 --- a/6-consumer/lessons/2-language-understanding/README.md +++ b/6-consumer/lessons/2-language-understanding/README.md @@ -348,10 +348,11 @@ Rather than calling LUIS from the IoT device, you can use serverless code with a This loads the values you added to the `local.settings.json` file for your LUIS app, creates a credentials object with your API key, then creates a LUIS client object to interact with your LUIS app. -1. This HTTP trigger will be called passing the text to understand as an HTTP parameter. These are key/value pairs sent as part of the URL. For this app, the key will be `text` and the value will be the text to understand. The following code extracts the value from the HTTP request, and logs it to the console. Add this code to the `main` function: +1. This HTTP trigger will be called passing the text to understand as JSON, with the text in a property called `text`. The following code extracts the value from the body of the HTTP request, and logs it to the console. Add this code to the `main` function: ```python - text = req.params.get('text') + req_body = req.get_json() + text = req_body['text'] logging.info(f'Request - {text}') ``` @@ -448,9 +449,18 @@ Rather than calling LUIS from the IoT device, you can use serverless code with a 404 is the status code for *not found*. -1. Run the function app and test it out by passing text to the URL. URLs cannot contain spaces, so you will need to encode spaces in a way that URLs can use. The encoding for a space is `%20`, so replace all the spaces in the text with `%20`. For example, to test "Set a 2 minutes 27 second timer", use the following URL: +1. Run the function app and test it out using curl. - [http://localhost:7071/api/text-to-timer?text=Set%20a%202%20minutes%2027%20second%20timer](http://localhost:7071/api/text-to-timer?text=Set%20a%202%20minutes%2027%20second%20timer) + ```sh + curl --request POST 'http://localhost:7071/api/text-to-timer' \ + --header 'Content-Type: application/json' \ + --include \ + --data '{"text":""}' + ``` + + Replace `` with the text of your request, for example `set a 2 minutes 27 second timer`. + + You will see the following output from the functions app: ```output Functions: @@ -465,6 +475,20 @@ Rather than calling LUIS from the IoT device, you can use serverless code with a [2021-06-26T19:45:53.746Z] Executed 'Functions.text-to-timer' (Succeeded, Id=f68bfb90-30e4-47a5-99da-126b66218e81, Duration=1750ms) ``` + The call to curl will return the following: + + ```output + HTTP/1.1 200 OK + Date: Tue, 29 Jun 2021 01:14:11 GMT + Content-Type: text/plain; charset=utf-8 + Server: Kestrel + Transfer-Encoding: chunked + + {"seconds": 147} + ``` + + The number of seconds for the timer is in the `"seconds"` value. + > 💁 You can find this code in the [code/functions](code/functions) folder. ### Task - make your function available to your IoT device diff --git a/6-consumer/lessons/2-language-understanding/code/functions/smart-timer-trigger/text-to-timer/__init__.py b/6-consumer/lessons/2-language-understanding/code/functions/smart-timer-trigger/text-to-timer/__init__.py index 84d0df46..d15d6e68 100644 --- a/6-consumer/lessons/2-language-understanding/code/functions/smart-timer-trigger/text-to-timer/__init__.py +++ b/6-consumer/lessons/2-language-understanding/code/functions/smart-timer-trigger/text-to-timer/__init__.py @@ -15,7 +15,9 @@ def main(req: func.HttpRequest) -> func.HttpResponse: credentials = CognitiveServicesCredentials(luis_key) client = LUISRuntimeClient(endpoint=endpoint_url, credentials=credentials) - text = req.params.get('text') + req_body = req.get_json() + text = req_body['text'] + logging.info(f'Request - {text}') prediction_request = { 'query' : text } prediction_response = client.prediction.get_slot_prediction(app_id, 'Staging', prediction_request) diff --git a/6-consumer/lessons/3-spoken-feedback/code-spoken-response/pi/smart-timer/app.py b/6-consumer/lessons/3-spoken-feedback/code-spoken-response/pi/smart-timer/app.py index 1b3daae3..50290b21 100644 --- a/6-consumer/lessons/3-spoken-feedback/code-spoken-response/pi/smart-timer/app.py +++ b/6-consumer/lessons/3-spoken-feedback/code-spoken-response/pi/smart-timer/app.py @@ -6,8 +6,6 @@ import time import wave import threading -from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse - from grove.factory import Factory button = Factory.getButton('GPIO-HIGH', 5) @@ -45,13 +43,6 @@ def capture_audio(): speech_api_key = '' location = '' language = '' -connection_string = '' - -device_client = IoTHubDeviceClient.create_from_connection_string(connection_string) - -print('Connecting') -device_client.connect() -print('Connected') def get_access_token(): headers = { @@ -83,6 +74,28 @@ def convert_speech_to_text(buffer): else: return '' +def get_timer_time(text): + url = '' + + body = { + 'text': text + } + + response = requests.post(url, json=body) + + if response.status_code != 200: + return 0 + + payload = response.json() + return payload['seconds'] + +def process_text(text): + print(text) + + seconds = get_timer_time(text) + if seconds > 0: + create_timer(seconds) + def get_voice(): url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/voices/list' @@ -167,18 +180,10 @@ def handle_method_request(request): if seconds > 0: create_timer(payload['seconds']) - method_response = MethodResponse.create_from_method_request(request, 200) - device_client.send_method_response(method_response) - -device_client.on_method_request_received = handle_method_request - while True: while not button.is_pressed(): time.sleep(.1) buffer = capture_audio() text = convert_speech_to_text(buffer) - if len(text) > 0: - print(text) - message = Message(json.dumps({ 'speech': text })) - device_client.send_message(message) \ No newline at end of file + process_text(text) \ No newline at end of file diff --git a/6-consumer/lessons/3-spoken-feedback/code-spoken-response/virtual-iot-device/smart-timer/app.py b/6-consumer/lessons/3-spoken-feedback/code-spoken-response/virtual-iot-device/smart-timer/app.py index 510b7fbf..fa2e3c5a 100644 --- a/6-consumer/lessons/3-spoken-feedback/code-spoken-response/virtual-iot-device/smart-timer/app.py +++ b/6-consumer/lessons/3-spoken-feedback/code-spoken-response/virtual-iot-device/smart-timer/app.py @@ -1,19 +1,11 @@ -import json +import requests import threading import time from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, SpeechSynthesizer -from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse speech_api_key = '' location = '' language = '' -connection_string = '' - -device_client = IoTHubDeviceClient.create_from_connection_string(connection_string) - -print('Connecting') -device_client.connect() -print('Connected') recognizer_config = SpeechConfig(subscription=speech_api_key, region=location, @@ -21,24 +13,6 @@ recognizer_config = SpeechConfig(subscription=speech_api_key, recognizer = SpeechRecognizer(speech_config=recognizer_config) -def recognized(args): - if len(args.result.text) > 0: - message = Message(json.dumps({ 'speech': args.result.text })) - device_client.send_message(message) - -recognizer.recognized.connect(recognized) - -recognizer.start_continuous_recognition() - -speech_config = SpeechConfig(subscription=speech_api_key, - region=location) -speech_config.speech_synthesis_language = language -speech_synthesizer = SpeechSynthesizer(speech_config=speech_config) - -voices = speech_synthesizer.get_voices_async().get().voices -first_voice = next(x for x in voices if x.locale.lower() == language.lower()) -speech_config.speech_synthesis_voice_name = first_voice.short_name - def say(text): ssml = f'' ssml += f'' @@ -70,17 +44,43 @@ def create_timer(total_seconds): announcement += 'timer started.' say(announcement) -def handle_method_request(request): - if request.name == 'set-timer': - payload = json.loads(request.payload) - seconds = payload['seconds'] - if seconds > 0: - create_timer(payload['seconds']) +def get_timer_time(text): + url = '' + + body = { + 'text': text + } - method_response = MethodResponse.create_from_method_request(request, 200) - device_client.send_method_response(method_response) + response = requests.post(url, json=body) -device_client.on_method_request_received = handle_method_request + if response.status_code != 200: + return 0 + + payload = response.json() + return payload['seconds'] + +def process_text(text): + print(text) + + seconds = get_timer_time(text) + if seconds > 0: + create_timer(seconds) + +def recognized(args): + process_text(args.result.text) + +recognizer.recognized.connect(recognized) + +recognizer.start_continuous_recognition() + +speech_config = SpeechConfig(subscription=speech_api_key, + region=location) +speech_config.speech_synthesis_language = language +speech_synthesizer = SpeechSynthesizer(speech_config=speech_config) + +voices = speech_synthesizer.get_voices_async().get().voices +first_voice = next(x for x in voices if x.locale.lower() == language.lower()) +speech_config.speech_synthesis_voice_name = first_voice.short_name while True: time.sleep(1) \ No newline at end of file diff --git a/6-consumer/lessons/3-spoken-feedback/code-timer/pi/smart-timer/app.py b/6-consumer/lessons/3-spoken-feedback/code-timer/pi/smart-timer/app.py index 47440566..478501c8 100644 --- a/6-consumer/lessons/3-spoken-feedback/code-timer/pi/smart-timer/app.py +++ b/6-consumer/lessons/3-spoken-feedback/code-timer/pi/smart-timer/app.py @@ -76,11 +76,11 @@ def convert_speech_to_text(buffer): def get_timer_time(text): url = '' - params = { + body = { 'text': text } - response = requests.post(url, params=params) + response = requests.post(url, json=body) if response.status_code != 200: return 0 diff --git a/6-consumer/lessons/3-spoken-feedback/code-timer/virtual-iot-device/smart-timer/app.py b/6-consumer/lessons/3-spoken-feedback/code-timer/virtual-iot-device/smart-timer/app.py index 0b20fd8c..0f745b8a 100644 --- a/6-consumer/lessons/3-spoken-feedback/code-timer/virtual-iot-device/smart-timer/app.py +++ b/6-consumer/lessons/3-spoken-feedback/code-timer/virtual-iot-device/smart-timer/app.py @@ -16,11 +16,11 @@ recognizer = SpeechRecognizer(speech_config=recognizer_config) def get_timer_time(text): url = '' - params = { + body = { 'text': text } - response = requests.post(url, params=params) + response = requests.post(url, json=body) if response.status_code != 200: return 0 diff --git a/6-consumer/lessons/3-spoken-feedback/single-board-computer-set-timer.md b/6-consumer/lessons/3-spoken-feedback/single-board-computer-set-timer.md index 72b0a6b8..b2b87597 100644 --- a/6-consumer/lessons/3-spoken-feedback/single-board-computer-set-timer.md +++ b/6-consumer/lessons/3-spoken-feedback/single-board-computer-set-timer.md @@ -26,14 +26,14 @@ Timers can be set using the Python `threading.Timer` class. This class takes a d Replace `` with the URL of your rest endpoint that you built in the last lesson, either on your computer or in the cloud. -1. Add the following code to set the text as a parameter on the URL and make the API call: +1. Add the following code to set the text as a property passed as JSON to the call: ```python - params = { + body = { 'text': text } - response = requests.post(url, params=params) + response = requests.post(url, json=body) ``` 1. Below this, retrieve the `seconds` from the response payload, returning 0 if the call failed: diff --git a/images/Diagrams.sketch b/images/Diagrams.sketch index 44f09f1f..086198c5 100644 Binary files a/images/Diagrams.sketch and b/images/Diagrams.sketch differ diff --git a/images/stock-7-cans-tomato-paste.png b/images/stock-7-cans-tomato-paste.png new file mode 100644 index 00000000..c08ae475 Binary files /dev/null and b/images/stock-7-cans-tomato-paste.png differ diff --git a/images/stock-rogue-corn.png b/images/stock-rogue-corn.png new file mode 100644 index 00000000..b9b6d980 Binary files /dev/null and b/images/stock-rogue-corn.png differ