from machine import Pin, PWM, I2C #Para usar na manipilação das GPIOs
from time import sleep_ms, ticks_ms
from i2c_Lcd import I2cLcd
import network #Para usar na conexão com a rede e no access point
import socket #Para construção a página http
#As linhas abaixo são opcionais:
import esp #Para usar na remoção de mensagens de sistema do ESP
import gc #Para remoção dos objetos não usados
esp.osdebug(None) #Desliga as mensagens de debug da espressif
gc.collect() #Garbage Collector - Limpa os objetos não usados da memória do microcontrolador
#Ajustando alguns objetos:
#Observação: os botões serão configurados como um INPUT_PULLUP, ou seja, seu valor lógico começa como 1(True)
botao1 = Pin(15, Pin.IN, Pin.PULL_UP) #Botão que ativa e desativa(o único que desativa) o alarme(sirene e estrobo)
#Estrobo:
led1 = Pin(2,Pin.OUT) #Led 1 do pisca-pisca
led2 = Pin(4,Pin.OUT) #Led 2 do pisca-pisca
#Sirene:
som = PWM(Pin(5,Pin.OUT), freq = 500, duty_u16 = 512)
botao2 = Pin(18, Pin.IN, Pin.PULL_UP) #Botão de pânico(Solta uma mensagem no LCD e ativa o alarme, porém não desativa-o)
#Configuração dos sensores:
#Sensor de abertura de janelas:
botao3 = Pin(13, Pin.IN, Pin.PULL_UP)
led3 = Pin(12, Pin.OUT)
#Sensor de presença na área externa:
botao4 = Pin(14, Pin.IN, Pin.PULL_UP)
led4 = Pin(27, Pin.OUT)
#Sensor perimétrico IR nos muros:
botao5 = Pin(26, Pin.IN, Pin.PULL_UP)
led5 = Pin.(25, Pin.OUT)
#Sensor de abertura de porta social/serviço:
botao6 = Pin(33, Pin.IN, Pin.PULL_UP)
led6 = Pin(32, Pin.OUT)
#Sensor de abertura do portão:
botao7 = Pin(35, Pin.IN, Pin.PULL_UP)
led7 = Pin(34, Pin.OUT)
#Declarando algumas variáveis de auxilio:
rep = 0 #Variável auxiliar para evitar o repique dos botões
t = 0 #Variável auxiliar de temporização
bot = True #Variável auxiliar booleana para os botões
a_leds #Variável auxiliar booleana para os leds do estrobo
i = 0 #Variável auxiliar de controle do alarme
#Configuração do LCD(serve para mostrar a mensagem do botão de pânico):
Endereco_padrao_do_LCD = 0x27
i2c = I2C(0, sda = Pin(22), scl = Pin(23), freq = 400000)
lcd = I2cLcd(i2c, Endereco_padrao_do_LCD, 2, 16)
#Configuração da página web:
wlan = network.WLAN(network.STA_IF) #Criação da station interface
wlan.active(True) #Ativação de interface
#Ajustanso as funções:
#Função que controla os botões:
#Definindo a interrupção:
#handler para a leitura do botão:
def apertouobotao(pino)
#Trazendo as variáveis para dentro da função:
global rep
global bot
#Configuração da lógica do aperto dos botões:
#Botão do alarme:
if ((ticks_ms() - rep) > 200): #O valor do repique é 200 milissegundos, o que significa dizer que o aperto dos botões só funciona após os 200 milissegundos se passarem
rep = ticks_ms()
#Lógica para a ativação do alarme:
if ((botao1.value == bot) or (botao2.value == bot) or (botao3.value != bot) or (botao4.value != bot) or (botao5.value != bot) or (botao6.value != bot) or (botao7.value != bot) ): #A condição leva em consideraçaõ os estados de todos os botões para ativar o alarme, sendo os botões 1 e 2 como True pois suas interrupções serão do tipo rising e o resto dos botões como False pois suas interrupções serão do tipo falling
if ((ticks_ms() - t) < 500): #Controla o ciclo do alarme em que o pisca-pisca acontece a cada meio segundo juntamente com a frequência do som do alarme que muda nesse mesmo intervalo de tempo, por isso o valor dessa subtração está menor que 500 millisegundos, já que esse if aciona a primeira parte do ciclo
led1.value(1)
led2.value(0)
som.duty_u16(512)
som.freq(250)
print("Alarme ligado.")
else: #Aqui o valor de ticks_ms - t > 500, logo vai acionar a segunda parte do ciclo
led1.value(not led1.value()) #Pega o valor oposto do valor do led1(led1 = 1 fica led1 = 0)
led2.value(not led2.value()) #led2 = 0 fica led2 = 1
som.duty_u16(512)
som.freq(250)
#Configurando o que cada botão faz:
#Botão de pânico:
if (botao2.value == bot):
lcd.putstr("ALERTA, INVASAO!LIGANDO PARA 190!") #Exibe uma mensagem de pânico no LCD. Observação: como o LCD tem 2 linhas e 16 colunas toda vez que todas as colunas de uma linha são preenchidas a mensagem continua sendo escrita na outra linha a partir da primeira coluna
#Sensor de abertura de janelas:
if (botao3.value(not botao2.value())): #Pega o valor oposto ao valor do botão 2 já que ele está com o tipo de interrupção oposta
led3.value(1)
print("Invasão pelas janelas detectada!")
else:
led3.value(not led3.value())
#Sensor de presença na área externa:
if(botao4.value(not botao2.value())):
led4.value(1)
print("Presença na área externa detectada!")
else:
led4.value(not led4.value())
#Sensor perimétrico IR nos muros:
if(botao5.value == not botao2.value):
led5.value(1)
print("Invasão pelos muros detectada!")
else:
led5.value(0)
#Sensor de abertura de porta social/serviço:
if(botao6.value != bot):
led6.value(1)
print("Invasão pela porta de social/serviço detectada!")
else:
led6.value(0)
#Sensor de abertura do portão:
if(botao7.value == botao6.value):
led7.value(1)
print("Invasão pelo portão detectada!")
else:
led7.value(0)
#Lógica para a desativação do alarme:
elif (botao1.value(not botao1.value)): #O alarme apenas é desligado quando o valor lógico do botão for diferente de quando seu valor liga o alarme
led1.value(0)
led2.value(0)
som.duty_u16(0)
print("Alarme desligado.")
#Ajusta as interrupções dos botões do alarme e de pânico e os seus respectivos handlers. Já que a interrupção está como rising o aperto do botão só vai contar após ele ser solto, pois ele começa em com o valor lógico de 1, quando é apertado ele vai para 0 e quando é solto volta para 1, ou seja, o aperto só funciona quando o botão é solto:
botao1.irq(trigger = Pin.IRQ_RISING, handler = apertouobotao)
botao2.irq(trigger = Pin.IRQ_RISING, handler = apertouobotao)
#Ajusta a interrupções dos sensores e o seus respectivo handlers. Já que a interrupção está como falling o aperto do botão só conta enquanto ele está pressionado, pois ele começa em com o valor lógico de 1, quando é apertado ele vai para 0, ou seja, o aperto só funciona quando o botão é pressionado, diferentemente do botão do alarme
botao3.irq(trigger = Pin.IRQ_FALLING, handler = apertouobotao)
botao4.irq(trigger = Pin.IRQ_FALLING, handler = apertouobotao)
botao5.irq(trigger = Pin.IRQ_FALLING, handler = apertouobotao)
botao6.irq(trigger = Pin.IRQ_FALLING, handler = apertouobotao)
botao7.irq(trigger = Pin.IRQ_FALLING, handler = apertouobotao)
#Função que se conecta à rede:
def conectar(rede,senha):
global wlan
if (not wlan.isconnected()):
wlan.connect(rede,senha)
while (not wlan.isconnected()):
pass
return True
#Função que disponibiliza acesso a outros dispositivos:
def disponibilizaracesso(nomerede):
#Ajustando o access point (AP):
ap = network.WLAN(network.AP_IF) #Criando a interface do access point
ap.active(True)
ap.config(max_clients=5)
ap.config(ssid = 'RedeESP32', authmode=network.AUTH_WPA_WPA2_PSK, password = 'ESP32_Senha123')
if (ap.active()):
saida = True
else:
saida = False
return saida
#Função que mostra a página de acordo com o led da placa:
def pagina():
if led.value():
estado = "Sistema de Segurança Ativado"
else:
estado = "Sistema de Segurança Desativado"
html = """
<html>
<head>
<title>Gerenciamento de Segurança Residencial</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="icon" href="data:,">
<style>
html{font-family: Helvetica; display:inline-block; margin: 0px auto; text-align: center;}
h1{color: #020402; padding: 4vh;}
p{font-size: 1.5rem;}
.button{
background-color: #F80000;
border-radius: 10px;
padding: 16px 40px;
font-size: 30px;
margin: 2px;
}
.button2{background-color: #48f800;}
</style>
</head><body> <h1>Gerenciamento de Segurança Residencial</h1>
<p> <strong>""" + estado + """</strong></p>
<p><a href="/?ligaLED"><button class="button">Ativar botão de pânico</button></a></p>
<p><a href="/?desligaLED"><button class="button button2">Desativar botão de pânico</button></a></p></body></html>"""
return html
print('ESP32 iniciado!')
if conectar('Ana Cláudia','27102006'):
print('Conectado à rede:', wlan.ifconfig())
#Criando um socket para ficar ouvindo os requests de página (porta 80):
#Observação: a resposta ao request será o envio da página na variável html
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #Criando um socket TCP/IP
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #Deixa reutilizar um IP
s.bind(('',80)) #Ajusta para receber conexões de um determinado IP (vazio para qualquer IP) na porta 80
s.listen(4) #Número máximo de conexões recebidas=4
'''
if disponibilizaracesso('coice de preá'):
print('rede ',nomerede,' disponível!')
'''
#Loop pra ficar ouvindo requisições e lendo a interação dos usuários com o servidorzinho:
while True:
conexao, endr = s.accept() #Método para aceitar a conexão, salvando em endr o endereço, enquanto conexao fica com a troca de pacotes do socket s
print('Conexão recebida de %s' % str(endr))
request = conexao.recv(1024)
request = str(request)
print('Solicitação recebida: %s' % request)
#Lendo se houve request para apagar e acender o LED:
led_on = request.find('/?ligaLED')
led_off = request.find('/?desligaLED')
if (led_on == 6):
#O led do esp liga junto aos led do estrobo
led1.value(1)
led2.value(1)
a_leds = True #Define a variável auxiliar booleana do led como True porque ela vai ser utilizada para a parte do código que controla o estrobo
if (led_off == 6):
led1.value(0)
led2.value(0)
som.duty_u16(0)
if (a_leds == True): #Controla o estrobo
i = i + 1
rep = ticks_ms()
led1.value(i%2)
led2.value(not led1.value())
som.duty_u16(512)
if (i%2 == 0):
som.freq(250)
else:
som.freq(300)
resposta = pagina() #Carrega em "resposta" a página atualizada pela função "pagina"
#Finalmente, manda a página atualizada pro acessante:
conexao.send('HTTP/1.1 200 OK\n')
conexao.send('Content-Type: text/html\n')
conexao.send('Connection: close\n\n')
conexao.sendall(resposta)
conexao.close() #E encerra a conexão!