Guilherme Anderson-PJI2-2020-1

De MediaWiki do Campus São José
Revisão de 18h00min de 20 de outubro de 2020 por Anderson.gm05 (discussão | contribs) (Diagrama de Implementação)
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para: navegação, pesquisa

Responsaveis

  • Anderson Gaspar, e-mail: andersongasparm@gmail.com
  • Guilherme Lopes Roque, email: guilherme.lroque@gmail.com

Levantamento de Requisitos

Funcionais:

  • RF.01 O sistema deve possuir uma estação Raspberry que servirá como gerenciador de sensores.
  • RF.02 O sistema deve permitir a instalação e remoção física de sensores da estação;
  • RF.03 O sistema deve possuir um servidor WEB (WSGI) para servir de interface com o administrador com o sistema;
  • RF.04 O sistema deve possuir um servidor de fila de mensagens (Broker) para as notificações, leitura e configuração dos limiares dos sensores através de redes externas.
  • RF.05 O sistema deve permitir a configuração valores limites de leitura dos sensores para gatilho das notificações da estação.
  • RF.06 O sistema suportar inicialmente os seguintes sensores:
  1. DHT11

Não funcionais:

  • RNF.01 - O usuário deve possuir um um sistema Linux Debian com interpretador python3 e estar conectado à Internet para interagir com o sistema.
  • RNF.02 - O usuário deve possuir um um sistema Linux Debian com interpretador python3 e instalador pip3 para instalar o sistema.
  • RNF.03 - O software desenvolvido para a estação Raspberry deve ser modular, prevendo futuras melhorias incrementais, como a compatibilidade com outros sensores;

Definições dos sujeitos

  • Sistema: Implementado pela estação meteorológica num dispositvo Raspberry e pelo servidor de fila de mensagens (Broker) num sistema linux. Este atende as requisições dos usuários primário (atua como sistema na linguagem UML) e exclusivamente no caso de uso Notificação atua como ator primário, sendo o iniciador da interação entre os sujeitos.
  • Administrador: Ator primário representado por uma pessoa física no ambiente local do sistema de estação meteorológica, este interage diretamente com a estação meteorológica na Raspberry através do protocolo HTTP.
  • Usuário: Ator primário representado por uma pessoa física em ambiente externo do sistema de estação meteorológica, este interage com a estação meteorológica por intermédio do Broker através do protocolo AMQP.
  • Sensor: Ator secundário que apenas executa rotinas solicitadas inicialmente pelos atores primários através do Sistema.

Casos de uso

Diagrama de caso local

Registrar sensor

Ator primário: Administrador.

Ator secundário: Sensor.


Fluxo principal:

  • O Administrador faz a instalação física do sensor na placa da Raspberry Pi.
  • O Administrador envia uma requisição HTTP contendo os dados do sensor a ser registrado diretamente para a estação meteorológica;
  • O sistema configura e ativa o sensor e responde ao Administrador uma mensagem HTTP de sucesso;

Remover sensor

Ator primário: Administrador

Ator secundário: Sensor.


Fluxo principal:

  • O Administrador envia uma requisição HTTP contendo o identificador do sensor a ser removido diretamente para a estação meteorológica.
  • A estação meteorológica remove o sensor de seus registros e rotinas e responde o Administrador uma mensagem HTTP de sucesso.
  • O Administrador faz desconexão física do sensor na placa da Raspberry Pi


Alterar registro Localmente

Ator primário: Administrador

Atores secundários: Sensor

Fluxo principal:

  • O Administrador envia uma requisição HTTP contendo os dados do sensor a ser atualizado diretamente para a estação meteorológica;
  • A estação meteorológica altera os registros do sensor e responde o administrador uma mensagem HTTP de sucesso;


Requisitar dados Localmente

Ator primário: Administrador

Atore secundários: Sensor.

