Visualización del tiempo con Serverless y Colors | Programar Plus

me gusta trotar A veces hace frío afuera. A veces hace frío, pero mira como si no fuera El sol brilla, los pájaros cantan. Luego sales con pantalones cortos y una camiseta y te das cuenta de que tienes aproximadamente 2 minutos antes de que comience la exposición.

Decidí resolver este problema del primer mundo usando una bombilla para mostrar un cierto color en función de la temperatura exterior. Funciona mejor de lo que esperaba, y eso es decir algo porque normalmente nada sale como yo quiero.

Este fue un proyecto divertido de construir, y dado que es esencialmente un servicio alojado que se ejecuta en un temporizador, es un caso de uso perfecto para Serverless.

Ahora podrías estar pensando, “um, ¿no sería más fácil simplemente verificar el clima?” Bueno, lo sería, pero entonces no tendría una excusa para comprar una bombilla cara o escribir un artículo con la palabra “Sin servidor”.

Entonces, veamos cómo puedes construir tu propio Weather Bulb. El código final no es complicado, pero tiene algunas piezas interesantes que vale la pena mencionar. Por cierto, ¿mencioné que es Serverless?

Construyendo la bombilla meteorológica

Lo primero que vas a necesitar es la bombilla. No puedes tener una bombilla meteorológica sin bombilla. Di la palabra “bombilla” en voz alta unas 10 veces y notarás qué palabra tan extraña es. Bombilla, bombilla, bombilla, bombilla, ¿ves? Extraño.

Estoy usando el LIFX Mini Color. No es *demasiado* caro, pero lo que es más importante, tiene una API abierta de par en par.

La API tiene dos métodos de autenticación. El primero contiene la palabra “OAuth” y lamento que haya tenido que leer eso. No se preocupe, hay una manera más fácil que no involucra a OAu…. lo que no será nombrado.

La segunda forma es registrar una aplicación con LIFX. Obtiene una clave y todo lo que tiene que hacer es pasar esa clave con cualquier solicitud HTTP. Eso es lo que estoy usando para esta demostración.

Por ejemplo, si quisiéramos cambiar el color de la bombilla a azul, simplemente podemos pasar color: blue al /state punto final

La API admite algunos formatos de color diferentes, incluidos colores con nombre (como rojo, azul), valores hexadecimales, RBG, Kevlin, brillo de tono y saturación. Esto es importante porque tiene en cuenta lo que resultó ser la parte más difícil de este proyecto: convertir la temperatura en color.

Representando la temperatura con color

Si alguna vez ha visto un informe meteorológico, estará familiarizado con la forma en que la meteorología representa las condiciones climáticas con color en un mapa.

Por lo general, esto se hace para visualizar la precipitación. Probablemente hayas visto esa ominosa franja verde de tormentas acercándose a ti en un mapa meteorológico mientras tratas de averiguar si debes meterte en la bañera porque estás en el camino de un tornado. O tal vez solo somos todos nosotros, almas desafortunadas aquí en Tornado Alley de Estados Unidos.

El color también se usa para representar la temperatura. Esto es precisamente lo que quería hacer con la bombilla. Lo difícil es que no parece haber una forma estandarizada de hacer esto. Algunos mapas lo muestran como colores sólidos en bandas. En este caso, el azul podría representar la banda de 0°F a 32°F.

Otros lo tienen como una escala de gradiente que es más precisa. Esto es lo que buscaba para Weather Bulb.

Mi primer intento de resolver esto fue simplemente buscar en Google “escala de color de temperatura” y otras varias iteraciones de ese término de búsqueda. Recibí mucha información sobre Kelvin.

Kelvin es una representación de la temperatura de un color. Literalmente. Para cualquier fuente de luz (bombilla, sol, etc.), la temperatura real de esa fuente afectará el color de la luz que emite. Un fuego quema un color rojo amarillento. Cuanto más caliente se pone el fuego, más se mueve hacia el blanco. De ahí el dicho, “al rojo vivo”. Entonces, si alguien alguna vez dice “al rojo vivo”, puedes corregirlo frente a todos porque ¿quién no ama a un idiota pedante?

La bombilla LIFX es compatible con Kelvin, por lo que podría pensar que esto funcionaría. Después de todo, esta es la escala Kelvin…

El problema es que simplemente no hay suficiente variación de color porque estos no son colores reales, sino el matiz de color que emite una luz en función de su “temperatura”. Aquí está la rueda de colores Kelvin que viene con la aplicación LIFX.

