README.md
emm-webapp
Aplicação web dedicada ao armazenamento de dados meteorológicos do projeto Estações Meteorológicas Modulares (EMM).
Atualmente publicada em:
API
A webapp oferece uma RESTful API para envio e acesso aos dados armazenados. Funciona assim: envia-se uma requisição HTTP contendo um objeto JSON (header content-type: application/json
) para a URL; a webapp responde com outro objeto JSON.
Note: Objetos JSON são análogos (em geral) aos dicionários de Python.
- No advento de erros, o seguinte JSON será retornado:
{"Error": message}
/get/boardhash (POST)
Permite ao usuário obter a hash de autenticação da sua própria estação. Esta hash (string de 128 caracteres) deve ser utilizada para autenticar o envio de dados pela API.
ENTRADA:
{ "board_id": int, "user_password": str }
SAÍDA:
{ "board_hash": str }
/post/rawsensordata (POST)
Permite ao usuário enviar dados para sua estação.
Naturalmente, a tarefa pode ser automatizada por um data logger, tal como emm-logger.
ENTRADA:
{ "board_hash": str, # hash de autenticação de usuário "data": # dados a serem guardados [ { "datetime": # chave primária da tabela { "value": str, # ex: 2016-08-10-17-20-00 "format": str, # ex: %Y-%m-%d-%H-%M-%S "source": str # ex: "RTC", "WEB", "SYS" }, "sensors": # N sensores lidos { "name1": number, "name2": number, ..., "nameN": number } } ] }
SAÍDA:
{ "success": "{N} new points were saved on the board." }
/get/csv/rawsensordata/
Permite a qualquer pessoa obter os dados da estação identificada por <int:board_id>
.
- Retorna um arquivo
.csv
contendo TODOS os dados da estação, no formato:DATETIME,sensor1,sensor2,...,sensorN
Esta é uma requisição GET simples (não requer JSON) e pode ser feita em um web browser quaquer.
Utilizando a API RESTful
Há duas opções básicas para interagir com a API:
Curl
$ curl -i -H 'content-type: application/json' -X POST -d '{"board_id": 3,"user_password": "1234"}' http://dados.cta.if.ufrgs.br/emm/api/get/boardhash HTTP/1.1 200 OK Server: nginx/1.6.2 Date: Thu, 25 Jun 2011 21:45:12 GMT Content-Type: application/json Content-Length: 88 Connection: keep-alive Set-Cookie: session=eyJfaWQiOiJhMjUwZjVhMDViMjdkMGNkOTUzN2Q4YTViYWQzODFiMiJ9.CqDqWA.5TmPTa9zus8ZVo0avVnwz-O4-Dc; Domain=.dados.cta.if.ufrgs.br; HttpOnly; Path=/ { "board_hash": "pbkdf2:sha1:1000$rT98ercf$bf77e6ca081826cbf9fc0fab23cb93bf17fe598b" }
Python + excelente biblioteca requests (instale via
pip3
).>>> import requests >>> url = 'http://dados.cta.if.ufrgs.br/emm/api/get/boardhash' >>> d = {'board_id': 3, 'user_password': '1234'} >>> r = requests.post(url, json=d) >>>> r <Response [200]> # 200 significa "sucesso" >>> r.json() {'board_hash': 'pbkdf2:sha1:1000$rT98ercf$bf77e6ca081826cbf9fc0fab23cb93bf17fe598b'}
Instalação e manutenção
Seguem abaixo instruções para instalação e manutenção da webapp em seu próprio servidor.
O projeto inclui um arquivo Makefile
contendo diversos comandos simples para manutenção no diretório raiz. É preciso estar neste diretório para executar:
~/emm-webapp $ make <command>
Execute simplesmente make
ou make help
para obter uma lista de todos os comandos disponíveis e uma breve descrição.
1. Preparando ambiente de execução
1.1 Obtenha uma cópia do repositório atual:
$ git clone https://git.cta.if.ufrgs.br/meteorolog/emm-webapp.git $ cd emm-webapp
1.2 Instale os programas necessários (requer permissão de root):
$ make deb-req
Os seguintes programas serão instalados no sistema via apt-get (logo, apenas para distribuições Debian):
- nginx: Servidor web, utilizado para reverse proxy;
- supervisor: Gerenciador de processos em background;
- python3: Interpretador da linguagem na qual a web app foi escrita;
- python3-pip: Gerenciador de pacotes do Python;
- virtualenv: Permite a criação de um ambiente virtual contendo uma instalação isolada de Python e das dependencias do projeto (ver arquivo
requirements.pip
);
1.3 Crie o ambiente virtual de Python onde a web app será executada:
$ make venv
1.4 Exporte uma frase-chave para ser usada como token de segurança da web app:
$ export EMMPASS=<DigiteUmaFraseSemEspaços>
OBS: dê um espaço em branco depois do
$
antes de digitar o comandoexport
para que o texto não seja gravado no histórico do terminal!
2. Preparando o banco de dados
É possível trabalhar em modo desenvolvimento ou produção configurando a variável ambiente EMMCONFIG
.
2.1 Desenvolvimento: SQLite, arquivo local
$ export EMMCONFIG=dev
$ make initdb
2.2 Produção: servidor MySQL
O Makefile
proporciona vários comandos para execução de scripts MySQL (ver make help
e production/manage_mysql.py
para maiores detalhes).
Necessário apenas uma vez, o comando seguinte cria o usuário ctaemm
e o banco emmdb
no servidor:
$ make mysql-setup
OBS: Nesse o ponto o banco ainda está vazio (sem tabelas).
$ export EMMCONFIG=prod
$ make initdb
OBS: As tabelas serão recriadas e dados existentes serão perdidos!
3. Executando a web app
É possível executar a aplicação em modo desenvolvimento ou produção. Em ambos os casos, é um servidor WSGI rodando em uma porta específica que intermedia as requisições web (GET, POST, etc) com a aplicação Python.
A porta pode (e deve) ser configurada na variável ambiente EMMPORT
. Padrão: 5000.
3.1 Desenvolvimento
- Execução em primeiro plano;
- Servidor WSGI: Werkzeug (padrão integrado ao Flask);
- Flag
DEBUG=True
(brecha de segurança!); - Banco de dados local SQLite;
Execute fazendo:
$ make run
Publicado por padrão em: http://localhost:5000
.
Pressione CTRL+C para interromper a execução.
3.2 Produção
- Execução em plano de fundo;
- Servidor WSGI: Gunicorn (instalado via pip em
make venv
); - Flag
DEBUG=False
; - Servidor de banco de dados MySQL;
Requer variável ambiente EMMSERVER
contendo o nome do servidor de rede da máquina.
A publicação é feita com:
$ make deploy
Assumindo EMMSERVER=localhost
, o site estará publicado localmente em:
Em resumo, o comando acima faz:
- Cria um servidor WSGI Gunicorn na porta
EMMPORT
; - Registra o processo Gunicorn na ferramenta Supervisor para iniciação automática junto ao sistema operacional;
- Registra o site no servidor web Nginx na forma de um reverse proxy da porta 80 para a aplicação WSGI na porta
EMMPORT
.
A publicação pode ser desfeita com:
$ make undeploy
4. Manutenção
Independente do banco de dados utilizado, ele pode ser manipulado em alto nível graças ao mapeador objeto-relacional SQLAlchemy utilizado pela aplicação.
O comando:
$ make shell
inica uma sessão IPython onde as tabelas e registros podem ser acessados e alterados como objetos Python. A exemplo:
>>> tables # para ver as tabelas disponíveis
>>> boards # a exemplo, esta é a tabela boards
app.models.board.Board
>>> boards.__fields__ # lista os campos da tabela
{'description', 'id', 'latitude', 'longitude', 'nickname', 'user_id'}
>>> boards.ls # lista todas linhas/registros da tabela
[<Board id=1 user='admin' nickname='Pezzi' sensor_count=4>,
<Board id=2 user='admin' nickname='CAP' sensor_count=4>]
>>> b = boards.get(2) # pega um registro via ID
>>> b.nickname = 'UFRGS' # altera um campo
>>> commit() # confirma a operação no DB
>>> boards.ls
[<Board id=1 user='admin' nickname='Pezzi' sensor_count=4>,
<Board id=2 user='admin' nickname='UFRGS' sensor_count=4>]