Fluxo principal:

  • O administrador envia uma requisição HTTP contendo os dados do sensor a ser lido para a estação meteorológica;
  • A estação meteorológica lê o sensor e responde o usuário uma mensagem HTTP de sucesso com os dados lidos;

Alterar registro

Ator primário: Usuário

Atores secundários: Sensor

Fluxo principal:

  • O usuário envia uma requisição via AMQP contendo os dados do sensor a ser atualizado para o Broker;
  • O Broker executa suas rotinas internas de enfileiramento e roteamento e repassa a requisição para a estação meteorológica.
  • A estação meteorológica altera os registros do sensor e responde o usuário uma com mensagem de sucesso através do Broker;


Requisitar dados

Ator primário: Usuário

Atores secundários: Sensor.

Fluxo principal:

  • O usuário envia uma requisição via AMQP contendo os dados do sensor a ser lido para o Broker;
  • O Broker executa suas rotinas internas de enfileiramento e roteamento e repassa a requisição para a estação meteorológica.
  • A estação meteorológica lê o sensor e responde o usuário com os dados através do Broker;

Notificação

Ator primário: Estação Meteorológica

Atores secundários:Sensor e Usuário.

Fluxo principal:

  • O sistema identifica um valor fora dos limites configurados para o sensor através de sua rotina interna de leitura.
  • O sistema envia para todos os usuários a notificação através do Broker.

Diagrama de Implementação

Diagrama de Implementação

Diagrama de classes

Diagrama Conceitual

Diagrama Interface

Este foi o primeiro diagrama feito, antes mesmo de qualquer definição de implementação. Após a definição da linguagem de programação, estudo dos recursos já existentes, testes de conceito e testes de validação chegamos aos próximos diagramas.

Diagrama Interfaces

Diagrama Interface

Diagrama Driver

Diagrama Driver

Diagrama Usuário

Diagrama Usuario

Modelagem de interações

Notificação

Notificação

Sequência:

  • O notificador, implementado pela classe 'Publisher' entra no loop de leitura periódicas do sensor e realiza uma leitura do sensor que está fora dos limites máximo e mínimo configurados e então publica a notificação no Broker, através do método 'basic_publish()'.
  • O Broker disponibiliza (macro 'queue') a publicação da estação meteorológica para todos usuários que se inscreveram.
  • A classe AMQPListen consome (macro 'consume') a publicação disponibilizada pelo Broker e notifica o Usuário através da impressão da mensagem no terminal de execução do comando.

Leitura externa

Diagrama de Leitura externa


Sequência:

  • O usuário faz uma requisição de leitura de sensor ao Broker através do comando 'amqp-request -r'.
  • A instancia da classe AMQPRequest invocada através do comando 'amqp-request' publica no Broker a requisição do Usuário através do método 'basic_publish()'.
  • O Broker disponibiliza (macro 'queue') a publicação do Usuário para a instância da classe Consumer da estação meteorológica.
  • A estação meteorológica consome (macro 'consume') a publicação disponibilizada pelo Broker e lê o sensor através do método 'read()'.
  • A estação meteorológica retorna o valor lido para o Broker.
  • O Broker retorna o valor recebido para o Usuário.

Atualização Externa

Configuração Externa

Sequência:

  • O usuário faz uma requisição de configuração do sensor ao Broker através do comando 'amqp-request -c'.
  • A instancia AMQPRequest invocada através do comando 'amqp-request' publica no Broker a requisição do Usuário através do método 'basic_publish()'.
  • O Broker disponibiliza (macro 'queue') a publicação do Usuário para a estação meteorológica.
  • A instância da classe 'Consumer' da estação meteorológica consome (macro 'consume') a publicação disponibilizada pelo Broker e atualiza os registros do sensor.
  • A estação meteorológica retorna uma mensagem de sucesso ao Broker.
  • O Broker retorna a mensagem recebida para o Usuário.

Atualização Local

Configuração Local
  • Através de qualquer aplicação o Administrador envia uma requisição HTTP PUT diretamente a estação meteorológica.
  • A estação meteorológica atualiza os registros do sensor e retorna uma resposta HTTP de sucesso.

