borne/main.py
2025-12-30 12:28:19 +01:00

191 lines
5.2 KiB
Python

from machine import Pin, I2C, RTC
from neopixel import NeoPixel
import network
import time
import ntptime
import urequests
import localtime_fr # TODO : Lire info HP.. HC.. sur HA > sensor.compteur_linky_ptec
import webrepl
class Bouton:
def __init__(self, nom, pin, todo = None, pin_led = None):
self.dernier_appui = 0
self.nom = nom
self.pin = Pin(pin, Pin.IN, Pin.PULL_UP)
self.pin.irq(trigger = Pin.IRQ_FALLING, handler = self.bouton_presse)
self.todo = todo
if pin_led is None:
self.avec_led = False
else:
self.avec_led = True
self.pin_led = Pin(pin_led, Pin.OUT)
def led_on(self):
if self.avec_led:
self.pin_led.on()
def led_off(self):
if self.avec_led:
self.pin_led.off()
def bouton_presse(self, pin):
self.maintenant = time.ticks_ms()
if time.ticks_diff(self.maintenant, self.dernier_appui) > DEBOUNCE_MS:
self.dernier_appui = self.maintenant
print("Bouton " + self.nom + " pressé !")
if self.todo is not None:
self.todo()
# Capter exception pour éviter les sorties intempestives (comme timeout sur ntp)
# Regarder https://docs.micropython.org/en/latest/esp32/quickref.html#timers
# led_jaune = Pin(0, Pin.OUT) # D0
# button_jaune = Pin(1, Pin.IN, Pin.PULL_UP) # D1
def action_jaune():
bouton_jaune.led_on()
led_bleue.off()
led_rouge.off()
set_relays(0b0011)
bouton_jaune = Bouton("jaune", 1, action_jaune, 0)
led_bleue = Pin(2, Pin.OUT) # D2
button_bleu = Pin(21, Pin.IN, Pin.PULL_UP) # D3
led_rouge = Pin(20, Pin.OUT) # D9
button_rouge = Pin(18, Pin.IN, Pin.PULL_UP) # D10
button_moins = Pin(16, Pin.IN, Pin.PULL_UP) # D6 (et masse)
button_plus = Pin(17, Pin.IN, Pin.PULL_UP) # D7 (et masse)
brightness = 0.01 # 1 %
def set_pixel(i, r, g, b):
np[i] = (
int(r * brightness),
int(g * brightness),
int(b * brightness)
)
pin_leds = Pin(19, Pin.OUT) # D8
np = NeoPixel(pin_leds, 10)
set_pixel(0, 0, 255, 0)
set_pixel(7, 0, 255, 0)
np.write()
# np.brightness(50)
i2c = I2C(scl=Pin(23), sda=Pin(22), freq=20000) # D5, D4
I2C_ADDR = 0x11
ntp_ok = False
ntp_ttl = 3600
ntp_attente = ntp_ttl
rtc = RTC()
pas_temps = 10
DEBOUNCE_MS = 500
dernier_appui = 0
token_ha = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkNGY4MDdmYWYzNDQ0NTc0ODY4MmFmNzA4NDdmMTE0MyIsImlhdCI6MTc2NDQ1Mzk0NSwiZXhwIjoyMDc5ODEzOTQ1fQ.DJgSqeTKPHWbKEFH3HuFih4QKt3CSqLqot34_vhCOQU"
def button_bleu_presse(pin):
global dernier_appui
maintenant = time.ticks_ms()
if time.ticks_diff(maintenant, dernier_appui) > DEBOUNCE_MS:
dernier_appui = maintenant
print("Bouton bleu !")
bouton_jaune.led_off()
led_bleue.on()
led_rouge.off()
set_relays(0b1100)
button_bleu.irq(trigger=Pin.IRQ_FALLING, handler=button_bleu_presse)
def button_rouge_presse(pin):
global dernier_appui
maintenant = time.ticks_ms()
if time.ticks_diff(maintenant, dernier_appui) > DEBOUNCE_MS:
dernier_appui = maintenant
print("Bouton rouge pressé !")
bouton_jaune.led_off()
led_bleue.off()
led_rouge.on()
set_relays(0b1100)
button_rouge.irq(trigger=Pin.IRQ_FALLING, handler=button_rouge_presse)
def button_moins_presse(pin):
global dernier_appui
maintenant = time.ticks_ms()
if time.ticks_diff(maintenant, dernier_appui) > DEBOUNCE_MS:
dernier_appui = maintenant
print("Bouton moins pressé !")
button_moins.irq(trigger=Pin.IRQ_FALLING, handler=button_moins_presse)
def button_plus_presse(pin):
global dernier_appui
maintenant = time.ticks_ms()
if time.ticks_diff(maintenant, dernier_appui) > DEBOUNCE_MS:
dernier_appui = maintenant
print("Bouton plus pressé !")
button_plus.irq(trigger=Pin.IRQ_FALLING, handler=button_plus_presse)
def set_relays(mask):
"""mask = bits 0..3 (1=ON, 0=OFF)"""
i2c.writeto_mem(I2C_ADDR, 0x10, bytes([mask]))
def HC(date_heure) -> bool:
heure, minute = date_heure[4], date_heure[5]
nb_minutes = heure * 60 + minute
_21h30 = 21 * 60 + 30 # TODO : Ne pas faire le calcul à chaque appel
_23h30 = 23 * 60 + 30
if (nb_minutes > _21h30 and nb_minutes < _23h30):
return True
return False
def ntp():
global ntp_ok, ntp_ttl, ntp_attente
if (wifi.isconnected() and (not ntp_ok or ntp_attente < 0)):
print("WIFI OK, call NTP")
ntptime.settime()
ntp_ok = True
ntp_attente = ntp_ttl
webrepl.start()
if (ntp_ok):
date_heure = localtime_fr.localtime()
print(f"Date et heure : {date_heure[3]}:{date_heure[4]}:{date_heure[5]} ({ntp_attente}, {HC(date_heure)})")
ntp_attente = ntp_attente - pas_temps
def charge() -> int:
try:
headers = {"Authorization": f"Bearer {token_ha}", "Content-Type": "application/json"}
response = urequests.get("https://ha-demo.arbi.fr/api/states/sensor.zoe_batterie", headers=headers)
data = response.json()
response.close()
return int(data["state"])
except Exception as e:
print("Erreur :", e)
return -1
# Init
set_relays(0b0000)
bouton_jaune.led_off()
led_bleue.off()
led_rouge.off()
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect("Livebox-BDC6", "KFQSn7PDCMSgPpM2Ws")
while True:
# now = datetime.now()
# print("Date et heure :", now)
ntp()
print(f"Charge : {charge()}")
time.sleep(pas_temps)
# set_pixel(0, 0, 0, 0) # OFF
# np.write()