<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Electronics on Gabriel Cachadiña</title><link>https://gabrielcachadina.com/es/tags/electronics/</link><description>Recent content in Electronics on Gabriel Cachadiña</description><generator>Hugo -- gohugo.io</generator><language>es-ES</language><managingEditor>gabrielcachadina@protonmail.com (Gabriel Cachadiña)</managingEditor><webMaster>gabrielcachadina@protonmail.com (Gabriel Cachadiña)</webMaster><copyright>John Doe (CC BY 4.0)</copyright><lastBuildDate>Sun, 22 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://gabrielcachadina.com/es/tags/electronics/index.xml" rel="self" type="application/rss+xml"/><item><title>Utilización del sensor PIR BM612</title><link>https://gabrielcachadina.com/es/blog/bm612/</link><pubDate>Sun, 22 Mar 2026 00:00:00 +0000</pubDate><author>gabrielcachadina@protonmail.com (Gabriel Cachadiña)</author><guid>https://gabrielcachadina.com/es/blog/bm612/</guid><description>&lt;p&gt;Actualmente me encuentro realizando un proyecto con el sensor BM612, que es un sensor de detección de infrarojos, normalmente usado para la detección de presencia humana. Al no haber encontrado una guia resumida de sus funcionalidades he decido crear una yo mismo. Esta información está basada en su &lt;a href="https://akizukidenshi.com/goodsaffix/BM612.pdf"&gt;hoja de características&lt;/a&gt; y en módulo &lt;a href="https://www.codrey.com/electronics/mh-sr602-pir-motion-sensor-guide/"&gt;SR602&lt;/a&gt;, que integra el BM612 en una pequeña PCB.
&lt;img src="https://gabrielcachadina.com/BM612.png" alt="BM612"&gt;&lt;/p&gt;
&lt;h1 id="pines"&gt;PINES&lt;/h1&gt;
&lt;p&gt;El BM612 cuenta con 6 PINs. A continuación se tiene una pequeña descripción de la funcionalidad de los mismos.
&lt;img src="https://gabrielcachadina.com/BM612-Schematic.png" alt="BM612-Schematic"&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>Actualmente me encuentro realizando un proyecto con el sensor BM612, que es un sensor de detección de infrarojos, normalmente usado para la detección de presencia humana. Al no haber encontrado una guia resumida de sus funcionalidades he decido crear una yo mismo. Esta información está basada en su <a href="https://akizukidenshi.com/goodsaffix/BM612.pdf">hoja de características</a> y en módulo <a href="https://www.codrey.com/electronics/mh-sr602-pir-motion-sensor-guide/">SR602</a>, que integra el BM612 en una pequeña PCB.
<img src="/BM612.png" alt="BM612"></p>
<h1 id="pines">PINES</h1>
<p>El BM612 cuenta con 6 PINs. A continuación se tiene una pequeña descripción de la funcionalidad de los mismos.
<img src="/BM612-Schematic.png" alt="BM612-Schematic"></p>
<h2 id="alimentación">Alimentación</h2>
<p>El dispositivo se alimentará con un voltaje entre $2.2V$ y $3.7 V$, precisando una corriente nunca superior a $11\mu A$. La alimentación se realizará entre los PINS &ldquo;VDD&rdquo; y &ldquo;GND&rdquo;</p>
<h2 id="outputs">Outputs</h2>
<h3 id="detección">Detección</h3>
<p>El sistema cuenta con el PIN &ldquo;REL&rdquo;, que estará en alto siempre que se supere la sensibilidad seleccionada por el sistema. Si esto es así se pondrá en alto el PIN &ldquo;REL&rdquo; durante la duración configurada por el dispositivo y siempre que no se siga detectando una señal.</p>
<h3 id="output-enable">Output Enable</h3>
<p>El  PIN &ldquo;OEN&rdquo; carece de documentación, pero por contexto se puede determinar que es un &ldquo;Output Enable&rdquo;, es decir, si se quiere deshabilitar la señal &ldquo;REL&rdquo; se podrá poner el PIN &ldquo;OEN&rdquo; a tierra, mientras que si se quiere que funcione de forma normal se pondrá a $V_{DD}$.</p>
<p>Según la hoja de características, se considera un alto seguro cuando se está por encima de $1.2V$ y un nivel bajo seguro si se está por debajo de $0.8V$.</p>
<h2 id="inputs">INPUTS</h2>
<h3 id="sensibilidad">Sensibilidad</h3>
<p>La sensibilidad de la detección del dispositivo vendrá dada por el PIN &ldquo;SENS&rdquo;. Esta sensibilidad determinará el ratio de detección de dispositivo, que tomará las lecturas de su sensórica y hará una comparativa entre las células infrarojas activas y no activas.</p>
<p>Para determinar la sensibilidad de detección se establecerá un voltaje en el PIN &ldquo;SENS&rdquo;, que tendrá su máxima sensiblidad en $0V$  y su mínima sensibilidad en $V_{DD}/2V$ o superior. Es decir, que si queremos detectar casi cualquier presencia, se conectará &ldquo;SENS&rdquo; a tierra, y para detecciones más estrictas se aplicará un voltaje superior a $V_{DD}/2$.</p>
<h3 id="tiempo-de-detección">Tiempo de detección</h3>
<p>El tiempo de detección establece el tiempo durante el cual el PIN &ldquo;REL&rdquo; estará activo, es decir, el tiempo donde se considerará que sigue habiendo una detección. Esto es útil para aplicaciones donde queramos tener una memoria de una detección.</p>
<p>Para determinar este tiempo de detección podremos actuar sobre el PIN &ldquo;ON_TIME&rdquo; de las 2 siguientes formas:</p>
<h4 id="analógico">Analógico</h4>
<p>El PIN &ldquo;ON_TIME&rdquo; genera una oscilación que determinará el tiempo en el que &ldquo;REL&rdquo; estará activo. El delay dependerá de la siguiente fórmula $T_d=\frac{230400}{f}$.</p>
<p>Para conseguir el funcionamiento del dispositivo se dispondrá de una resistencia y un condensador, que harán que el &ldquo;REL&rdquo; aumente en duración cuanto mayor sea la pareja de estos elementos. En la hoja de característica se muestran tablas con los tiempos que se mantendrá activa la señal &ldquo;REL&rdquo;</p>
<h4 id="digital">Digital</h4>
<p>Por otro lado, se podrá configurar la duración de &ldquo;REL&rdquo; mediante la aplicación de un voltaje constante por la entrada &ldquo;ON_TIME&rdquo;, siendo tierra el mínimo tiempo posible y siendo $V_{DD}/2$ el máximo (3600s), se tiene una tabla con las posibles configuraciones de resistencias en la tabla del punto 4.2. de la ficha de características.</p>
<h1 id="circuito-de-ejemplo">Circuito de ejemplo</h1>
<p>En la imagen se muestra un circuito de ejemplo donde:</p>
<ul>
<li>La alimentación es de $3.3V$</li>
<li>La sensibilidad está conectada a tierra, por lo que es la máxima posible</li>
<li>La duración del pulso es la más larga posible, siendo de 3600s, ya que se tiene un voltaje cercano a $V_{DD}/2$</li>
<li>Querremos que el sensor siempre esté activo, por lo que el PIN &ldquo;OEN&rdquo; estará en $3.3V$.</li>
<li>La señal que dará el sensor será leída por un microcontrolador.
<img src="/BM612-Example.png" alt="BM612-Example"></li>
</ul>
]]></content:encoded></item><item><title>Interfaz Web para almacenar variables no volátiles en un ESP32</title><link>https://gabrielcachadina.com/es/blog/webinterfaceinesp32/</link><pubDate>Sun, 08 Mar 2026 00:00:00 +0000</pubDate><author>gabrielcachadina@protonmail.com (Gabriel Cachadiña)</author><guid>https://gabrielcachadina.com/es/blog/webinterfaceinesp32/</guid><description>&lt;p&gt;Actualmente estoy realizando un proyecto con el chip &lt;a href="https://documentation.espressif.com/esp32-c3_datasheet_en.html"&gt;ESP32-C3&lt;/a&gt; que tiene que conectarse a un punto Wi-Fi mediante su antena integrada y mandar una serie de datos por el protocolo &lt;a href="https://mqtt.org/"&gt;MQTT&lt;/a&gt;. Para conseguir esto he guardado el usuario y la contraseña del punto en varias globales que son usadas por la librería &lt;a href="https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/network/esp_wifi.html"&gt;&lt;code&gt;esp_wifi.h&lt;/code&gt;&lt;/a&gt; lo cual es una solución válida si no deseamos que esta información cambie nunca. Sin embargo, para mi proyecto necesito una solución que:&lt;/p&gt;</description><content:encoded><![CDATA[<p>Actualmente estoy realizando un proyecto con el chip <a href="https://documentation.espressif.com/esp32-c3_datasheet_en.html">ESP32-C3</a> que tiene que conectarse a un punto Wi-Fi mediante su antena integrada y mandar una serie de datos por el protocolo <a href="https://mqtt.org/">MQTT</a>. Para conseguir esto he guardado el usuario y la contraseña del punto en varias globales que son usadas por la librería <a href="https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/network/esp_wifi.html"><code>esp_wifi.h</code></a> lo cual es una solución válida si no deseamos que esta información cambie nunca. Sin embargo, para mi proyecto necesito una solución que:</p>
<ol>
<li>Me permita cambiar estas variables mientras el código está funcionando.</li>
<li>Le permita al usuario hacerlo sin tener que volver a compilar el código.</li>
<li>Se guarde en una memoria no volátil, para que, en caso de un corte de energía, la información permanezca en el controlador</li>
</ol>
<p>En este post describo mi solución a estos problemas, pasando por alternativas que podrían ser igualmente válidas para el lector en el caso de este lo requiera.</p>
<h1 id="interfaz-de-comunicación">Interfaz de comunicación</h1>
<p>Como ya he descrito, en mi caso necesito que las variables de conexión al punto Wi-Fi sean variables, para poder funcionar en cualquier instalación que se desee. En primer lugar debemos pensar en cómo interactuará el usuario con nuestro dispositivo. Las principales interfaces que ofrece el chip son:</p>
<ul>
<li><strong>Conexión física</strong>: En el caso en que nuestro usuario tenga acceso directo al dispositivo, este podría ser programado mediante el terminal o una utilidad como <a href="https://putty.org/index.html">PuTTy</a></li>
<li><strong>Conexión remota</strong>: El ESP32-C3 cuenta con las siguientes interfaces
<ul>
<li><strong>Bluetooth</strong>: Activando la interfaz Bluetooth se podría enviar la información mediante aplicaciones como <a href="https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal&amp;hl=en-US">Serial Bluetooth Terminal</a></li>
<li><strong>Wi-Fi</strong>: Teniendo a su vez 2 alternativas.
<ul>
<li>Conectarse a un punto Wi-Fi existente, que es justo lo que buscamos y lo que puede llegar a fallar</li>
<li>Crear un HotSpot, es decir, un punto de acceso donde conectar otro dispositivo para interactuar con nuestro ESP32</li>
</ul>
</li>
<li><strong>Zigbee</strong>: Necesitando que el usuario tenga un Coordinador Zigbee para hablar de forma directa con el dispositivo.
Tras considerar estas alternativas he decido utilizar un HotSpot, ya que, a diferencia de todas las soluciones anteriormente descritas, es la única que no requiere de ningún dispositivo adicional (cables, programas o dispositivos adicionales), permitiendo modificar las variables únicamente mediante un dispositivo Wi-Fi, como un teléfono.</li>
</ul>
</li>
</ul>
<h2 id="programación">Programación</h2>
<p>Una vez decidido el canal, debemos determinar <strong>la forma en la que</strong> los datos se enviarán al dispositivo. Una forma técnica sería enviando una petición HTTP mediante un post con la información que se desee, pero no es una solución fácil de explicar a un usuario no técnico, es por ello que he decidido que el mismo ESP32 tenga una página web donde se puedan configurar las variables. Esta solución tendrá la siguiente forma:</p>
<h3 id="hotspot">HotSpot</h3>
<ol>
<li>En primer lugar iniciaremos el punto de acceso:</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">//              Access Point
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">wifi_init_softap</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="nf">esp_netif_create_default_wifi_ap</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="kt">wifi_init_config_t</span> <span class="n">cfg</span> <span class="o">=</span> <span class="nf">WIFI_INIT_CONFIG_DEFAULT</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="nf">ESP_ERROR_CHECK</span><span class="p">(</span><span class="nf">esp_wifi_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cfg</span><span class="p">));</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="kt">wifi_config_t</span> <span class="n">wifi_config</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="p">.</span><span class="n">ap</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">            <span class="p">.</span><span class="n">ssid</span> <span class="o">=</span> <span class="n">WIFI_SSID_AP</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">            <span class="p">.</span><span class="n">ssid_len</span> <span class="o">=</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">WIFI_SSID_AP</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="p">.</span><span class="n">channel</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">            <span class="p">.</span><span class="n">password</span> <span class="o">=</span> <span class="n">WIFI_PASS_AP</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">            <span class="p">.</span><span class="n">max_connection</span> <span class="o">=</span> <span class="n">MAX_STA_CONN</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">            <span class="p">.</span><span class="n">authmode</span> <span class="o">=</span> <span class="n">WIFI_AUTH_WPA_WPA2_PSK</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">strlen</span><span class="p">(</span><span class="n">WIFI_PASS_AP</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="n">wifi_config</span><span class="p">.</span><span class="n">ap</span><span class="p">.</span><span class="n">authmode</span> <span class="o">=</span> <span class="n">WIFI_AUTH_OPEN</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="nf">ESP_ERROR_CHECK</span><span class="p">(</span><span class="nf">esp_wifi_set_mode</span><span class="p">(</span><span class="n">WIFI_MODE_AP</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="nf">ESP_ERROR_CHECK</span><span class="p">(</span><span class="nf">esp_wifi_set_config</span><span class="p">(</span><span class="n">WIFI_IF_AP</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">wifi_config</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="nf">ESP_ERROR_CHECK</span><span class="p">(</span><span class="nf">esp_wifi_start</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;Wi-Fi AP started. SSID=&#39;%s&#39;, IP=192.168.4.1&#34;</span><span class="p">,</span> <span class="n">WIFI_SSID_AP</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="páginas">Páginas</h3>
<p>En segundo lugar tendremos el web server, que tendrá a su vez 2 páginas, la página de registro de credenciales y la página encargada de guardarlas.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">//              WebServer
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span><span class="kt">httpd_handle_t</span> <span class="nf">start_webserver</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="kt">httpd_config_t</span> <span class="n">config</span> <span class="o">=</span> <span class="nf">HTTPD_DEFAULT_CONFIG</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="kt">httpd_handle_t</span> <span class="n">server</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">httpd_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">server</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">config</span><span class="p">)</span> <span class="o">==</span> <span class="n">ESP_OK</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;HTTP server started&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="kt">httpd_uri_t</span> <span class="n">root</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">            <span class="p">.</span><span class="n">uri</span>      <span class="o">=</span> <span class="s">&#34;/&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">            <span class="p">.</span><span class="n">method</span>   <span class="o">=</span> <span class="n">HTTP_GET</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="p">.</span><span class="n">handler</span>  <span class="o">=</span> <span class="n">root_get_handler</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">            <span class="p">.</span><span class="n">user_ctx</span> <span class="o">=</span> <span class="nb">NULL</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="nf">httpd_register_uri_handler</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">root</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="kt">httpd_uri_t</span> <span class="n">submit</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">            <span class="p">.</span><span class="n">uri</span>      <span class="o">=</span> <span class="s">&#34;/submit&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">            <span class="p">.</span><span class="n">method</span>   <span class="o">=</span> <span class="n">HTTP_POST</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="p">.</span><span class="n">handler</span>  <span class="o">=</span> <span class="n">submit_post_handler</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="p">.</span><span class="n">user_ctx</span> <span class="o">=</span> <span class="nb">NULL</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="nf">httpd_register_uri_handler</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">submit</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="nf">ESP_LOGE</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;Failed to start HTTP server&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="k">return</span> <span class="n">server</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h4 id="página-de-credenciales">Página de credenciales</h4>
<p>Página donde se introducirán las credenciales</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">//              HTML Website
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="kt">char</span> <span class="n">html_page</span><span class="p">[</span><span class="mi">512</span><span class="p">];</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">build_html_page</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">current_ssid</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">current_pass</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="nf">snprintf</span><span class="p">(</span><span class="n">html_page</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">html_page</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="s">&#34;&lt;!DOCTYPE html&gt;&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="s">&#34;&lt;html&gt;&#34;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="s">&#34;&lt;head&gt;&lt;title&gt;ESP32 Config&lt;/title&gt;&lt;/head&gt;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="s">&#34;&lt;body&gt;&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="s">&#34;&lt;h2&gt;ESP32 Configuration Portal&lt;/h2&gt;&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="s">&#34;&lt;p&gt;Current Wi-Fi:&lt;/p&gt;&#34;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="s">&#34;&lt;ul&gt;&lt;li&gt;SSID: %s&lt;/li&gt;&lt;li&gt;Password: %s&lt;/li&gt;&lt;/ul&gt;&#34;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="s">&#34;&lt;form method=</span><span class="se">\&#34;</span><span class="s">POST</span><span class="se">\&#34;</span><span class="s"> action=</span><span class="se">\&#34;</span><span class="s">/submit</span><span class="se">\&#34;</span><span class="s">&gt;&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="s">&#34;New SSID:&lt;br&gt;&#34;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="s">&#34;&lt;input type=</span><span class="se">\&#34;</span><span class="s">text</span><span class="se">\&#34;</span><span class="s"> name=</span><span class="se">\&#34;</span><span class="s">ssid</span><span class="se">\&#34;</span><span class="s">&gt;&lt;br&gt;&lt;br&gt;&#34;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="s">&#34;New Password:&lt;br&gt;&#34;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="s">&#34;&lt;input type=</span><span class="se">\&#34;</span><span class="s">password</span><span class="se">\&#34;</span><span class="s"> name=</span><span class="se">\&#34;</span><span class="s">password</span><span class="se">\&#34;</span><span class="s">&gt;&lt;br&gt;&lt;br&gt;&#34;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="s">&#34;&lt;input type=</span><span class="se">\&#34;</span><span class="s">submit</span><span class="se">\&#34;</span><span class="s"> value=</span><span class="se">\&#34;</span><span class="s">Save</span><span class="se">\&#34;</span><span class="s">&gt;&#34;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="s">&#34;&lt;/form&gt;&#34;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="s">&#34;&lt;/body&gt;&#34;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="s">&#34;&lt;/html&gt;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="n">current_ssid</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">?</span> <span class="nl">current_ssid</span> <span class="p">:</span> <span class="s">&#34;Not set&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="n">current_pass</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">?</span> <span class="nl">current_pass</span> <span class="p">:</span> <span class="s">&#34;Not set&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="c1">//              HTTP Handlers
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="kt">esp_err_t</span> <span class="nf">root_get_handler</span><span class="p">(</span><span class="kt">httpd_req_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="kt">char</span> <span class="n">ssid</span><span class="p">[</span><span class="mi">32</span><span class="p">],</span> <span class="n">password</span><span class="p">[</span><span class="mi">64</span><span class="p">];</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="nf">load_saved_wifi</span><span class="p">(</span><span class="n">ssid</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ssid</span><span class="p">),</span> <span class="n">password</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">password</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="c1">// Print to serial
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="c1"></span>    <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;Current Wi-Fi: SSID=&#39;%s&#39;, PASSWORD=&#39;%s&#39;&#34;</span><span class="p">,</span> <span class="n">ssid</span><span class="p">,</span> <span class="n">password</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="nf">build_html_page</span><span class="p">(</span><span class="n">ssid</span><span class="p">,</span> <span class="n">password</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="nf">httpd_resp_set_type</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="s">&#34;text/html&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="nf">httpd_resp_send</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">html_page</span><span class="p">,</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">html_page</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="k">return</span> <span class="n">ESP_OK</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h4 id="página-de-almacenado">Página de almacenado</h4>
<p>Página donde se ejecutará la función de almacenado de las variables de la forma que se desee, en este caso en la memoria NVS que se explicará más adelante:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">static</span> <span class="kt">esp_err_t</span> <span class="nf">submit_post_handler</span><span class="p">(</span><span class="kt">httpd_req_t</span> <span class="o">*</span><span class="n">req</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="kt">char</span> <span class="n">content</span><span class="p">[</span><span class="mi">200</span><span class="p">];</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="nf">httpd_req_recv</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">content</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">content</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>  <span class="c1">// Get data from the last page
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="nf">httpd_resp_send_err</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">HTTPD_500_INTERNAL_SERVER_ERROR</span><span class="p">,</span> <span class="s">&#34;Failed to receive POST data&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="k">return</span> <span class="n">ESP_FAIL</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">content</span><span class="p">[</span><span class="n">ret</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="c1">// Parse form &#34;ssid=&lt;ssid&gt;&amp;password=&lt;pass&gt;&#34;
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"></span>    <span class="kt">char</span> <span class="n">ssid</span><span class="p">[</span><span class="mi">32</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="kt">char</span> <span class="n">password</span><span class="p">[</span><span class="mi">64</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="nf">sscanf</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="s">&#34;ssid=%31[^&amp;]&amp;password=%63s&#34;</span><span class="p">,</span> <span class="n">ssid</span><span class="p">,</span> <span class="n">password</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">ssid</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="k">if</span> <span class="p">(</span><span class="n">ssid</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;+&#39;</span><span class="p">)</span> <span class="n">ssid</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">password</span><span class="p">[</span><span class="n">i</span><span class="p">];</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="k">if</span> <span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="sc">&#39;+&#39;</span><span class="p">)</span> <span class="n">password</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39; &#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="c1">// Save to NVS and print
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"></span>    <span class="nf">save_wifi_credentials</span><span class="p">(</span><span class="n">ssid</span><span class="p">,</span> <span class="n">password</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="c1">// Confirmation page
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">response</span> <span class="o">=</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="s">&#34;&lt;html&gt;&lt;body&gt;&#34;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="s">&#34;&lt;h3&gt;Credentials Saved!&lt;/h3&gt;&#34;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="s">&#34;&lt;a href=</span><span class="se">\&#34;</span><span class="s">/</span><span class="se">\&#34;</span><span class="s">&gt;Go Back&lt;/a&gt;&#34;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="s">&#34;&lt;/body&gt;&lt;/html&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="nf">httpd_resp_sendstr</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">response</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="k">return</span> <span class="n">ESP_OK</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h1 id="memoria-permanente">Memoria permanente</h1>
<p>Ahora mismo tenemos una solución que puede obtener los datos que un usuario introduzca a través de una interfaz web, pero, ¿cómo almacenamos estos datos? Usar una variable que pasemos por distintas funciones podría ser una posible solución, pero esta no sería resistente ante reinicios del ESP, lo cual provocaría la pérdida de la información almacenada en memoria.</p>
<p>Por estos motivos es por los que decido almacenar las variables introducidas en la interfaz web dentro de la memoria no volátil, la memoria <a href="https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/storage/nvs_flash.html">NVS</a>. Esta memoria se encuentra en la Flash del ESP32 y es resistente a reinicios del sistema. Para esto crearemos 2 funciones, una para leer los datos de la memoria NVS y otro para almacenar nuevos datos.</p>
<h2 id="lectura-de-memoria-nvs">Lectura de memoria NVS</h2>
<p>En primer lugar tendremos una función que cargará de leer la memoria no volátil para ver si se encuentran variables ya guardadas dentro de la sección de <code>wifi_creds</code>. Si no es el caso yo he considerado como una buena opción retornar unas variables por defecto con estos valores.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">load_saved_wifi</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">ssid</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">ssid_len</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pass</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">pass_len</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="kt">nvs_handle_t</span> <span class="n">nvs_handle</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="kt">esp_err_t</span> <span class="n">err</span> <span class="o">=</span> <span class="nf">nvs_open</span><span class="p">(</span><span class="s">&#34;wifi_creds&#34;</span><span class="p">,</span> <span class="n">NVS_READONLY</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">nvs_handle</span><span class="p">);</span>  <span class="c1">// Open non-volatile storage with a given namespace from the default NVS partition
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="n">err</span> <span class="o">==</span> <span class="n">ESP_OK</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Namespace Exists
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"></span>        <span class="kt">size_t</span> <span class="n">required_size</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="n">required_size</span> <span class="o">=</span> <span class="n">ssid_len</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nf">nvs_get_str</span><span class="p">(</span><span class="n">nvs_handle</span><span class="p">,</span> <span class="s">&#34;ssid&#34;</span><span class="p">,</span> <span class="n">ssid</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">required_size</span><span class="p">)</span> <span class="o">!=</span> <span class="n">ESP_OK</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Get string value for given key
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"></span>            <span class="nf">strncpy</span><span class="p">(</span><span class="n">ssid</span><span class="p">,</span> <span class="n">WIFI_SSID</span><span class="p">,</span> <span class="n">ssid_len</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">required_size</span> <span class="o">=</span> <span class="n">pass_len</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nf">nvs_get_str</span><span class="p">(</span><span class="n">nvs_handle</span><span class="p">,</span> <span class="s">&#34;password&#34;</span><span class="p">,</span> <span class="n">pass</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">required_size</span><span class="p">)</span> <span class="o">!=</span> <span class="n">ESP_OK</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Get string value for given key
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"></span>            <span class="nf">strncpy</span><span class="p">(</span><span class="n">pass</span><span class="p">,</span> <span class="n">WIFI_PASSWORD</span><span class="p">,</span> <span class="n">pass_len</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="nf">nvs_close</span><span class="p">(</span><span class="n">nvs_handle</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="c1">// If namespace does not exist
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"></span>        <span class="c1">// Set Default values as a constant
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"></span>        <span class="nf">strncpy</span><span class="p">(</span><span class="n">ssid</span><span class="p">,</span> <span class="n">WIFI_SSID</span><span class="p">,</span> <span class="n">ssid_len</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="nf">strncpy</span><span class="p">(</span><span class="n">pass</span><span class="p">,</span> <span class="n">WIFI_PASSWORD</span><span class="p">,</span> <span class="n">pass_len</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;Using -&gt; SSID=&#39;%s&#39;, PASS=&#39;%s&#39;&#34;</span><span class="p">,</span> <span class="n">ssid</span><span class="p">,</span> <span class="n">pass</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h2 id="escritura-en-la-memoria-nvs">Escritura en la memoria NVS</h2>
<p>Por otro lado si se desean modificar estas variables se accederá a esos zonas de memoria y se introducirán los nuevos datos.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">static</span> <span class="kt">void</span> <span class="nf">save_wifi_credentials</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">ssid</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pass</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="kt">nvs_handle_t</span> <span class="n">nvs_handle</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">nvs_open</span><span class="p">(</span><span class="s">&#34;wifi_creds&#34;</span><span class="p">,</span> <span class="n">NVS_READWRITE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">nvs_handle</span><span class="p">)</span> <span class="o">==</span> <span class="n">ESP_OK</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="nf">nvs_set_str</span><span class="p">(</span><span class="n">nvs_handle</span><span class="p">,</span> <span class="s">&#34;ssid&#34;</span><span class="p">,</span> <span class="n">ssid</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="nf">nvs_set_str</span><span class="p">(</span><span class="n">nvs_handle</span><span class="p">,</span> <span class="s">&#34;password&#34;</span><span class="p">,</span> <span class="n">pass</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="nf">nvs_commit</span><span class="p">(</span><span class="n">nvs_handle</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="nf">nvs_close</span><span class="p">(</span><span class="n">nvs_handle</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;Saved credentials to NVS: SSID=&#39;%s&#39;, PASS=&#39;%s&#39;&#34;</span><span class="p">,</span> <span class="n">ssid</span><span class="p">,</span> <span class="n">pass</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h1 id="conclusión">Conclusión</h1>
<p>Cabe destacar que la solución aquí mencionada cuenta con una serie de vulnerabilidades a tomar en cuenta. En primer lugar se tiene un punto de acceso Wi-Fi constantemente abierto, lo cual puede suponer un riesgo de seguridad, ya que, cualquier usuario que llegue a obtener las credenciales puede interactuar con esta interfaz web y sacar de la misma las credenciales que se están usando actualmente. Por ello recomiendo usar un GPIO que funcione como Jumper para habilitar o no esta opción. Un ejemplo de esta configuración sería:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl">    <span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span>    <span class="c1">//              HotSpot
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"></span>    <span class="c1">// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span>    <span class="c1">// Initialize NVS
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"></span>    <span class="nf">ESP_ERROR_CHECK</span><span class="p">(</span><span class="nf">nvs_flash_init</span><span class="p">());</span>                <span class="c1">// Initialize the default NVS partition and check for errors
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="c1">// Jumper that defines if the Hotspot should be active
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"></span>    <span class="kt">gpio_config_t</span> <span class="n">io_conf</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">      <span class="p">.</span><span class="n">pin_bit_mask</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1ULL</span> <span class="o">&lt;&lt;</span> <span class="n">HOTSPOT_PIN</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">      <span class="p">.</span><span class="n">mode</span> <span class="o">=</span> <span class="n">GPIO_MODE_INPUT</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="p">.</span><span class="n">pull_up_en</span> <span class="o">=</span> <span class="n">GPIO_PULLUP_ENABLE</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">      <span class="p">.</span><span class="n">pull_down_en</span> <span class="o">=</span> <span class="n">GPIO_PULLDOWN_DISABLE</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="p">.</span><span class="n">intr_type</span> <span class="o">=</span> <span class="n">GPIO_INTR_DISABLE</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="nf">gpio_config</span><span class="p">(</span><span class="o">&amp;</span><span class="n">io_conf</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="kt">int</span> <span class="n">jumper_hotspot</span> <span class="o">=</span> <span class="nf">gpio_get_level</span><span class="p">(</span><span class="n">HOTSPOT_PIN</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">jumper_hotspot</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//Check if the jumper cable is active
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"></span>        <span class="nf">wifi_init_softap</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="nf">start_webserver</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="k">while</span> <span class="p">(</span><span class="nf">gpio_get_level</span><span class="p">(</span><span class="n">HOTSPOT_PIN</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="nf">vTaskDelay</span><span class="p">(</span><span class="nf">pdMS_TO_TICKS</span><span class="p">(</span><span class="mi">100</span><span class="p">));</span> <span class="c1">// Keep the code here while the user changes the nvs memory
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1"></span>        <span class="p">}</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="c1">// If jumper removed → reboot cleanly
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="c1"></span>        <span class="nf">esp_restart</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="p">}</span></span></span></code></pre></div><p>Además de esto el código del ESP32 actualmente no se encuentra encriptado, por lo que cualquier usuario podría leer la memoria del mismo y extraer su funcionamiento/obtener las credenciales que deseara. La memoria del ESP puede ser encriptada para este tipo de casos, pero no se documentará en este post.</p>
<p>Con esto dispones de una solución que permite a un usuario no técnico configurar variables almacenadas en la memoria de un ESP32 y garantizando la permanencia de los datos.  A continuación muestro un esquema del sistema que utiliza todas las funciones anteriormente descritas y que, en caso de conectarse al punto Wi-Fi realiza una serie de acciones hasta hacer un DeepSleep (esencialmente un reinicio).</p>
<p><img src="/esphotspotnvs.svg" alt="esphotspotnvs"></p>
]]></content:encoded></item></channel></rss>