Configuração|Leitura Local

Leitura Local

Sequencia configuração:

  • Através de qualquer aplicação o Administrador envia uma requisição HTTP POST diretamente a estação meteorológica.
  • A estação meteorológica registra os dados do sensor, faz a ativação do sensor e retorna uma resposta HTTP de sucesso.

Sequencia leitura:

  • Através de qualquer aplicação o Administrador envia uma requisição HTTP GET diretamente a estação meteorológica.
  • A estação meteorológica lê os dados do sensor e retorna uma resposta HTTP de sucesso com os dados lidos.

Interação com o sistema

Instalação do Broker

 sudo apt install erlang
 sudo apt install rabbitmq-server 
 sudo rabbitmq-server enable rabbitmq_management
 sudo systemctl start rabbitmq-server.service
 sudo rabbitmqctl add_user admin admin
 sudo rabbitmqctl set_user_tags admin administrator	
 sudo rabbitmqctl set_permissions -p / admin "." "." "."

OBS: Para o nosso projeto foi criado um serviço RabbitMQ na nuvem no campus do IFSC, servindo com Broker.

Servidor: rabbitmq.sj.ifsc.edu.br

Gerenciamento do Broker

O gerenciamento do Broker é feito através do comando 'systemctl' de sistemas linux. Exemplos:

 sudo systemctl start rabbitmq-server.service #inicia o serviço
 sudo systemctl stop rabbitmq-server.service #interrompe o serviço
 sudo systemctl restart rabbitmq-server.service #reinicia
 sudo systemctl status rabbitmq-server.service #exibe o estado corrente

Nota: Toda configuração AMQP é feita a partir dos dispositivos finais.

Instalação da Estação Meteorológica

Instalação no sistema Linux Debian

 git clone https://github.com/GuilhermeRoque/PJ2.git
 cd PJ2/station/
 sudo chmod +x installer.sh
 sudo ./installer.sh

Instalação com Venv

 git clone https://github.com/GuilhermeRoque/PJ2.git
 cd PJ2/station/
 python3 -m venv venv
 source venv/bin/activate
 pip3 install -r requirements.txt

Execução da Estação Meteorológica

Instalação no sistema Debian

Os serviços já estão ativos e sendo gerenciados pelo systemd, o daemon gerencidar do sistema Linux Debian.

Instalação com Venv

 cd PJ2/station/interface/
 python3 mainWeb.py &
 python3 mainPublisherAMQP.py &
 python3 mainConsumerAMQP.py &
 cd ../driver/
 python3 mainDriver.py &

Instalação dos comandos de Usuário

Instalação em sistemas Linux Debian

 git clone https://github.com/GuilhermeRoque/PJ2.git
 cd PJ2/user/
 sudo chmod +x installer.sh
 ./installer.sh

Instalação com Venv

 git clone https://github.com/GuilhermeRoque/PJ2.git
 cd PJ2/user/
 python3 -m venv venv
 source venv/bin/activate
 pip3 install -r requirements.txt

API REST

Endpoint: /sensor`

GET

Retorna em `'application/json' uma leitura em tempo real do sensor informado. O corpo da requisição contém o id do sensor em formato application/json.

  • Corpo da requisição:
 {
     "id": "sensor1"
 }
  • Código de resposta de sucesso: 200 OK
  • Corpo da resposta:
  {
     "humidity": 50,
     "temperature": 26.0
  }
  • Código de resposta de erro 'sensor não não existe': '404 NOT FOUND'. Sem corpo de resposta.
  • Código de resposta de erro 'requisição inválida': '400 BAD REQUEST'. Sem corpo de resposta.

POST

Executa o cadastro de uma novo sensor. O corpo da requisição contém todos os parâmetros do sensor em formato `application/json`.

  • Requisitos:

