So, once again, Google is saying goodbye to another service. Websites attached to the businesses profile you can create from Google Maps map points
My parents have a rental cabin by the lake, and my mom took advantage of this easy service of google, where you can quickly create a website so it gets linked in the Google Maps and well, it also worked as a standalone website for all intents and purposes.
These pasts few weeks I’ve been reading a lot about small/indie web and how companies do take most of our data with them when they shut down. A particularly sad website I came across it’s the google graveyard which lists all companies Google has killed.
They received a notice from google that they are shuting down these pages soon and gave no other option than just creating a new one form services like Wix. Which is not at all good nor an easy solution. https://support.google.com/business/answer/14368911?hl=en
Since my mom put effort on creating this website, I wanted to save it somehow, so I thought, since it’s basically static website with some dynamic comments, to create a local copy with wget and host it on my VPS under a new domain name I bought for the occasion: https://lagoyluz.com
wget --adjust-extension -H -k -K -p https://lagoyluz.negocio.site
I found these parameters to work best to download also some resources that were needed like CSS and Fonts, and some images. You can check the wget docs for the details on each parameter.
The cloned index.html itself was absolutely bloated with google’s javascript tracking code and it was completely unfriendly. I made a first pass of removing some scripting I thought not necessary for my clone, and manage to cut it down to a still not very nice 3500 lines of a lot of garbage. Anyway, everything was displayed and working except for the navigation menu and its links, which I did not investigate why in the cloned version did not worked so I just added my own Javascript to cover links and anchor functionality
I copied to a static folder behind my nginx reverse proxy and created a certificate for it with Let’s encrypt (which gave me some trouble cause I forgot again how the acme challenges worked). And after a few hours I had my own version of the website working under a new domain with SSL
Regarding the dynamic content, I will have to think in some backend or static build for my parent to be able to push new reviews they want to share and change the photographs
Now more than ever, I am feeling strong about walled gardens and the impact of trusting them with your information, work and time, just to be let down once they decide to shutdown x or y service for no reason other than not making billions a year. It is true, though, that an effort is required to make this process of self hosting or domain name driven identity more technically affordable. We need more services like the ones being developed by the Small Tech Foundation https://small-tech.org/, and go even further with high level services where spawning you digital identity with your own domain at home is a matter of a few clicks, just as easy as getting a new phone number.
https://boffosocko.com/2017/07/28/an-introduction-to-the-indieweb/
https://blog.morettigiuseppe.com/articles.html From when I helped to render the cabin’s blueprints
]]>I wanted to try adding 3d stuff to my drone footage in Lago Ranco, Chile. So it was a great opportunity to learn some basics on the VFX tools in Blender. I followed two tutorials for this.
Here is the result. There are several take aways. First I need to learn proper lighting, I should learn how to match the actual shadows in the footage.
I couldn’t get a good material for the STONE. I would like the stone material to be similar as the mountain. As if it was extracted from it.
But is a start.
]]>This project essentially follows the same approach as my previous Bed Lights project, utilizing the ESP32 and ESPHome, along with the same LED strip.
However, in this iteration, I introduced some automations. Apart from controlling the light in Home Assistant, I also integrated Chromecast with the TV. This integration allows me to determine whether the TV is on and which application is currently in use.
With this information, I implemented a couple of automations to adjust the light when the TV is in playback mode. Specifically, I dim the light when the TV is in playback, except for Spotify where the light effects differ.
Here are the details of the automations in YAML format:
alias: TV Light reacts to playback in TV
description: ""
trigger:
- platform: device
device_id: 43254314315431
domain: media_player
entity_id: 543265435432
type: playing
enabled: false
- platform: state
entity_id:
- media_player.livingroom_tv
attribute: app_name
from: com.google.android.apps.tv.launcherx
condition: []
action:
- if:
- condition: state
entity_id: media_player.livingroom_tv
attribute: app_name
state: com.spotify.tv.android
then:
- service: scene.turn_on
target:
entity_id: scene.chill
metadata: {}
else:
- service: scene.turn_on
target:
entity_id: scene.watching_tv
metadata: {}
mode: single
This YAML configuration was generated using the GUI to set up the automation. Two scenes with predefined light configurations were created, specifying color and brightness options. This allows for easy modification of the scenes without affecting the automation.
That’s all for today!
]]>This Monstera plant was a friend’s gift and it has been living in the floor a long time. Let’s overengineer a fix for this, that at least takes 10 times more time than go buy a stool in the shop next door.
It uses a 3d platform piece and three 2cm diameter 40cm long wooden sticks and I glued all together because it was faster.
The STL file it’s here. Or in the Thingiverse page
]]>If you’re like me, with a desktop PC that isn’t always online but houses your media server powered by Jellyfin, you’ve probably faced the challenge of waking it up quickly when needed. Jellyfin is an open-source media server that allows you to manage and stream your media collection effortlessly.
I initially experimented with the traditional magic packet approach, only to find that my motherboard didn’t fully support it, and reliability was a bit of an issue.
Enter the ESP32, a versatile microcontroller I’ve used in other projects, and ESPHOME. The ESP32 is a powerful and flexible microcontroller widely used in the maker community. ESPHOME is a framework for creating custom firmwares for ESP8266/ESP32 boards. After stumbling upon this project from Erriez, I discovered a solution where an ESP32 could intercept connections for the power and reset buttons of the desktop PC.
My initial prototype, though in a rather “temporary fashion,” successfully allowed me to power up the PC. You can find the details on how to build the circuit in the GitHub project page.
This is how the device turns out in HA.
However, reading the reset pin to determine the computer’s status proved to be a bit trickier than expected. Undeterred, I sought an alternative solution and found a Home Assistant companion app for Windows. This app, coupled with Mosquitto MQTT, allowed me to create a sensor in Home Assistant that could accurately report whether the computer was sleeping, off, or available. This way, I could make informed decisions about when to press the power button remotely before diving into a Jellyfin binge.
As I explored further, I discovered additional possibilities for improvement. Leveraging Google TV integration, which provides a sensor indicating the currently opened application, I could refine my setup. By identifying when Jellyfin was in use, I could automatically check if the computer needed powering up, avoided the need to wake up the computer myself.
If you’re facing a similar challenge or love tinkering with home automation, give this approach a try.
ESP32 ftw
chao!
]]>Vamos a integrar un módulo ESP32 con cámara, sensor de movimiento y pantalla en mi instalación de Home Assistant. La clave para este proyecto fue la implementación de ESPHome, una plataforma que simplifica la integración de dispositivos ESP32 en Home Assistant.
El modulo que tenía guardado hace un tiempo es el TTGO: LILYGO® TTGO T-Camera ESP32 WROVER cámara 0,96 OLED. Importante es que la versión de mi placa es 1.6.2. Eso sera relevante a la hora de identificar los diferentes pines de los periféricos.
Al principio, me encontré con un problema al intentar cargar el programa en el ESP32. Por algún motivo en MacOS era imposible hace la carga del programa en el ESP32. Quizás los drivers USB/Serial. La solución fue cambiar a Windows. Desde Windows pude cargar los binario desde ESPHome.
Experimenté dificultades con los pines de la cámara, ya que estaban ligeramente diferentes a los estándar. Afortunadamente, encontré ejemplos útiles que me ayudaron a solucionar este problema. El la sección de links “Configuración Funcional para TTGO ESP32 Camera Board” Uno de los comentarios propone una configuración de PINs que sirve para la placa 1.6.2
La configuración la hice toda a través de las herramientas de ESPHome. ESPHome es una plataforma de código abierto diseñada para simplificar la integración de dispositivos basados en ESP8266 y ESP32 con el ecosistema Home Assistant. Permite la configuración fácil y la programación de dispositivos IoT utilizando un formato YAML sencillo, lo que facilita la creación de firmware personalizado para una variedad de sensores, actuadores y otros componentes electrónicos.
Me base en la configuración de los links de recursos, pero finalmente adapté la configuración inicial de espHome con la de los posts de referencia. También añadí la configuración para poder enviar mensajes a la pantalla a través de una cola de MQTT. Esto último no tiene mucha utilidad pero era mi primera vez interactuando con MQTT.
esphome:
name: camera-1
esp32:
board: esp32dev
framework:
type: arduino
# Example configuration entry
mqtt:
broker: homeassistant
username: mosquitto
password: 432fr354g543r
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "fdsfdsfds+cKCuURB6GbFf4="
ota:
password: "fdsfdsfdsfds"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Camera-1 Fallback Hotspot"
password: "23243242d"
captive_portal:
# ttgo_camearv16 configuration
esp32_camera:
external_clock:
pin: GPIO4
frequency: 20MHz
i2c_pins:
sda: GPIO18
scl: GPIO23
data_pins: [GPIO34, GPIO13, GPIO14, GPIO35, GPIO39, GPIO38, GPIO37, GPIO36]
vsync_pin: GPIO5
href_pin: GPIO27
pixel_clock_pin: GPIO25
resolution: 640x480
jpeg_quality: 10
# Image settings
name: Camera 1
binary_sensor:
- platform: gpio
pin:
number: GPIO19
mode: INPUT
inverted: False
name: Camera 1 Motion
device_class: motion
filters:
- delayed_off: 1s
- platform: gpio
pin:
number: GPIO15
mode: INPUT_PULLUP
inverted: True
name: Camera 1 Button
filters:
- delayed_off: 50ms
- platform: status
name: Camera 1 Status
sensor:
- platform: wifi_signal
name: Camera 1 WiFi Signal
update_interval: 10s
- platform: uptime
name: Camera 1 Uptime
i2c:
sda: GPIO21
scl: GPIO22
# This file has to exists when compiling
font:
- file: "fonts/Roboto-Regular.ttf"
id: tnr1
size: 17
# Configuración para Mosquitto MQTT
text_sensor:
- platform: mqtt_subscribe
name: "Info for screen"
id: infocamera
topic: home/camera1_screen_text
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
address: 0x3C
rotation: 180
lambda: |-
it.printf(0, 0, id(tnr1), "%s", id(infocamera).state.c_str());
Antes de cargar espHome emite una key que habrá que introducir después para integrar el dispositivo, se tendrá que guardar hasta entonces.
Para aprovechar al máximo la pantalla, decidí utilizar MQTT para mostrar información relevante. Configuré manualmente la conexión con el servidor MQTT y agregué el componente necesario para la pantalla. MQTT tiene que estar instalado en Home Assistant. Se puede hacer a través del addon de Mosquitto. Se instala muy fácil. Luego solo queda definir un TOPIC donde se escriben y leen los mensajes de la cola. En mi caso home/camera1_screen_text. No es necesario que tenga esta estructura. Peru la estructura con / ayuda a organizar diferentes estancias.
Utilicé este pequeño script para probar mi configuración de Mosquitto que habia instalado en Home Assistant. Este script lo ejecuté desde otro ordenador conectado a la red.
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("home/camera1_screen_text")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set("mosquitto", "6Y2TRQuNtjPHqEvC")
client.connect("homeassistant", 1883, 60)
# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()
He realizado una modificación en la carcasa para mi proyecto del termostato, inspirado en el artículo Control de Calefacción con Home Assistant. La nueva tapa tiene los agujeros para la cámara, pantalla, botones y sensor de movimiento.
A continuación, puedes ver la foto de la nueva tapa:
El nuevo modelo no tenía las medidas adecuadas por tanto la placa no se cabia en el marco, pero como referencia, aquí están los enlaces a los archivos STL:
Asi se vé ya instalada
Aquí está la imagen de la configuración en HA, utilice una de las tarjetas predefinidas que pueden mostrar el video en la pantalla principal y ademas los botones para el sensor de movimiento y otras cosas que puedan haber en esa estancia (luces por ejemplo)
Es posible instalar un firmware que conecté la cámara a la red y asi poder acceder directamente a las imágenes. Se puede descargar desde “Documentación Original (YAML) - Importante para el Streaming” en los recursos de referencia.
Welcome, everyone! In this post, I’ll walk you through the process of setting up a Wordpress installation behind Docker, under a NGINX reverse proxy (to route different domains to different services), and Certbot to secure with SSL the site. Throughout this journey, I encountered and and somewhat successfully addressed various challenges.
To provide a bit of context, I manage a Virtual Private Server (VPS) on Digital Ocean. On this VPS, I have Docker installed, and I utilize an NGINX reverse proxy to serve not only this Wordpress installation but also my personal website and other services I need. My personal domain is pointing to this VPS, creating a cohesive and centralized environment for all my online endeavors.
I kicked off the process by installing WordPress through Docker. I have all my docker configs organized in folders depending on the service. My docker compose file for all Wordpress needs looks like this:
version: '3.4'
services:
database:
image: mysql:5.7
command:
- "--character-set-server=utf8"
- "--collation-server=utf8_unicode_ci"
ports:
- "3306:3306" # (*)
restart: on-failure:5
environment:
MYSQL_USER: wordpress
MYSQL_DATABASE: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: wordpress
wordpress:
depends_on:
- database
image: wordpress:latest
ports:
- "8008:80" # (*)
restart: on-failure:5
volumes:
- ./public:/var/www/html
environment:
WORDPRESS_DB_HOST: database:3306
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_NAME: wordpress
phpmyadmin:
depends_on:
- database
image: phpmyadmin/phpmyadmin
ports:
- 8084:80 # (*)
restart: on-failure:5
environment:
PMA_HOST: database
wordmove:
tty: true
depends_on:
- wordpress
image: mfuezesi/wordmove
restart: on-failure:5
container_name: luablu_wordmove # (+)
volumes:
- ./config:/home
- ./public:/var/www/html
- ~/.ssh:/root/.ssh # (!)
networks:
default:
external:
name: nginx-reverse_default
The most important part of this config is define the network and make all defined services belong to that network.
I had to be able to route the new domain to wordpress and I wasn’t able to find the host and port that contained the wordpress intallation. I ended up with this config.
server {
server_name domain.com;
listen 80 ;
# Do not HTTPS redirect Let'sEncrypt ACME challenge
location /.well-known/acme-challenge/ {
root /home/static-websites/letsencrypt;
auth_basic off;
allow all;
try_files $uri =404;
break;
}
location / {
return 301 https://$server_name$request_uri;
}
}
server {
server_name domain.com;
listen 443 ssl http2 ;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/nginx/letsencrypt/live/domain.com/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
proxy_pass http://wordpress:80/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The acme challenge will be relevant for later CERTBOT config. the firts block redirects to HTTPS. For now the important part is the proxy_pass. Which is pointing to the CONTAINER name and the exposed port. I actually didnt know you could use container’s name to point to it. Non of Ips or other known host names worked for me.
With these adjustments, I achieved accessibility to the WordPress site from any external location.
Moving on, I installed Certbot (from official docs)[https://certbot.eff.org/instructions?ws=other&os=ubuntufocal] on my Digital Ocean VPS to obtain an SSL certificate. This step presented 2 main hurdles:
Incorrect DNS redirect configuration: My domain’s IPV6 was not pointing to the correct IP from DO, this meant the Certbot challenges were failing
Utilizing the Certbot web-root plugin: Overcoming Let’s Encrypt challenges involved using the web-root plugin, with specific configuration for the challenge location pointing to the directory created by Certbot.
Successfully navigating these challenges, I generated the SSL certificates necessary to enhance the security of the site.
- /etc/letsencrypt/:/etc/nginx/letsencrypt
Recognizing that security extends beyond the initial certificate installation, I created a script that automates the renewal process. This script accesses the container and triggers a reload to apply the new certificates. This automation is seamlessly integrated into the Certbot renewal process, executed as a convenient hook.
To streamline the entire process, I added the certbot renewal
command with the hook to a cronjob on my Digital Ocean VPS. This ensures that the certificates are renewed at regular intervals, maintaining the site’s security and constant accessibility.
Since the certificate are only loaded once at boot by Nginx, after the cert is regenerated we need to restart nginx. I did thig by attaching a POST RENEWAL script to certbot with the following content.
#!/bin/bash
docker exec -it nginx-proxy service nginx reload
nginx-proxy is the name of the container that has my nginx reverser proxy, and the rest the command to execute inside the machine. Now to include the trigger we execute like this:
certbot renew --deploy-hook /root/scripts/letsencrypt/post-deploy-certbot-renewal.sh
Make sure you add the deploy hook for the auto renewal. It can be by placing it in the deploy hook folder inside etc/letsencrypt or defining it when you create the cert. When reniewing, certbot will remember.
Thats ALL!
]]>Vamos a esconder las luces de noche de la habitación detrás de la cama y controlarlas por Home Assistant. Aprovecharemos la integración con home assistant para sincronizar el encendido con la alarma del iPhone y para tener un botón rápido de encendido y apagado
Este es un proyecto muy sencillo ya que todo el software y configuraciones se hacen en via interfaz y se utilizan los mismos 5V por USB del ESP32 para alimentar las luces.
Primero partes y componentes!
Mi instalación de Home Assistant es en una raspberry, pero cualquier instalación serviría. Se pueden encontrar instrucciones en la web de Home Assistant para la instalación. (Esto probablemente sería lo más complicado de conseguir, hay falta de stock, aunque se supone debería volver en 2023)
Cualquier ESP32 debería funcionar. Se puede comprobar en la página de ESPHome Los míos son de AliExpress. También se puede encontrar en amazon: https://amzn.to/3jewNUA
En mi caso, estoy usando estas tiras de led. Lo importante es que sean tiras de leds WS2812B. Estas utilizan el tipo de direccionamiento compatible con el software que instalaremos en el ESP32
Vamos a instalar un WLED. Un firmware especial para controlar luces de este tipo y que tiene compatibilidad con home assistant integrada. Para esto basta con
Para conectar la placa a la tira de led necesitaremos 3 puntos. Un GPIO para controlar los leds, un pin de 5V y un GND. Por defecto el firmware admite conectar las luces en el puerto GPIO1 sin ninguna otra configuración.
De este paso hay muchos videos, por ejemplo: https://www.youtube.com/watch?v=TOEnFKLm9Sw
Una vez instalado el firmware y el ESP conectado, Home Assistant debería reconocer un dispositivo nuevo WLED que se puede configurar sin problemas y que dejara accesibles todas las entidades de la luces. Las que vamos a utilizar aquí, serán color y intensidad.
La primera automatización que se necesita es la de apagado y encendido. Me decanté por hacerlo con el móvil, asi no tenía que diseñar y implementar el botón físico. La idea es la siguiente: La aplicación para Home Assistant permite implementar acciones en el teléfono que se traducen en EVENTOS que se pueden leer desde home assistant. Utilizaremos uno de estos eventos para indicar encendido/apagado. Luego, a traves del widget para iOS de HA se puede acceder el botón fácilmente en cualquier lugar.
Vamos paso a paso: En la Aplicación vamos a Settings -> Companion App -> Actions -> Add Aquí solo tenemos que poner un nombre y guardar para después el EXAMPLE TRIGGER al final
Luego nos vamos a Home Assistant a Settings -> Automations & Scenes y creamos una nueva automatización. Dentro de la automatización hacemos click en los tres puntos de la derecha para abrir el editor YAML y usamos lo siguiente:
alias: Bedside light
description: Bedside light description
trigger:
- platform: event
event_type: ios.action_fired
event_data:
actionID: your_action_id
actionName: Read Light
condition: []
action:
- if:
- condition: device
type: is_on
device_id: your_device_id
entity_id: light.wled
domain: light
then:
- type: turn_off
device_id: your_device_id
entity_id: light.wled
domain: light
else:
- type: turn_on
device_id: your_device_id
entity_id: light.wled
domain: light
enabled: true
brightness_pct: 20
mode: single
Remplazamos el actionID con el valor del trigger example en la action la companion app que vimos antes, y también el device y entity del dispositivo añadido en Home Assistant. Esta misma configuración se puede conseguir igualmente solo con las opciones de la UI. Después solo queda añadir el widget de Home Assistant con las acciones y deberíamos tener algo como esto:
Para esto utilizaremos los Atajos de iOS, que nos permiten ejecutar una acción cuando se activa la alarma del móvil. La acción será enviar un evento a Home Assistant. Y de la misma manera que antes la utilizaremos para encender la luz a brillo máximo. El nombre de la acción no es relevante, mientras sea el mismo que leamos desde HA
Para encapsular el circuito diseñé una caja simple con cierre por imanes.
Como mejora, me gustaría añadir un botón manual de encendido en la cama. De este modo es mas fácil encender y apagar durante la noche si ver el móvil. EL firmware de WLED deja automáticamente el PIN GPIO0 como switch, si se conecta con tierra se apaga y enciende la luz, osea sería cuestión solo de diseñar el botón, sin requerir nada de esto software.
Otra mejora seria introducir un sensor de movimiento para en la noche al levantarse active dos o tres sensores de abajo para iluminar un poco el camino.
]]>Advertencia: Algunas conexiones trabajan a 220V, si no estás seguro de lo que haces mejor consultar un profesional.
La instalación de mi caldera actual tenía un termostato honeywell inalámbrico, que después de inspeccionarlo un poco solo tenía un par de relés. Parecía que accionaba la caldera con solo un interruptor.
Es un módulo termostato que se posiciona dentro de casa y manda la señal RF para activar el relé.
De la caldera bajaban dos pares de cables, uno de alimentación de 220v para alimentar el módulo inalámbrico y otro a modo de interruptor para activar y desactivar la caldera. [foto cableado y caldera]
A partir de videos y información de tipos de cableado y caldera se puede identificar que el A B es el cableado para poner en marcha la caldera. O sea, los cables A B los tenemos que poner en nuestro propio relé. Los cables NL son 220V de línea que alimentan el módulo inalámbrico, que en mi caso no he usado porque la ESP32 se alimenta por USB a un enchufe. Se podría haber puesto una placa transformadora, pero la verdad prefería no meterme a transformar esos voltajes.
La idea es utilizar una placa ESP32 con ESPHome conectado a Home Assistant, la placa acciona un módulo relé que activa y desactiva la caldera desde la interfaz de termostato de Home Assistant.
Vamos primero a listar todos los componentes necesarios.
Mi instalación de Home Assistant es en una raspberry, pero cualquier instalación serviría, siempre y cuando tenga Bluetooth. Los termómetros de Xiaomi que utilizo necesitan bluetooth. Se pueden encontrar instrucciones en la web de Home Assistant para la instalación. (Esto probablemente sería lo más complicado de conseguir, hay falta de stock, aunque se supone debería volver en 2023)
Cualquier ESP32 debería funcionar. Se puede comprobar en la página de ESPHome Los míos son de AliExpress. También se puede encontrar en amazon: https://amzn.to/3jewNUA
La mayoría funciona igual, los míos son de Amazon https://amzn.to/3HEgEBy
Este componente es el que usaremos para basar el control de temperatura. Tenía unos de Xiaomi que se pueden conectar a Home Assistant con este tutorial. Concretamente, el modelo es: https://es.aliexpress.com/item/1005005054100936.html
El circuito de control es muy sencillo, necesitaremos soldar 3 pines de la placa ESP32 al módulo Relé, uno de GPIO, cualquiera sirve, yo usé TODO. Luego necesitaremos un GND y un VCC. Suele haber un par de cada en las placas. Los de GND y VCC van al GND y VCC del módulo relé, y el GPIO al Signal line (en el caso del módulo del link mencionado anteriormente).
Cualquier tutorial de “controlar un rele con ESP32” mostrará una configuración similar, simplemente cambiarán que pines se usa.
Necesitaremos subir la configuración al módulo ESP32 para esto necesitaremos tener ESPHome en Home Assistant. Esto hay otras personas que lo explican mucho mejor que yo, por ejemplo aquí. El código que vamos a subir a la placa es el siguiente:
esphome:
name: boiler-control
esp32:
board: lolin32
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "ZQZysfdsfdsfsvc2+3rEbHA84g7uj9g="
ota:
password: "93eb9a3fdsfdsfds684d23fadee4a"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Boiler-Control Fallback Hotspot"
password: "dHFVhxEDkT0I"
captive_portal:
switch:
- platform: gpio
pin: 1
name: smartthermostatrelay
Casi todo será autogenerado durante la instalación del ESPHome en la placa, por lo que no tenemos que cambiar nada de eso, solo tendremos que añadir la parte que configura nuestro interruptor:
switch:
- platform: gpio
pin: 1
name: smartthermostatrelay
Esto hará que podamos referirnos a nuestra caldera como smartthermostatrelay dentro de Home Assistant
Una vez tenemos el termómetro configurado y nuestro interruptor con ESP32 también listo, solo necesitamos crear el componente de Termostato con el que podremos establecer la temperatura que queremos. Home Assistant hará el resto.
Esta sección se debe añadir al fichero /config/configuration.yaml que se puede acceder de muchas maneras, yo lo modifiqué con el ADDON File Editor
climate:
- platform: generic_thermostat
name: Termostato
heater: switch.smartthermostatrelay
target_sensor: sensor.termostato_temperature
Las dos variables importantes: heater es el relé que hemos instalado, debe coincidir con el nombre que le hayamos dado. Y luego, target_sensor, que sera la temperatura de referencia, este sensor saldrá del termómetro que se haya configurado.
Despues de un reinicio de Home Assistant el termostato debería ya ser visible y poder ajustarse a la temperatura deseada.
Para poder acceder desde fuera de casa y poder encender y apagar la calefacción antes de llegar a casa, yo utilizo el servicio de cloud del mismo home assistant, pero también es posible configurarlo manualmente, según algunos tutoriales.
Para proteger los componentes y poner todo debajo de la caldera, diseñé una caja, con los agujeros para atornillarla que coincidían con los que ya habían en la pared con el otro termostato, y para el cierre dejé unos pequeños huecos para pegar unos imanes y hacer un cierre magnético. Intente poner unas plataformas donde poner unos tornillos, pero no me salieron con las medidas correctas y simplemente pegue los componentes. No es ideal, pero funciona.
Todo instalado debajo de la caldera quedó así:
Lo primero que me gustaría mejorar es las temperaturas en las habitaciones, tengo varios termómetros más instalados en diferentes habitaciones, pero de momento solo tengo uno como referencia. Una mejora sería utilizar los sensores template de HA y dependiendo del momento del día, o una escena concreta, cambiar el termómetro de referencia. También podría ser basado en la media de todos los termómetros.
Ahora, el siguiente paso, sería integrar también las maquinas de aire acondicionado al sistema. HA con ESPHome también pueden controlar dispositivos con infrarrojos, como los mandos de los aires. Integrando los aires se podrían utilizar en modo caliente cuando la temperatura baje mucho y la caldera no sea suficiente. Pero también estará listo para controlar los aires en el verano con el mismo termostato.
]]>I wanted to try something related to programming but as different as possible as what I do as a software developer in a day to day basis, so I got back to Godot engine. I had downloaded it and tried it out for the first time during the first months of the pandemic, and did a couple of tests with some 3d models from Blender and I loved it. So this time I wanted to learn a bit how multiplayer would work in a simple 2d game. Just a couple of players and some guns.
The players should be able to see each other synchronized, be able to shoot and take damage and die. Simple enough. Also some of the tutorials I was following suggested a lobby and waiting room, so I did, because why not.
Now, a quick YouTube search took me to one excellent series on multiplayer Godot. This basically has all you need to start and also an explanation on the network concepts. I skipped things related to authentication since I’m obviously not there yet, but all the rest was perfectly applicable to my 2d fighter platformer.
It was easy enough to get tutorials on basic movement in 2D to allow my player to move around, and another one on how to create tilemaps for your world. I use some free game art from https://opengameart.org/ and move on with the multiplayer tutorials. Now, the following were my main pain points while understanding the code itself.
For me, the most difficult concept to grasp in the multiplayer environment was implementing interpolation and how to have players play in the past, so they have enough information to interpolate movement between the not so recent past and the recent past. This concept is much better explain in the Game Development Center’s series episode 12.
Here there’s another document that can help in understanding the justification behind this solution: entity-interpolation
Another issue is the fact that we need to account for the latency generated in the server-client communication, when not working you may encounter issues like this one:
Multiplayer is difficult 🥹🥹🥹 #gamedev #GodotEngine pic.twitter.com/zfqINjIWvc
— Giuseppe Moretti (@gmoretti) July 17, 2022
Here clock in the bottom right instance is behind so action coming from the server does not get “reproduced” in the correct time.
Once time is compensated, you can use that same clock to account for damage and/or deaths. You send a timestamp alongside this information when informing clients. And the clients wait for their clocks to match that timestamp to execute the actions.
This is the code in the client. We don’t react to the damage until the local clock is equal to the damage time.
# keys (damage variable) in damage_dict are timestamps
func ReceiveDamage():
for damage in damage_dict.keys():
if damage <= Server.client_clock:
#Reacting to the damage
current_hp = damage_dict[damage]["Health"]
damage_dict.erase(damage)
Now, once latency and clock are managed, things start to look much better.
Some progress on the latency and damage
— Giuseppe Moretti (@gmoretti) July 18, 2022
🙃#GodotEngine pic.twitter.com/gSpsrwXFMz
What I liked the most was the speed of iteration, Godot is very lightweight and launching a scene is super quick. Since I did not know about any engines, I first tried Unity and I felt like everything was too big, at least for what I needed. I had to get use to how a tiling system works and although it’s not specific from Godot the features for tiling were quite easy to work with once you know how of course.
On the other hand, there is a lot of use of String to connect things, string paths to refer to nodes and to signal callbacks. This is cool at the beginning, but when refactoring it makes it a little more cumbersome.
I was interesting to notice how the whole communication was simpler than it felt it would be. The way one server instance process handles one game. If you want more rooms, you need more instances of the server game process. After this principle, you can then use all sort of techniques to spawn your server processes, like basic scripting or containerized solutions. But the complexity at the bottom remains the same. One instance of the server handles one game.
multiplayer from 2 different machines, server handling collisions and interpolation between states. I do have some syncing issues after 10+min because of drfting clock tho #GodotEngine #gamedev 🤓 thanks @GamedevStefan for the amazin tutorials 👏👏 pic.twitter.com/zKdkcuIR4j
— Giuseppe Moretti (@gmoretti) July 31, 2022
The most difficult part for me was the clock and interpolation part. i would like to create a new project and just code again the multiplayer sync part, understanding how to improve it and why I am getting sync issues after some time connected into a game.
Also, I would like to maybe try a local co-op style focusing in just gameplay and not networking. The idea would be to tryout different mechanics and test them in different test project, as assignments to grasp concepts.
Links to the github repos with the server and client projects.
https://github.com/gmoretti/godot-online-multiplayer-fighter-client
https://github.com/gmoretti/godot-online-multiplayer-fighter-server
The amazing series where all this is actually explained , from Game Development Center https://www.youtube.com/watch?v=lnFN6YabFKg&list=PLZ-54sd-DMAKU8Neo5KsVmq8KtoDkfi4s
The amazing series where all this is actually explained , from Game Development Center https://www.youtube.com/watch?v=lnFN6YabFKg&list=PLZ-54sd-DMAKU8Neo5KsVmq8KtoDkfi4s
Another Multiplayer series for Godot from Rayuse, from which a learned how to create the lobby and waiting room https://www.youtube.com/watch?v=MGo06JvYkrA&list=PLRe0l8OGr7rcFTsWm3xyfCOP4NpH72vB1
]]>