{"id":236,"date":"2021-12-05T12:42:37","date_gmt":"2021-12-05T11:42:37","guid":{"rendered":"https:\/\/www.davidestebanmunoz.com\/?p=236"},"modified":"2022-01-01T17:08:35","modified_gmt":"2022-01-01T16:08:35","slug":"transporte-bilbao-alexa-skill","status":"publish","type":"post","link":"https:\/\/www.davidestebanmunoz.com\/?p=236","title":{"rendered":"Transporte Bilbao Alexa Skill"},"content":{"rendered":"\n<p><a href=\"https:\/\/www.davidestebanmunoz.com\/?p=247&amp;lang=es\">Este articulo se puede leer en castellano aqui<\/a><\/p>\n\n\n\n<p>This alexa skill is accessible at <a href=\"https:\/\/www.amazon.es\/dp\/B09PHW45PS\">https:\/\/www.amazon.es\/dp\/B09PHW45PS<\/a><\/p>\n\n\n\n<p>The objective of this skill is to have next public transports for Bilbao and its surrounding area. Now, it supports lines 1, 2 and 3 of Metro Bilbao .<\/p>\n\n\n\n<p>The interaction with the user is voice based in spanish language:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>alexa pidele a transporte bilbao los siguientes metros de matiko a algorta<\/p><\/blockquote>\n\n\n\n<p>And if you own a display alexa element such us alexa show , you will get the information also in a graphical card<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"500\" data-dnt=\"true\"><p lang=\"es\" dir=\"ltr\">O si dispones de un dispositivo con pantalla, podr\u00e1s ver tambi\u00e9n la hora de llegada <a href=\"https:\/\/t.co\/HLVFYacAWJ\">pic.twitter.com\/HLVFYacAWJ<\/a><\/p>&mdash; botmakerdvd (@botmakerdvd) <a href=\"https:\/\/twitter.com\/botmakerdvd\/status\/1476955846533910535?ref_src=twsrc%5Etfw\">December 31, 2021<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Python endpoint<\/h2>\n\n\n\n<p>Its arquitecture is quite simple, in this case , by the moment it does not support favourite journeys so it is only 2 dockers based, an nginx and a python containers running on the VPS. It is the green block of this diagram, the blue one is common for many other diagrams and its explanation can be seen <a href=\"https:\/\/www.davidestebanmunoz.com\/?p=130\">here<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"611\" height=\"281\" src=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/metro_alexa.png\" alt=\"\" class=\"wp-image-240\" srcset=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/metro_alexa.png 611w, https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/metro_alexa-300x138.png 300w\" sizes=\"auto, (max-width: 611px) 100vw, 611px\" \/><\/figure>\n\n\n\n<p>The docker-compose recipe can be seen here, it is interesting the volume used for sharing timezone between host and container, since it is critical for being able to query transport APIs with correct time:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>version: '3'\nservices:\n    flaskapp_metro:\n        build:\n            context: .\/\n            dockerfile: Dockerfile_flask\n        image: flask:0.0.1\n        container_name: flaskapp_metro\n        volumes:\n            - \"\/home\/ubuntu\/dockers\/metro_alexa\/data\/scripts:\/code\/\"\n            - \/etc\/localtime:\/etc\/localtime:ro\n        environment:\n            - FLASK_APP=\/code\/metrobot_alexa.py\n        command: python \/code\/metrobot_alexa.py\n        networks:\n            - alexa_metro\n    nginx_metro:\n        image: nginx\n        depends_on:\n          - flaskapp_metro\n        container_name: nginx_metro\n        networks:\n          - proxy_nginx-proxy\n          - alexa_metro\n        environment:\n            - VIRTUAL_HOST=metro.davidestebanmunoz.com\n            - LETSENCRYPT_HOST=metro.davidestebanmunoz.com\n        volumes:\n            - \"\/home\/ubuntu\/dockers\/metro_alexa\/data\/nginx\/etc_nginx:\/etc\/nginx\"\nnetworks:\n    alexa_metro:\n    proxy_nginx-proxy:\n        external: true <\/code><\/pre>\n\n\n\n<p>The dockerfile used for building flask image is this one:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FROM python:3.8-slim\nENV LANG en_US.UTF-8\nENV LANGUAGE en_US:en\nENV LC_ALL en_US.UTF-8\n\nRUN apt-get update &amp;&amp; apt-get upgrade -y\nRUN apt install -y gcc libssl-dev\nRUN pip install https:\/\/github.com\/botmakerdvd\/flask-ask\/archive\/refs\/heads\/master.zip\nRUN apt remove -y gcc libssl-dev\nRUN apt autoremove -y<\/code><\/pre>\n\n\n\n<p>In this case flask-ask library is used. I forked this library into my repository because I needed to change its behaviour and answer with a 400 Bad Request code when requests are not signed by Alexa . This was mandatory in order to be able to publish this skill  into Alexa skills store.<\/p>\n\n\n\n<p>Main Nginx container (the one in blue block) will be responsible of handling the HTTPs keys and certificates so we do not need to worry about this and the nginx configuration file is quite simple:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n  listen 80;\n  server_name metro.davidestebanmunoz.com;\n  location \/ {\n  proxy_pass http:\/\/flaskapp_metro:5001;\n  proxy_set_header Host \"localhost\";\n  } }\n<\/code><\/pre>\n\n\n\n<p>metro.davidestebanmunoz is a A type register in DNS. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Alexa skill<\/h2>\n\n\n\n<p>This skill has one intent with 3 slots, \u00abtransporte\u00bb that for now can be \u00abmetro\/s\u00bb and \u00abtren\/es\u00bb and \u00aborigen\u00bb and \u00abdestino\u00bb that are the stations.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"503\" height=\"488\" src=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen.png\" alt=\"\" class=\"wp-image-243\" srcset=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen.png 503w, https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-300x291.png 300w\" sizes=\"auto, (max-width: 503px) 100vw, 503px\" \/><\/figure>\n\n\n\n<p>The stations are coded so every information (type of transport operator, line and code for external API) can be extracted from value so no other external DB is needed. Also, using synonims, spanish pronunciation of basque toponims is solved.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"517\" height=\"116\" src=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-1.png\" alt=\"\" class=\"wp-image-244\" srcset=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-1.png 517w, https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-1-300x67.png 300w\" sizes=\"auto, (max-width: 517px) 100vw, 517px\" \/><\/figure>\n\n\n\n<p>Finnally the endpoint of the skill is configured to call https:\/\/metro.davidestebanmunoz.com<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"822\" height=\"165\" src=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-2.png\" alt=\"\" class=\"wp-image-245\" srcset=\"https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-2.png 822w, https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-2-300x60.png 300w, https:\/\/www.davidestebanmunoz.com\/wp-content\/uploads\/2022\/01\/imagen-2-768x154.png 768w\" sizes=\"auto, (max-width: 822px) 100vw, 822px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li>Type: Alexa Skill<\/li><li>Where: Docker on VPS<\/li><li>Languages and technologies used: Python, flask, Alexa, DNS<\/li><li>Github repo: no<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/www.davidestebanmunoz.com\/?p=236\">Read More<span class=\"screen-reader-text\">Transporte Bilbao Alexa Skill<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[86,96,38,90,49],"class_list":["post-236","post","type-post","status-publish","format-standard","hentry","category-personal-projects","tag-alexa","tag-dns","tag-docker-en","tag-flask","tag-python","excerpt"],"_links":{"self":[{"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/posts\/236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=236"}],"version-history":[{"count":8,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/posts\/236\/revisions"}],"predecessor-version":[{"id":252,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/posts\/236\/revisions\/252"}],"wp:attachment":[{"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}