{"id":2541,"date":"2020-07-19T11:41:09","date_gmt":"2020-07-19T11:41:09","guid":{"rendered":"http:\/\/blog.rastersoft.com\/?p=2541"},"modified":"2020-10-21T12:14:38","modified_gmt":"2020-10-21T12:14:38","slug":"a-ritmo-de-conga-8","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=2541","title":{"rendered":"A ritmo de conga (8)"},"content":{"rendered":"\n<p>Esta ser\u00e1, en principio, la \u00faltima entrada. En ella voy a describir el servidor\/app que escrib\u00ed para controlar mi aspiradora robot.<\/p>\n\n\n\n<p><strong>DISCLAIMER:<\/strong> no ser\u00e9 responsable si alguien decide seguir mis pasos y se carga su aspiradora. En principio todo lo que cuento deber\u00eda ser seguro, pero por motivos obvios no me puedo responsabilizar de lo que hagan otras personas, s\u00f3lo de lo que haga yo.<\/p>\n\n\n\n<p>El c\u00f3digo est\u00e1 escrito en python, est\u00e1 disponible en mi cuenta de Gitlab en <a href=\"https:\/\/gitlab.com\/rastersoft\/opendonita\">servidor para robots Conga 1490<\/a>, y se llama <strong>OpenDo\u00f1ita<\/strong>. Esta descripci\u00f3n complementa a la del <a href=\"https:\/\/blog.rastersoft.com\/?p=2463\">cap\u00edtulo 5<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-video aligncenter meme\"><video height=\"200\" style=\"aspect-ratio: 272 \/ 200;\" width=\"272\" controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/reading_searching_in_book.mp4\"><\/video><\/figure>\n\n\n\n<p>Para empezar, est\u00e1 c\u00f3mo hacerlo funcionar. Yo lo he puesto en una <a rel=\"noreferrer noopener\" href=\"https:\/\/www.raspberrypi.org\/products\/raspberry-pi-4-model-b\/\" target=\"_blank\">Raspberry Pi 4<\/a> que ten\u00eda muerta de risa por casa (de momento <a rel=\"noreferrer noopener\" href=\"https:\/\/osmc.tv\/\" target=\"_blank\">OSMC<\/a> no funciona en ella), la misma con la que configur\u00e9 la red WiFi interna para analizar el tr\u00e1fico. Sin embargo es posible ponerla en cualquier ordenador, siempre y cuando se configure un DNS adecuado. En efecto, si recordamos, la aspiradora se conectar\u00e1 siempre a dos dominios concretos, <em>bl-app-eu.robotbona.com<\/em> y <em>bl-im-eu.robotbona.com<\/em>, por lo que necesitamos enga\u00f1arla de alguna manera para que se conecte a nuestro servidor. La manera m\u00e1s sencilla es entrar en la configuraci\u00f3n de nuestro <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Wireless_access_point\" target=\"_blank\">router Wifi<\/a> y y configurar la IP de nuestra <em>Raspberry Pi<\/em> como la IP del <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Name_server\" target=\"_blank\">servidor DNS<\/a> de nuestra red. Luego, en dicha Raspberry instalamos <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Dnsmasq\" target=\"_blank\">dnsmasq<\/a>, pero no configuramos la parte de DHCP, s\u00f3lo el servidor DNS. Una vez hecho esto editamos el fichero <em>\/etc\/hosts<\/em> y a\u00f1adimos estas dos entradas:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted mycode\">192.168.X.Y bl-app-eu.robotbona.com<br>192.168.X.Y bl-im-eu.robotbona.com<\/pre>\n\n\n\n<p>Siendo <em>192.168.X.Y<\/em> la IP del equipo en donde vayamos a poner a correr el servidor (que, normalmente, ser\u00e1 la misma <em>Raspberry Pi<\/em>).<\/p>\n\n\n\n<p>Un detalle importante es que mi c\u00f3digo necesita Python 3.6 o superior, lo que significa que funcionar\u00e1 en <em>Raspbian<\/em>, pero no en la versi\u00f3n actual de <em>OSMC<\/em> pues est\u00e1 basada en la versi\u00f3n <em>stretch<\/em> de Debian (lo he probado; quer\u00eda meter todo en la misma Raspberry pero no ha podido ser). Hasta que actualicen el sistema base a <em>buster<\/em> (y me consta que est\u00e1n en ello) no se podr\u00e1 hacer.<\/p>\n\n\n\n<figure class=\"wp-block-video aligncenter meme\"><video height=\"220\" style=\"aspect-ratio: 320 \/ 220;\" width=\"320\" controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/fixing.mp4\"><\/video><\/figure>\n\n\n\n<p>Una vez que est\u00e1 hecho reiniciamos <em>dnsmasq<\/em> para que refresque los valores, y ya podemos lanzar nuestro servidor. Para ello, desde un terminal, vamos al directorio donde est\u00e9 el c\u00f3digo y escribimos:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted mycode\">sudo screen .\/congaserver<\/pre>\n\n\n\n<p>Es importante estar en el directorio correspondiente pues, por defecto, es ah\u00ed donde el servidor buscar\u00e1 el directorio <em>html<\/em> con las p\u00e1ginas de la aplicaci\u00f3n web que se utiliza para controlar a las aspiradoras. Si lo lanzamos desde otro directorio lo m\u00e1s probable es que no funcione. Para m\u00e1s informaci\u00f3n sobre <em><a href=\"https:\/\/linuxize.com\/post\/how-to-use-linux-screen\/\" target=\"_blank\" rel=\"noreferrer noopener\">screen<\/a><\/em>, recomiendo leer <a href=\"https:\/\/linux.die.net\/man\/1\/screen\" target=\"_blank\" rel=\"noreferrer noopener\">la documentaci\u00f3n<\/a>. Es necesario usarlo (o bien <em>nohup<\/em> en su lugar) para poder salir de la sesi\u00f3n SSH de la RPi y que el programa siga corriendo.<\/p>\n\n\n\n<p>Podemos probar si funciona todo correctamente simplemente abriendo un navegador y escribiendo en un terminal<\/p>\n\n\n\n<pre class=\"wp-block-preformatted mycode\">ping bl-app-eu.robotbona.com<\/pre>\n\n\n\n<p>Si todo est\u00e1 correcto, deber\u00eda resolver a la IP de nuestra <em>Raspberry Pi<\/em>.<\/p>\n\n\n\n<p>Y ahora que est\u00e1 todo listo y corriendo, ya podemos conectar la aspiradora. Para ello tenemos tres opciones:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Apagar la WiFi y volverla a encender. En este caso, la aspiradora volver\u00e1 a conectarse a ella, buscar\u00e1 el servidor de nuevo y se conectar\u00e1 al nuestro, pues recibir\u00e1 la IP desde nuestro servidor DNS.<\/li><li>Apagar la aspiradora y volverla a encender. Para ello es necesario retirarla de la base de carga y apagar el interruptor situado en el lado derecho, esperar unos segundos y volver a encenderlo.<\/li><li>Volver a emparejar la aspiradora. Es el m\u00e1s lioso, pues con el DNS en marcha la app oficial no podr\u00e1 conectarse al servidor (usa un puerto diferente) y se negar\u00e1 a arrancar, por lo que tendremos que utilizar el script <em>configconga.py<\/em>, que explicar\u00e9 m\u00e1s adelante.<\/li><\/ul>\n\n\n\n<p>En cualquiera de los tres casos sabremos si hemos tenido \u00e9xito porque en la pantalla de nuestro servidor aparecer\u00e1n mensajes que indican que se est\u00e1n haciendo peticiones.<\/p>\n\n\n\n<p>Una vez conectada, ya est\u00e1 todo listo para empezar a trabajar. Si ahora abrimos un navegador y metemos la IP del equipo de nuestro servidor, nos aparecer\u00e1 la siguiente pantalla:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_conga1.png\" rel=\"lightbox-0\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"545\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_conga1-1024x545.png\" alt=\"\" class=\"wp-image-2543\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_conga1-1024x545.png 1024w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_conga1-300x160.png 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_conga1-768x409.png 768w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_conga1-1536x818.png 1536w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_conga1.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>En la parte blanca de la derecha es donde aparecer\u00e1 el mapa, pero de momento estar\u00e1 en blanco. Por otro lado, en la parte superior izquierda tenemos un indicador de carga de la bater\u00eda. Cuando esta completamente negra estar\u00e1 cargada, y si est\u00e1 blanca estar\u00e1 descargada. Ah\u00ed se ve que est\u00e1 casi cargada del todo.<\/p>\n\n\n\n<p>El s\u00edmbolo del rayo indica que est\u00e1 cargando. Cuando est\u00e9 cargada del todo (o cuando no est\u00e9 en la base) dicho s\u00edmbolo desaparecer\u00e1.<\/p>\n\n\n\n<p>A continuaci\u00f3n vemos los cuatro botones que podemos utilizar. El primero, con forma de casa, ordena a la aspiradora volver a la base. Sin embargo, si ya est\u00e1 en la base aparecer\u00e1 s\u00f3lo en forma de l\u00edneas, sin relleno (tal y como se ve en la captura).<\/p>\n\n\n\n<p>El siguiente bot\u00f3n, con forma de \u00abplay\u00bb, le indica a la aspiradora que comience a trabajar. Al hacerlo cambiar\u00e1 a un cuadrado, o sea, \u00abstop\u00bb.<\/p>\n\n\n\n<p>El tercer bot\u00f3n, con forma de altavoz, permite activar o desactivar el pitido de aviso de la aspiradora. Tal y como est\u00e1 en la captura, est\u00e1 desactivado. Al activarlo sonar\u00e1 un pitido de aviso y el icono pasar\u00e1 a estar relleno.<\/p>\n\n\n\n<p>El \u00faltimo bot\u00f3n, el engranaje, muestra la pantalla de configuraci\u00f3n de modo de limpieza. Al pulsarlo aparece esta imagen:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/modos-de-limpieza.png\" rel=\"lightbox-1\"><img loading=\"lazy\" decoding=\"async\" width=\"963\" height=\"979\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/modos-de-limpieza.png\" alt=\"\" class=\"wp-image-2544\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/modos-de-limpieza.png 963w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/modos-de-limpieza-295x300.png 295w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/modos-de-limpieza-768x781.png 768w\" sizes=\"auto, (max-width: 963px) 100vw, 963px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>Los cuatro superiores, con forma de ventilador, representan las cuatro potencias de aspiraci\u00f3n (nada, eco, normal y turbo). Las cuatro siguientes, con forma de gota de agua, la cantidad de l\u00edquido que se utiliza para humedecer la fregona (nada, poco, normal, mucho). Un detalle importante es que no es posible escoger a la vez los modos \u00abnada\u00bb de aspiraci\u00f3n y fregona. Por \u00faltimo, los siete inferiores representan los modos de aspirado y fregado disponibles, aunque lo normal es utilizar el modo <em>auto<\/em> y no complicarse.<\/p>\n\n\n\n<p>Lo mejor de todo es que recuerda el modo escogido incluso si se apaga la aspiradora, pues la configuraci\u00f3n se guarda en nuestro servidor.<\/p>\n\n\n\n<p>Para cerrar esta ventana basta con pulsar la flecha situada abajo a la derecha.<\/p>\n\n\n\n<p>Si ponemos a funcionar la aspiradora, se ir\u00e1 generando poco a poco el mapa, cuyo tama\u00f1o se ir\u00e1 ajustando poco a poco a medida que se va calculando. Por eso al principio estar\u00e1 formado por c\u00edrculos gigantescos, pero luego ir\u00e1n haci\u00e9ndose m\u00e1s peque\u00f1os a medida que la superficie descubierta aumente. As\u00ed, al principio veremos algo as\u00ed:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_y_mapa.png\" rel=\"lightbox-2\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"545\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_y_mapa-1024x545.png\" alt=\"\" class=\"wp-image-2549\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_y_mapa-1024x545.png 1024w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_y_mapa-300x160.png 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_y_mapa-768x409.png 768w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_y_mapa-1536x818.png 1536w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/app_y_mapa.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">El protocolo REST<\/h2>\n\n\n\n<p>Y tras esto, paso a describir el protocolo REST utilizado por el servidor. Porque, efectivamente, la nueva <em>app<\/em> es una aplicaci\u00f3n web, por lo que se puede actualizar y tunear sin necesidad de parar el servidor y volver a lanzarlo (lo que, adem\u00e1s, exigir\u00eda volver a hacer que la aspiradora se conectase a \u00e9l usando uno de los tres m\u00e9todos comentados antes).<\/p>\n\n\n\n<p>Los comandos que acepta son los siguientes. Para empezar, est\u00e1n los tres espec\u00edficos del emulador del servidor de Robot Bona, que son:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted mycode\">\/baole-web\/common\/sumbitClearTime.do\n\/baole-web\/common\/getToken.do\n\/baole-web\/common\/*<\/pre>\n\n\n\n<p>Los dos primeros devuelven los datos necesarios para emparejar la aspiradora con el servidor, y el tercero devuelve simplemente un <em>OK<\/em>.<\/p>\n\n\n\n<p>Ahora vienen los comandos espec\u00edficos del servidor. Estos son comandos que no afectan a la aspiradora, sino que son \u00fatiles para implementar la <em>app<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted mycode\">\/robot\/list\n\/robot\/XXXXX\/getStatus\n\/robot\/XXXXX\/setStatus\n\/robot\/XXXXX\/getProperty?key=YYYYYY\n\/robot\/XXXXX\/setProperty?key=YYYYYY&amp;value=ZZZZZZ<\/pre>\n\n\n\n<p>El primero devuelve una lista con el identificador de cada robot que est\u00e1 conectado ahora mismo al servidor. Este identificador se puede utilizar para enviar comandos a un robot espec\u00edfico si tenemos varios en casa.<\/p>\n\n\n\n<p>Los otros cuatro son comandos de servidor. El par\u00e1metro XXXXX ser\u00eda un identificador del robot al que va dirigido (obtenido con <em>list<\/em>), o bien puede ser <em>all<\/em> si queremos dirigirnos a todos. De hecho, actualmente la <em>app<\/em> no soporta discernir entre robots, y siempre env\u00eda los comandos a <em>all<\/em>. Si en el futuro me compro otro robot puede que lo implemente.<\/p>\n\n\n\n<p><em>getStatus<\/em> devuelve el estado actual de la aspiradora. Se trata de un diccionario con los datos enviados por la aspiradora al servidor, tales como el mapa, el nivel de bater\u00eda, el modo actual de trabajo&#8230; Cada vez que la aspiradora env\u00eda una actualizaci\u00f3n, el servidor la almacena internamente, y es esta cach\u00e9 la que se env\u00eda aqu\u00ed. Eso significa, por ejemplo, que si no estamos aspirando, el mapa que recibamos ser\u00e1 el \u00faltimo que se envi\u00f3, aunque haya sido hace horas. Tambi\u00e9n si hubo alg\u00fan error aparecer\u00e1 su c\u00f3digo en el campo correspondiente, aunque haga mucho que no se produjeron m\u00e1s errores.<\/p>\n\n\n\n<p><em>setStatus<\/em> permite modificar alguno de los valores anteriores, pero s\u00f3lo en la cach\u00e9 del servidor. No afecta a la aspiradora. Existe para poder resetear algunos campos que se activan en casos muy concretos, como por ejemplo el campo <em>error<\/em>, y as\u00ed poder detectar cuando se ha producido uno nuevo. Actualmente no se utiliza para nada.<\/p>\n\n\n\n<p><em>getProperty<\/em> y <em>setProperty<\/em> se utilizan para almacenar datos personalizados en el servidor, referidos a una aspiradora concreta. Actualmente se utilizan para almacenar la configuraci\u00f3n deseada (potencia de succi\u00f3n, cantidad de agua en modo fregado, y modo de limpieza), de manera que aunque se apague la aspiradora, el sistema recordar\u00e1 la configuraci\u00f3n deseada por el usuario. La forma de almacenarlo es como pares <em>clave\/valor<\/em>, y siempre son <em>strings<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-video aligncenter meme\"><video height=\"180\" style=\"aspect-ratio: 302 \/ 180;\" width=\"302\" controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/lista.mp4\"><\/video><\/figure>\n\n\n\n<p>Por \u00faltimo, la lista de comandos que van a la aspiradora. Son:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted mycode\">\/robot\/XXXXX\/clean\n\/robot\/XXXXX\/stop\n\/robot\/XXXXX\/return\n\/robot\/XXXXX\/updateMap\n\/robot\/XXXXX\/sound?status=0|1\n\/robot\/XXXXX\/fan?speed=0|1|2|3\n\/robot\/XXXXX\/watertank?speed=0|1|2|3\n\/robot\/XXXXX\/mode?type=auto|gyro|random|borders|area|x2|scrub\n\/robot\/XXXXX\/notifyConnection\n\/robot\/XXXXX\/askStatus<\/pre>\n\n\n\n<p><em>clean, stop<\/em> y <em>return<\/em> controlan la operaci\u00f3n b\u00e1sica de la aspiradora: comenzar un ciclo de limpieza, parar, y volver a la base. No tiene m\u00e1s complicaci\u00f3n.<\/p>\n\n\n\n<p><em>updateMap<\/em> env\u00eda un comando 131, de manera que en torno a una d\u00e9cima de segundo despu\u00e9s tendremos la variable <em>map<\/em> actualizada, y podremos obtener su nuevo valor con <em>\/robot\/XXXXX\/getStatus<\/em>.<\/p>\n\n\n\n<p><em>sound<\/em> permite activar (1) o desactivar (0) el pitido de aviso de la aspiradora. Teniendo en cuenta que cada vez que termina de cargar emite un pitido, yo personalmente prefiero apagarlo.<\/p>\n\n\n\n<p><em>fan<\/em> y <em>watertank<\/em> permiten escoger la potencia de aspiraci\u00f3n y la cantidad de agua que se utilizar\u00e1n durante el ciclo de limpieza.<\/p>\n\n\n\n<p><em>mode<\/em> permite escoger entre los siete modos de limpieza, aunque lo normal es utilizar <em>auto<\/em>.<\/p>\n\n\n\n<p><em>notifyConnection<\/em> emite un comando 400. En la app actual se emite nada m\u00e1s cargar la p\u00e1gina, para avisar de que hay una app abierta.<\/p>\n\n\n\n<p><em>askStatus<\/em> emite un comando 98, el cual hace que unos milisegundos m\u00e1s tarde la aspiradora env\u00ede una actualizaci\u00f3n de su estado. El servidor, al recibirlo, actualizar\u00e1 su cach\u00e9 y podremos leer los cambios con <em>robot\/XXXXX\/getStatus.<\/em><\/p>\n\n\n\n<p>Por \u00faltimo, cualquier petici\u00f3n que no coincida con este formato se asumir\u00e1 que est\u00e1 pidiendo un fichero, por lo que se buscar\u00e1 en la carpeta <em>html<\/em>. Es as\u00ed como se sirven las p\u00e1ginas HTML y las im\u00e1genes de la app.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Emparejando la conga a una red WiFi<\/h2>\n\n\n\n<p>Una vez que hemos cambiado el DNS veremos que la app oficial, la del m\u00f3vil, ya no funciona. Esto es porque intenta conectarse al servidor oficial, y al no poder por apuntar ahora al nuestro, se niega a abrirse siquiera. Eso significa que no podemos utilizarla si necesitamos emparejar nuestro aspirador con otra red WiFi.<\/p>\n\n\n\n<p>Afortunadamente, para eso est\u00e1 <em>configconga.py<\/em>. Es un programita que permite realizar la operaci\u00f3n de emparejado. Para ello necesitamos un ordenador con WiFi.<\/p>\n\n\n\n<p>Lo primero es poner la aspiradora en <em>modo emparejamiento<\/em>. Para ello hay que mantener pulsado el bot\u00f3n de encendido hasta que el piloto de WiFi empiece a parpadear y suene un pitido.<\/p>\n\n\n\n<p>En este momento la aspiradora se ha convertido en un punto de acceso WiFi, con un nombre <em>CongaGyro_XXXXXX<\/em> (siendo XXXXXX el identificador \u00fanico de la aspiradora). Ahora tienes que conectarte desde tu ordenador a esa WiFi (no tiene contrase\u00f1a), y ejecutar el programa anterior con:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted mycode\">.\/configconga.py    WIFI_SSID    WIFI_PASSWORD<\/pre>\n\n\n\n<p>Siendo <em>SSID<\/em> el identificador de la red WiFi a la que quieres conectar tu aspiradora, y <em>PASSWORD<\/em> la clave de dicha red WiFi. Una vez hecho esto la aspiradora dejar\u00e1 de ser un punto de acceso, y pasar\u00e1 a conectarse a la WiFi indicada.<\/p>\n\n\n\n<p>\u00a1Ahora, a disfrutarlo!<\/p>\n\n\n\n<figure class=\"wp-block-video aligncenter meme\"><video height=\"240\" style=\"aspect-ratio: 320 \/ 240;\" width=\"320\" controls src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2020\/07\/enjoy.mp4\"><\/video><\/figure>\n\n\n\n<p><a href=\"https:\/\/blog.rastersoft.com\/?p=2571\">Parte 9<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Esta ser\u00e1, en principio, la \u00faltima entrada. En ella voy a describir el servidor\/app que escrib\u00ed para controlar mi aspiradora robot. DISCLAIMER: no ser\u00e9 responsable si alguien decide seguir mis pasos y se carga su aspiradora. En principio todo lo que cuento deber\u00eda ser seguro, pero por motivos obvios no me puedo responsabilizar de lo &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=2541\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">A ritmo de conga (8)<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,16,5,7],"tags":[],"class_list":["post-2541","post","type-post","status-publish","format-standard","hentry","category-cacharreo","category-opendonita","category-programacion","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/2541","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2541"}],"version-history":[{"count":25,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/2541\/revisions"}],"predecessor-version":[{"id":2628,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/2541\/revisions\/2628"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}