Os seguintes atributos são obrigatórios no corpo da requisição:`id`, `max` `min`, `model`, `data_type` e `type_specific`.

  • Corpo da requisição:
 {
     "id": "sensor1",
     "max": "24",
     "min": "20",
     "model": "DHT11",
     "data_type": "temperature"
     "type_specific": "{"pin":4}"
 }
 
  • Código de resposta de sucesso:`201 CREATED` Sem corpo de resposta.
  • Código de resposta de sucesso 'criado mas não foi possível ativar':`202 ACEEPTED`.Sem corpo de resposta.
  • Código de resposta de erro geral:`400 BAD REQUEST` Sem corpo de resposta.

PUT

Executa a atualização dos limiares e grandeza de monitoramento de um sensor. O corpo da requisição contém todos os atributos do sensor que serão alterados em formato `application/json`. Obs: O sensor por padrão lê todos os dados que possui capacidade, porém apenas será gerado notificação para a grandeza especificada em 'data_type'.

  • Requisitos:

Os seguintes atributos são obrigatórios no corpo da requisição:`id`, `max`, `min` e `data_type`.

  • Corpo da requisição:
 {
     "id": 1,
     "max": 24,
     "min": 20,
     "data_type": "temperature"
 }
 
  • Código de resposta de sucesso:`200 OK` Sem corpo de resposta.
  • Código de resposta de erro geral:`400 BAD REQUEST` Sem corpo de resposta.

DELETE

O corpo da requisição contém o id do sensor a ser removido em formato `application/json`.

  • Requisitos:

Os seguintes atributos são obrigatórios no corpo da requisição:`id`

  • Corpo da requisição:
 {
     "id": sensor1
 }
  • Código de resposta de sucesso:`200 OK`. Sem corpo de resposta.
  • Código de resposta de erro geral:'400 BAD REQUEST`. Sem corpo de resposta.

Tabela HTTP Request

TabelaCurl.png


Exemplos com o 'curl'

Exemplos com a aplicação 'curl' disponível para sistemas Linux:

 curl --header "Content-Type: application/json" --request POST --data '{"id":"sensor1","max":10,"min":5,"model":"DHT11","data_type":"temperature","type_specific":{"pin":4}}' localhost:5000/sensor
 curl --header "Content-Type: application/json" --request PUT --data '{"id":"sensor1","max":8,"min":5,"data_type":"temperature"}' localhost:5000/sensor
 curl --header "Content-Type: application/json" --request GET --data '{"id":"sensor1"}' localhost:5000/sensor
 curl --header "Content-Type: application/json" --request DELETE --data '{"id":"sensor2"}' localhost:5000/sensor

Comandos AMQP

Sintaxe:

  • Ler um sensor:
 amqp-request.py -i <IP> -r <sensorID>
  • Alterar limiares e grandeza de monitoramento de um sensor
 amqp-request.py -i <IP> -c <sensorID> -M <max> -m <min> -d <datatype> 
  • Receber notificações da estação meteorológica
 amqp-listen.py


Parâmetros:

  • <IP>: Endereço do Broker.
  • <sensorID>: Identificador do sensor
  • <max>: Limiar superior.
  • <min>: Limiar inferior.
  • <datatype>: Grandeza à ser monitorada.

Testes do sistema

Retorno dos comandos AMQP

Para executar os comandos a seguir, é preciso estar conectado na Internet e saber o IP do Broker.

amqp-request.py -i rabbitmq.sj.ifsc.edu.br -r sensor1

Leitura Local

Retorno do "journalctl -u consumerAMQP.service -f"

Leitura Local


amqp-listen.py

Leitura Local

Retorno dos comandos API REST

Para executar os comandos a seguir, é preciso estar na mesma rede que a estação meteorológica e a mesma deve estar operante.

curl --header "Content-Type: application/json" --request POST --data '{"id":"sensor1","max":10,"min":5,"model":"DHT11","data_type":"temperature","type_specific":{"pin":4}}' localhost:5000/sensor

