{"id":247,"date":"2021-12-05T17:02:16","date_gmt":"2021-12-05T16:02:16","guid":{"rendered":"https:\/\/www.davidestebanmunoz.com\/?p=247"},"modified":"2022-01-01T17:10:26","modified_gmt":"2022-01-01T16:10:26","slug":"skill-alexa-transporte-bilbao","status":"publish","type":"post","link":"https:\/\/www.davidestebanmunoz.com\/?p=247&lang=es","title":{"rendered":"Skill Alexa Transporte Bilbao"},"content":{"rendered":"\n<p><a href=\"https:\/\/www.davidestebanmunoz.com\/?p=236\">This article can be read in english here<\/a><\/p>\n\n\n\n<p>Esta skill de alexa es accessible en <a href=\"https:\/\/www.amazon.es\/dp\/B09PHW45PS\">https:\/\/www.amazon.es\/dp\/B09PHW45PS<\/a><\/p>\n\n\n\n<p>El objetivo de esta skill es tener informaci\u00f3n sobre los siguientes transportes p\u00fablicos de Bilbao y su area alrededor. Actualmente soporta las l\u00edneas 1 2 y 3 de Metro Bilbao, asi como la linea del txorierri de euskotren.<\/p>\n\n\n\n<p>La interacci\u00f3n con el usuario est\u00e1 basada en comandos de voz en castellano:<\/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>Yi tienes un alexa echo show o dispositivo similar, con pantalla, puedes obtener la informaci\u00f3n de forma gr\u00e1fica<\/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>Su arquitectura es muy simple, en este caso, por el momento, no soporta guardar nuestros recorridos favoritos por lo que solamente est\u00e1 basado en 2 contenedores docker. Un contenedor nginx y un contenedor Python que corren en el VPS. Son el bloque verde de este diagrama, el bloque azul es com\u00fan a muchos otros diagramas y su explicaci\u00f3n se puede ver <a href=\"https:\/\/www.davidestebanmunoz.com\/?p=176&amp;lang=es\">aqui<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><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>La receta de docker compose se puede ver aqui, conviene recalcar el uso del volumen para compartir zona horaria entre el host y el contenedor, ya que es critico para llamar a las APIs con la hora correcta:<\/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>El dockerfile utilizado para construir la imagen flask es este:<\/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>Tal y como se observa, se utiliza la libreria flask-ask. He \u00abforkeado\u00bb esta libreria en mi repositorio, porque he necesitado cambiar su comportamiento y devolver una respuesta con c\u00f3digo 400 (Bad request) cuando las peticiones no han sido firmadas por Alexa. Esto ha sido un requisito obligatorio para poder publicar esta skill en la tienda de skills de Alexa.<\/p>\n\n\n\n<p>El contenedor Nginx principal (el que aparece en el bloque azul) ser\u00e1 el responsable de manejar las claves privadas y certificados relacionados con el HTTPs por lo que no nos tenemos que preocupar de ello. Por ello el fichero de configuraci\u00f3n de Nginx es muy 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 es un registro tipo A en el DNS.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Alexa skill<\/h2>\n\n\n\n<p>Esta skill tiene un intent con 3 slots. \u00abtransporte\u00bb que por ahora puede ser \u00abmetro\/s\u00bb o \u00abtren\/es\u00bb y \u00aborigen\u00bb y \u00abdestino\u00bb que son las estaciones.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><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>Las estaciones han sido codificadas para que toda la informaci\u00f3n necesaria (tipo de transporte, l\u00ednea, y c\u00f3digo para las APIs externas) se pueda extraer del valor de la estaci\u00f3n y de esa manera no necesitar ninguna base de datos externa. Asimismo, utilizando sinonimos se resuelve la problem\u00e1tica de la pronunciaci\u00f3n en castellano de las estaciones con top\u00f3nimo en euskera.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><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>Finalmente, el endpoint de la skill se configura para que llame a https:\/\/metro.davidestebanmunoz.com<\/p>\n\n\n\n<figure class=\"wp-block-image\"><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>Tipo: Skill Alexa<\/li><li>Ubicaci\u00f3n: Docker en VPS<\/li><li>Lenguajes y tecnolog\u00edas usados: 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=247&#038;lang=es\">Read More<span class=\"screen-reader-text\">Skill Alexa Transporte Bilbao<\/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":[21],"tags":[88,98,25,92,67],"class_list":["post-247","post","type-post","status-publish","format-standard","hentry","category-proyectos-personales","tag-alexa-es","tag-dns-es","tag-docker","tag-flask-es","tag-python-es","excerpt"],"_links":{"self":[{"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/posts\/247","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=247"}],"version-history":[{"count":3,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/posts\/247\/revisions"}],"predecessor-version":[{"id":253,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=\/wp\/v2\/posts\/247\/revisions\/253"}],"wp:attachment":[{"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=247"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=247"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.davidestebanmunoz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}