Estos colores apenas se distinguen entre sí en la bombilla. No es exactamente lo que buscaba.

Eso me deja tratando de convertir el color a hexadecimal, RGB o algún otro formato. Esto es difícil porque ¿por dónde empiezas? Pasé una cantidad vergonzosa de tiempo ajustando los valores de escala RGB entre azul para frío (0, 0, 255) y rojo para caliente (255, 0, 0). Fue en ese momento que me di cuenta de que tal vez HSL sería una mejor manera de ir aquí. ¿Por qué? Porque matiz es mucho más fácil de entender.

Matiz

El tono es una representación del color en una escala de 0 a 360. Por eso, a menudo vemos el color representado en una rueda (360°). Esa es una gran simplificación, pero a menos que quieras que empiece a hablar de longitudes de onda, sigamos con esa definición.

La rueda de color de tono se ve así…

Si lo aplanamos, es más fácil razonar.

Estamos listos para convertir temperatura a color. Lo primero que debemos hacer es determinar un rango de temperatura establecido. Fui con 0℉ a 100℉. No podemos trabajar con infinitas combinaciones de colores de temperatura. Los números continúan para siempre, los colores no. Solo puede calentarse tanto antes de que nuestra bombilla esté de color rojo brillante todo el tiempo, y eso es 100 ℉. Lo mismo es cierto para el frío.

Si el azul claro representa 0°F, puedo comenzar en la marca de 200 en la escala de tonalidad. El rojo representará 100 ℉. Puede ver que el rojo está en ambos extremos, por lo que puedo moverme hacia la izquierda O hacia la derecha, según los colores que quiera usar para representar la temperatura. No es lo mismo que los colores que usan en los programas meteorológicos reales, pero ¿a quién le importa? Obviamente yo no.

Elegí ir a la derecha porque no hay rosa a la izquierda y el rosa es mi color favorito. También sentí que el rosa representa el calor un poco mejor que el verde. El verde es lluvia y tornados.

Ahora podemos volver a un tono basado en la temperatura. ¿Listo? Aquí vamos.

Supongamos que hace 50°F afuera.

Si 100°F es lo más caliente que vamos (360) y 0°F es lo más frío (200), entonces tenemos una escala de color de 160 puntos. Para saber dónde debemos estar en ese rango de 160 puntos, podemos dividir la temperatura actual por el límite superior de 100 °F, lo que nos dará el porcentaje exacto que necesitamos para movernos en nuestro rango, o 50 %. Si nos movemos el 50 % del camino hacia un rango de 160 puntos, eso nos deja en 80. Dado que comenzamos en 200, eso nos da un matiz de 280.

Eso suena complicado, pero solo porque los problemas de palabras en matemáticas CHUPAR. Así es como se ve el código cuando todo está dicho y hecho…

let hue = 200 + (160 * ( temperature / 100 ));

¡OK! Tenemos una escala de color dinámica basada en el tono, y si no lo supiera, podemos pasar el tono a LIFX de la misma manera que pasamos un color con nombre.

Ahora solo tenemos que averiguar cuál es la temperatura actual, volver a un tono y hacerlo cada pocos minutos. ¡Sin servidor, aquí vamos!

Funciones de temporizador sin servidor

Sin servidor está de moda. Es como solía ser HTML5: no importa lo que sea, solo importa que conozcas la palabra y no tengas miedo de usarla en una publicación de blog.

Para este ejemplo, usaremos Azure Functions porque hay soporte para disparadores de temporizador y podemos probar esos disparadores de temporizador localmente antes de implementarlos usando VS Code. Una de las cosas de Serverless que me irrita muchísimo es cuando no puedo depurarlo localmente.

Con Azure Functions Core Tools y Azure Functions Extension para VS Code, puedo crear un nuevo proyecto sin servidor y seleccionar un disparador de temporizador.

Los disparadores de temporizador en Azure Functions se especifican como expresiones cron. No te preocupes, yo tampoco sabía qué era eso.

Las expresiones cron le permiten ser muy específico con la definición de intervalos. Cron divide las cosas en segundo, minuto, hora, día, mes, año. Entonces, si quisiera ejecutar algo cada segundo de cada minuto de cada hora de cada día de cada año, su expresión se vería así…

* * * * * *

Si quisiera ejecutarlo todos los días a las 10:15, se vería así…

* 15 10 * * *

Si desea ejecutarlo cada 5 minutos (que es el valor predeterminado de Azure), lo especifica diciendo “cuando los minutos son divisibles por 5”.

0 */5 * * * *

A los efectos de esta función, lo configuramos en 2 minutos.