Leitura Local

Retorno do "journalctl -u webApp.service -f"

Leitura Local


curl --header "Content-Type: application/json" --request GET --data '{"id":"sensor1"}' localhost:5000/sensor

Leitura Local

Retorno do "journalctl -u webApp.service -f"

Leitura Local


curl --header "Content-Type: application/json" --request PUT --data '{"id":"sensor1","max":24,"min":20,"data_type":"temperature"}' localhost:5000/sensor


Leitura Local

Retorno do "journalctl -u webApp.service -f"

Leitura Local


curl --header "Content-Type: application/json" --request DELETE --data '{"id":"sensor1"}' localhost:5000/sensor


Leitura Local

Retorno do "journalctl -u webApp.service -f"

Leitura Local

Considerações finais

Conceitos e ferramentas utilizadas

Para desenvolver o sistema final, integrando todos os serviços, foi utilizado no desenvolvimento os seguintes conceitos:

  • Programação multiprocesso: Como é oferecido mais de uma funcionalidade no sistema é necessário definir uma forma de como tudo vai operar em conjunto. Dentre as opções de multiprocessos, multithreading e rotinas assíncronas, foi escolhido o multiprocesso devido a sua maior facilidade de manutenção, operação, e por existir uma evidente distinção entre os serviços oferecidos (leitura de sensor, comunicação WEB e comunicação AMQP.
  • Orientação a objeto: Para maior qualidade de código (abstração, manutenção e estruturação) foi utilizado o paradigma de orientação a objeto (POO).
  • Serviços WEB: Para prover um serviço localmente por meio de interfaces e protocolos padronizados.
  • Comunicação persistente por mensagens: Para prover suporte a comunicação assíncrona e persistente que é necessária num sistema distribuído na internet.


Flask é um micro-framework destinado principalmente a pequenas aplicações com requisitos mais simples, como por exemplo, a criação de um site básico. Possui um núcleo simples e expansível que permite que um projeto possua apenas os recursos necessários para sua execução.

SQLAlquemy é um ORM completo, criado com Python para desenvolvedores de aplicativos, que fornece flexibilidade total do SQL, obtendo um conjunto completo de padrões de persistência de nível corporativo bem conhecidos, que são projetados para acesso a banco de dados eficientes e de alto desempenho.

RabbitMQ é um servidor de mensagens de código aberto desenvolvido em Erlang, implementado para suportar mensagens em um protocolo denominado Advanced Message Queuing Protocol (AMQP). Ele possibilita lidar com o tráfego de mensagens de forma rápida e confiável, além de ser compatível com diversas linguagens de programação, possuir interface de administração nativa e ser multiplataforma. Dentre as aplicabilidades do RabbitMQ estão possibilitar a garantia de assincronicidade entre aplicações, diminuir o acoplamento entre aplicações, distribuir alertas, controlar fila de trabalhos em background.

pika: Pika é uma implementação Python puro do protocolo AMQP 0-9-1 que tenta permanecer bastante independente da biblioteca de suporte de rede subjacente.

Adicionar compatibilidade com sensores

Criar a classe específica do sensor

Esta classe deve conter a lógica de interação com o sensor, devendo implementar os métodos 'read' e 'activate' declarados pela classe abstrata 'Sensor'. Ex: station/driver/dht11.py

Codificar como o driver deve construir o sensor

Esta classe é o 'SensorDriver' em /station/driver/driver.py e deve apenas ser incrementada. Note que esta classe recebe um json via socket com as informações do sensor a ser lido ou ativado e então instancia um objeto da classe específica do tipo do sensor para por fim ler ou ativar o sensor.


Link video tutorial: https://drive.google.com/file/d/1POOpJiaZGvek9D_0dWIh4MRuvZZ4PNW-/view?usp=sharing

Link de como ler BMP280: https://learn.adafruit.com/adafruit-bmp280-barometric-pressure-plus-temperature-sensor-breakout/circuitpython-test