Introduction: Starting a Smart Home - Projeto Final

Projeto apresentado é parte do projeto final do curso de IoT aplicado a Smart Home.


O projeto mostrado a seguir é parte do projeto final a ser apresentado no curso de IoT aplicada a Smart Home, que consiste de sensores e atuadores conectados na DrangonBoard + Linker Mezzanine, um aplicativo desenvolvido com o ionic (a ser incluido em breve) e as informações/dados das "coisas" serão salvados na cloud da AWS. Para uma primeira iteração com a DragonBoard e IoT como um todo, decidiu-se fazer um sistema de acendimento automático de luzes, com um sensor de luminosidade, uma chave liga/desliga para ativar um aparelho de ar-condicionado de acordo com uma temperatura pre-setada e um sensor de proximidade que será instalado no portão de uma garagem, com a intenção de informar ao proprietário da casa se o portão encontra-se aberto ou fechado.

Step 1: Materias Necessários

  1. Place DragonBoard. https://www.amazon.com/DragonBoard-410C-IoT-Start...
  2. 96Boards Linker Mezzanine https://www.96boards.org/product/linkspritesensork...
  3. Sensor de luminozidade (LDR) que acompanha a Linker Mezzanine.
  4. Sensor de temperatura que acompanha a Linker Mezzanine.
  5. Botão touch que acompanha a Linker Mezzanine.
  6. Relé acompanha a Linker Mezzanine, utlizado para ligar o systema de A/C.
  7. LED acompanha a Linker Mezzanine, que representará a iluminação a ser ativada.
  8. Instalação das bibliotecas citadas no passo 5.

Step 2: Sensores, Atuadores E Conexões.

1. Linker Mezzanine:

Será necessário conectar a placa Mezzanine na dragonboard. Para detalhes, consultar link http://linksprite.com/wiki/index.php5?title=Linker...

2. Sensor luminosidade (LDR)

O sensor é parte do Kit da Linker Mezzanine e deverá ser conectado na entrada ADC1. Para detalhes técnicos: http://linksprite.com/wiki/index.php5?title=LDR_Mo...

3. Sensor de Temperatura

O sensor é parte do Kit da Linker Mezzanine e deverá ser conectado na entrada ADC2. Para detalhes técnicos: http://linksprite.com/wiki/index.php5?title=Therma...

4. Botão Touch

O sensor é parte do Kit da Linker Mezzanine e deverá ser conectado na entrada D1. Este botão irá ligar/desligar o sistema como um todo. O acesso a este botão é somente local. Para detalhes técnicos:http://linksprite.com/wiki/index.php5?title=Touch_...

5. Relé

O relé é parte do Kit da Linker Mezzanine e deverá ser conectado na entrada D2. Ele será utiizado para ligar/desligar o sistema de A/C.Para detalhes técnicos: http://linksprite.com/wiki/index.php5?title=Relay_...

6. LED

O LED é parte do kit da Linker Mezzanine e deverá ser conectado na entrada D4. O LED representará o sistema de iluminação de uma casa, seja algum cômodo interno da casa ou externo, como a iluminação de um jardim. Foi adicionado um resistor de 10k ohm em sério com o já existente para diminuir a corrente utilizada pelo sistema, já que em experiências anteriores verificou-se conflitos com as portas analógicas. Para detalhes técnicos: http://linksprite.com/wiki/index.php5?title=5mm_Re...

7. Sensor de contato magnético.

Este sensor foi comprado a parte e não faz parte do Kit da Linker Mezzanine. Ele será usado em uma janela ou no portão de uma garagem para informar se a janela/garagem está aberta ou fechada. O sensor é um conjunto formado por 2 pequenas peças (ver foto do Step acima), o sensor proprimamente dito e um pequeno "imã", que ao aproximar-se do sensor irá alterar o estado do sensor. O sensor utlizado neste projeto foi um N/A (normalmente aberto). Quando o imã não está próximo do sensor, o sensor reportará estado aberto. Quando o imã estiver próximo do sensor, o estado reportado será fechado.

Step 3: Aplicativo Para Controle Remoto

O aplicativo foi desenvolvido com o Ionic Framework, http://ionicframework.com/. Será necessário fazer o download e a instalação da ultima versão.