Estoy usando un intervalo de 2 minutos porque esa es la frecuencia con la que podemos llamar a la API meteorológica de forma gratuita 💰.

Obtener el pronóstico de DarkSky

DarkSky tiene una maravillosa API meteorológica a la que puede llamar hasta 1000 veces al día de forma gratuita. Si hay 1440 minutos en un día (y los hay), eso significa que podemos llamar a DarkSky cada 1,44 minutos por día y permanecer en la zona libre. Acabo de redondear a 2 minutos porque la temperatura no cambia tan rápido.

Así es como se ve nuestra función cuando llamamos a la API de DarkSky. Todos mis tokens, claves, configuraciones de latitud y longitud están en variables de entorno, por lo que no están codificados. Esos se establecen en el local.settings.json Archivo. solía axios para mis solicitudes HTTP porque es un paquete mágico, mágico.

const axios = require('axios');

module.exports = function (context, myTimer) {
  // build up the DarkSky endpoint
  let endpoint = `${process.env.DS_API}/${process.env.DS_SECRET}/${process.env.LAT}, 
                  ${process.env.LNG}`;
  
  // use axios to call DarkSky for weather
  axios
    .get(endpoint)
    .then(response => {
      let temp = Math.round(response.data.currently.temperature);
    
      // TODO: Set the color of the LIFX bulb
    })
    .catch(err => {
      context.log(err.message);
    });
};

Ahora que tengo la temperatura, necesito llamar a la API de LIFX. Y no lo sabría, alguien ya ha creado un paquete npm para hacer esto llamado lifx-http-api. Es por eso que amas JavaScript.

Configuración del tono de bombilla

Después de que vuelve el resultado del clima, necesito usar la instancia de la API de LIFX y llamar al setState método. Este método devuelve una promesa, lo que significa que necesitamos anidar promesas. Las promesas de anidamiento pueden salirse de control y podrían llevarnos de vuelta al infierno de devolución de llamada, que es lo que estamos tratando de evitar con las promesas en primer lugar.

En cambio, manejaremos la primera promesa y luego regresaremos Promise.all que podemos manejar en otro nivel superior then. Esto solo nos impide anidar. then declaraciones.

Recuerden niños, las promesas son solo devoluciones de llamada socialmente aceptables.

const axios = require('axios');
const LIFX = require('lifx-http-api');

let client = new LIFX({
  bearerToken: process.env.LIFX_TOKEN
});

module.exports = function (context, myTimer) {
  // build up the DarkSky endpoint
  let endpoint = <code>${process.env.DS_API}/${process.env.DS_SECRET}/${
    process.env.LAT
    },${process.env.LNG}<code>;
    
  // use axios to call DarkSky for weather
  axios
    .get(endpoint)
    .then(response => {
      let temp = Math.round(response.data.currently.temperature);
      
      // make sure the temp isn't above 100 because that's as high as we can go
      temp = temp < 100 ? temp : 100;
      
      // determine the hue
      let hue = 200 + (160 * (temp / 100));

      // return Promise.all so we can resolve at the top level
      return Promise.all([
        data,
        client.setState('all', { color: <code>hue:${hue}<code> })
      ]);
    })
    .then(result => {
      // result[0] contains the darksky result
      // result[1] contains the LIFX result
      context.log(result[1]);
    })
    .catch(err => {
      context.log(err.message);
    });
};

Ahora podemos ejecutar esto localmente y ver cómo funciona nuestro temporizador.

¡Eso es! Vamos a desplegarlo.

Implementación de la bombilla meteorológica

Puedo crear un nuevo proyecto de Functions desde la extensión de VS Code.

Puedo hacer clic con el botón derecho en “Abrir en el portal”, donde puedo definir una fuente de implementación para que absorba mi código de Github y lo implemente. Esto es ideal porque ahora, cada vez que presiono un cambio en Github, mi aplicación se vuelve a implementar automáticamente.

Todos saluden al bulbo meteorológico

¡Ahora siéntate y contempla el suave resplandor de la bombilla meteorológica! ¿Por qué mirar la temperatura real cuando puedes mirar este hermoso tono de rosa intenso?

¿Puedes adivinar cuál es la temperatura según lo que sabes de este artículo? La persona que deje un comentario y se acerque más recibirá una bombilla LIFX gratis de mi parte (porque los ❤️ a todos ustedes), o el costo de la bombilla si se encuentra fuera de los EE. UU. (~$40).

Puede tomar todo el código para este proyecto de Github.

(Visited 38 times, 1 visits today)