# emm-webapp Aplicação web dedicada ao armazenamento de dados meteorológicos do projeto [Estações Meteorológicas Modulares](http://cta.if.ufrgs.br/projects/estacao-meteorologica-modular/wiki/Wiki) (EMM). Atualmente publicada em: * [dados.cta.if.ufrgs.br/emm](http://dados.cta.if.ufrgs.br/emm/) ## 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](https://git.cta.if.ufrgs.br/meteorolog/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 ``. * 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** ```text $ 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`). ```text >>> 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 # 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 ``` 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= ``` OBS: dê um espaço em branco depois do `$` antes de digitar o comando `export` 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: * http://localhost/emm 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](http://www.sqlalchemy.org/) 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 [, ] >>> b = boards.get(2) # pega um registro via ID >>> b.nickname = 'UFRGS' # altera um campo >>> commit() # confirma a operação no DB >>> boards.ls [, ] ```