O aplicativo irá se comunicar (ler e atualizar os dados) com a cloud da AWS (AWS IoT- https://aws.amazon.com/iot/), que posteriormente será acessada pela placa dragonboard para atualização dos status dos sensores e atuadores.

- Sistema de Iluminação mostra o estado do sitesma de iluminação, ligado ou desligado. Quando o nível de luminosidade baixar do valor configurado, as luzes se acenderão automaticamente. Quando a intensidade de luz aumentar além do valor definido, as luzes se apagarão.

- O botão A/C acionará o relé, que por sua vez acionará o sistema de A/C da casa. Também é possível definir o valor desejado da temperatura. Assim que a temperatura da casa estiver maior do que a temperatura de acionamento, o A/C será ligado e permanecerá ligado até a temperatura abaixar em 2 graus da tempreatura definida. Por exemplo, iremos considerar que a temperatura é de 23 graus. Quando a temperatura interior chegar a 24 graus, o A/C será ligado e permanecerá ligado até a temperatura chegar a 20 graus, desligando então. Depois o ciclo se repetirá.

- Garagem informará a atual posição da garagem, se aberta ou fechada.

- Temperatura é apenas informativa e mostra a temperatura do interior da casa.

- Luminosidade é apesas informativa e mostra o valor da luminosidade atual.

Segue em anexo os arquivos home.html e home.ts contendos os códigos para comunicação com a cloud AWS e atualização do app.

Step 4: Programa Em Python

As seguintes bibliotecas serão necessárias para a execução do programa:

<p>import spidev<br>import time
import logging
import json
import argparse</p><p>from libsoc import gpio
from time import sleep
from datetime import date, datetime
from gpio_96boards import GPIO
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from AWSIoTPythonSDK.MQTTLib</p>

Segue abaixo código completo do programa:

<p>import spidev<br>import time
import logging
import json
import argparse</p><p>from libsoc import gpio
from time import sleep
from datetime import date, datetime
from gpio_96boards import GPIO
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient</p><p>GPIO_CS = GPIO.gpio_id('GPIO_CS') #Analog Port
BUTTON = GPIO.gpio_id('GPIO_A')
RELE = GPIO.gpio_id('GPIO_C')
LED = GPIO.gpio_id('GPIO_G')</p><p>pins = ((GPIO_CS, 'out'),
        (BUTTON, 'in'),
	(RELE, 'out'),	
	(LED, 'out'),
        )</p><p>def setdevices(deltaMessagePython):
	System_Status = deltaMessagePython['SystemStatus']
	Rele_Status = deltaMessagePython['AC']
	Led_Status = deltaMessagePython['SisIlumi']</p><p>	##### AC
	if Rele_Status == 1:
	    gpio.digital_write(RELE, GPIO.HIGH)</p><p>	if Rele_Status == 0:
	    gpio.digital_write(RELE, GPIO.LOW)</p><p>	##### Sistema de Iluminacao
	if Led_Status == 1:
	    gpio.digital_write(LED, GPIO.HIGH)	
	
	if Led_Status == 0:
	    gpio.digital_write(LED, GPIO.LOW)</p><p>def readadc(gpio):</p><p>	gpio.digital_write(GPIO_CS, GPIO.HIGH)
	time.sleep(0.0002)
	gpio.digital_write(GPIO_CS, GPIO.LOW)
	r = spi.xfer2([0x01, 0xA0, 0x00])#ADC2 - Temperature
	gpio.digital_write(GPIO_CS, GPIO.HIGH)
	adcout = (r[1] << 8) & 0b1100000000
	adcout = adcout | (r[2] & 0xff)	
	adc_temp = (adcout *5.0/1023-0.5)*100</p><p>	gpio.digital_write(GPIO_CS, GPIO.HIGH)
	time.sleep(0.0002)
	gpio.digital_write(GPIO_CS, GPIO.LOW)
	r = spi.xfer2([0x01, 0x80, 0x00])#ADC1 - Luminosity
	gpio.digital_write(GPIO_CS, GPIO.HIGH)
	adcoutldr = (r[1] << 8) & 0b1100000000
	adcoutldr = adcoutldr | (r[2] & 0xff)
	adcoutldr = str(adcoutldr)	
	now = datetime.utcnow()
	now_str = now.strftime('%Y-%m-%dT%H:%M:%SZ')
	temperatura = "{:.2f}".format(adc_temp)
	payload_temp = '{"state":{"desired": {"Luminosidade": ' + adcoutldr + ', "Temperatura": ' + temperatura + '}}}'
	myMQTTClient.publish("$aws/things/DBpyAWS1116/shadow/update", payload_temp, 0)
	return r</p><p>def desliga():
	gpio.digital_write(RELE, GPIO.LOW)
	gpio.digital_write(LED, GPIO.LOW)</p><p>def run(gpio):
    system_status = 1</p><p>    while True:
	time.sleep(2)        
	button_value = gpio.digital_read(BUTTON)
	print ("----")	
        time.sleep(0.25)
	if button_value == 1:
	   if system_status == 0:
		   system_status = 1 
	   else:
		   system_status = 0	
		   desliga()
   	
	
	if system_status == 1:
	   value = readadc(gpio)
   
	print "SYSTEM_STATUS %d" %system_status
	time.sleep(3)
    
 </p><p>class shadowCallbackContainer:
    def __init__(self, deviceShadowInstance):
        self.deviceShadowInstance = deviceShadowInstance</p><p>    # Custom Shadow callback
    def customShadowCallback_Delta(self, payload, responseStatus, token):
        print("Received a delta message:")
	### payload update script	
	payloadDict = json.loads(payload)
	deltaMessage = json.dumps(payloadDict["state"])
	print "DELTA MESSAGE %s" %deltaMessage
        ### Request to update the reported state
        newPayload = '{"state":{"reported":' + deltaMessage + '}}'
	deltaMessagePython = json.loads(deltaMessage)
	setdevices(deltaMessagePython)</p><p>spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 10000
spi.mode = 0b00
spi.bits_per_word = 8</p><p>####### Thing definition</p><p># AWS IoT certificate based connection
myMQTTClient = AWSIoTMQTTClient("DBpyAWS1116")
myMQTTClient.configureEndpoint("a28rqf8gnpw7g.iot.us-west-2.amazonaws.com", 8883)
myMQTTClient.configureCredentials("/home/linaro/shared/AWS/root-CA.crt", "/home/linaro/shared/AWS/"SUA CHAVE"-private.pem.key", "/home/linaro/shared/AWS/"SEU CERTIFICADO"-certificate.pem.crt")
myMQTTClient.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing
myMQTTClient.configureDrainingFrequency(2)  # Draining: 2 Hz
myMQTTClient.configureConnectDisconnectTimeout(10)  # 10 sec
myMQTTClient.configureMQTTOperationTimeout(5)  # 5 sec
 
#connect and publish
myMQTTClient.connect()
myMQTTClient.publish("coisajsb", "connected", 0)</p><p>########################</p><p>####### Shadow definition</p><p># Init AWSIoTMQTTShadowClient
myAWSIoTMQTTShadowClient = None
myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("DBpyAWS1116")
myAWSIoTMQTTShadowClient.configureEndpoint("SEU END-POINT.us-west-2.amazonaws.com", 8883)
myAWSIoTMQTTShadowClient.configureCredentials("/home/linaro/shared/AWS/root-CA.crt", "/home/linaro/shared/AWS/"SUA CHAVE"-private.pem.key", "/home/linaro/shared/AWS/"SEU CERTIFICADO-certificate.pem.crt")</p><p># AWSIoTMQTTShadowClient configuration<br>myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10)  # 10 sec
myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5)  # 5 sec</p><p># Connect to AWS IoT
myAWSIoTMQTTShadowClient.connect()</p><p># Create a deviceShadow with persistent subscription
deviceShadowHandler = myAWSIoTMQTTShadowClient.createShadowHandlerWithName("DBpyAWS1116", True)
shadowCallbackContainer_Bot = shadowCallbackContainer(deviceShadowHandler)</p><p># Listen on deltas
deviceShadowHandler.shadowRegisterDeltaCallback(shadowCallbackContainer_Bot.customShadowCallback_Delta)</p><p>#########################</p><p>myMQTTClient.publish("$aws/things/DBpyAWS1116/shadow/update", '{"state":{"desired": {"SystemStatus":1, "SisIlumi":0, "AC":0, "Garagem": "Fechada", "Temperatura": 25, "Luminosidade": 123}}}', 0)</p><p>if __name__ == "__main__":
    
    with GPIO(pins) as gpio:
         run(gpio)</p>

Step 5: Finalização

Após ter concluido os passos anteriores, deve-se inicializar o sistema executando o código fornecido no passo 5 e inicializar o app através do Ionic, usando o comando Ionic serve.

Para um possível troubleshoot, recomenda-se usar a função MQTT Client TEST do AWS, onde é possível verificar e as mensagens enviadas pela dragonboard está sendo atualizada de forma correta na AWS Cloud: https://us-west-2.console.aws.amazon.com/iotv2/hom...

Step 6: Criando Uma "coisa" Na AWS IoT

Para fazer o setup do IoT na AWS, os seguintes passos deverão ser seguidos:

1) Criar um projeto no AWS IoT atravé do link: https://console.aws.amazon.com/iot.

2) Clique "create a thing" e então, "Create a single thing". Dê o nome do projeto e clique em Next.

3) Na tela seguinte, clique em "Create a thing without certificate". Nesse tutorial não iremos utilizar os certificados por questões práticas, porém não é recomendado fazer o uso de IoT sem certificados.

4) Nesse momento, sua "coisa" já estará criada. Clique no botão da "coisa" que foi criado para abrir a tela com as opções. Nessa tela podemos ver os tópicosMQTT que podem ser usados para fazer a atualização dos dados a serem enviados para a Could, assim como é uma ótima ferramenta para troubleshooting. No código em Python que será apresentado em breve, foram utlizados alguns destes tópicos. Nas opções também podemos ver a "shadow", que nada mais é que a informação que está na dragonboard refletida na AWS Cloud.