Mudanças entre as edições de "PJI29006-2015-1-Wiki do Projeto"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
 
(37 revisões intermediárias por 6 usuários não estão sendo mostradas)
Linha 1: Linha 1:
 +
__NOTOC__
 
=Sistema de Automatização de Sala de Aula=
 
=Sistema de Automatização de Sala de Aula=
  
Linha 4: Linha 5:
  
 
* [https://dotproject.sj.ifsc.edu.br/?m=projects&a=view&project_id=14 Sistema de Gerenciamento de Projetos (dotProject)]
 
* [https://dotproject.sj.ifsc.edu.br/?m=projects&a=view&project_id=14 Sistema de Gerenciamento de Projetos (dotProject)]
* [http://pending... Repositório de Documentos (GIT)]
+
* [https://github.com/guialbu/Sistema-Webba Repositório do Código Fonte (GIT)]
 
 
 
  
 
==Descrição==
 
==Descrição==
Linha 113: Linha 112:
 
{{collapse bottom}}
 
{{collapse bottom}}
  
 +
===Casos de Uso===
  
===Casos de Uso===
+
{{collapse top| Descrição dos Casos de Uso}}
  
 
<center>[[Arquivo:caso_de_uso.png| 650px]]</center>
 
<center>[[Arquivo:caso_de_uso.png| 650px]]</center>
 
{{collapse top| Descrição dos Casos de Uso}}
 
  
 
====CSU01====
 
====CSU01====
Linha 239: Linha 237:
  
 
'''Pós-condições:''' Projetor ligado e funcionando de acordo como o usuário solicitou
 
'''Pós-condições:''' Projetor ligado e funcionando de acordo como o usuário solicitou
 
  
 
<center>[[Arquivo:ana4.png| 650px]]</center>
 
<center>[[Arquivo:ana4.png| 650px]]</center>
 
  
 
====CSU05====
 
====CSU05====
Linha 315: Linha 311:
  
 
====CSU07====
 
====CSU07====
 
  
 
'''Desligando a iluminação'''  
 
'''Desligando a iluminação'''  
Linha 372: Linha 367:
  
 
b. O usuário ajusta a posição da cortina conforme sua escolha de forma manual  
 
b. O usuário ajusta a posição da cortina conforme sua escolha de forma manual  
 
 
  
 
<center>[[Arquivo:pj17.png| 650px]]</center>
 
<center>[[Arquivo:pj17.png| 650px]]</center>
Linha 428: Linha 421:
  
 
3. O sistema salva as informações e as funcionalidades dos aparelhos são armazenadas no banco de dados.
 
3. O sistema salva as informações e as funcionalidades dos aparelhos são armazenadas no banco de dados.
 
 
  
 
'''Pós-condições''': Aparelhos de climatização  cadastrados e prontos para serem usados.
 
'''Pós-condições''': Aparelhos de climatização  cadastrados e prontos para serem usados.
Linha 454: Linha 445:
  
 
4. O usuário volta para [http://wiki.sj.ifsc.edu.br/index.php/PJI29006-2015-1-Wiki_do_Projeto#CSU09 CSU09].
 
4. O usuário volta para [http://wiki.sj.ifsc.edu.br/index.php/PJI29006-2015-1-Wiki_do_Projeto#CSU09 CSU09].
 
  
 
'''Fluxo Alternativo''' (1): Alteração no modo de controle do sistema.
 
'''Fluxo Alternativo''' (1): Alteração no modo de controle do sistema.
Linha 492: Linha 482:
  
 
6. O usuário volta para [http://wiki.sj.ifsc.edu.br/index.php/PJI29006-2015-1-Wiki_do_Projeto#CSU09 CSU09].
 
6. O usuário volta para [http://wiki.sj.ifsc.edu.br/index.php/PJI29006-2015-1-Wiki_do_Projeto#CSU09 CSU09].
 
  
 
'''Fluxo Alternativo''' (1): Alteração no modo de controle do sistema.
 
'''Fluxo Alternativo''' (1): Alteração no modo de controle do sistema.
Linha 537: Linha 526:
  
 
'''Pós-condições''':  Ventiladores ligados e funcionando conforme o usuário solicitou.
 
'''Pós-condições''':  Ventiladores ligados e funcionando conforme o usuário solicitou.
 
 
  
 
<center>[[Arquivo:UseCase_Diagram_System2.png| 650px]]</center>
 
<center>[[Arquivo:UseCase_Diagram_System2.png| 650px]]</center>
Linha 648: Linha 635:
  
 
{{collapse bottom}}
 
{{collapse bottom}}
 
  
 
===Modelo de Domínio===
 
===Modelo de Domínio===
Linha 662: Linha 648:
 
A execução do projeto, dentro da disciplina de Projeto Integrador II de 2015.1, consistirá de 2 ciclos de desenvolvimentos. Ao final de cada ciclo, os conjuntos de requisitos funcionais abaixo devem ser satisfeitos:
 
A execução do projeto, dentro da disciplina de Projeto Integrador II de 2015.1, consistirá de 2 ciclos de desenvolvimentos. Ao final de cada ciclo, os conjuntos de requisitos funcionais abaixo devem ser satisfeitos:
  
==== Ciclo 1 ====
+
{{collapse top | Ciclo 1}}
 
 
 
* RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
 
* RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
 
** RF01.1. O dispositivo móvel deve controlar o projetor (liga/desliga);
 
** RF01.1. O dispositivo móvel deve controlar o projetor (liga/desliga);
Linha 676: Linha 661:
 
** RF05.4. Autenticar usuário
 
** RF05.4. Autenticar usuário
 
*** A partir de arquivo de usuário e senha
 
*** A partir de arquivo de usuário e senha
 
+
{{collapse bottom | Ciclo 1}}
==== Ciclo 2 ====
+
{{collapse top | Ciclo 2}}
 
 
 
* RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
 
* RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
 
** RF01.2. Carregar arquivo independente da extensão
 
** RF01.2. Carregar arquivo independente da extensão
Linha 692: Linha 676:
 
*** completo
 
*** completo
 
** RF05.9. Manipular arquivos
 
** RF05.9. Manipular arquivos
 
+
{{collapse bottom | Ciclo 2}}
==== Ciclos posteriores ====
+
{{collapse top | Ciclos Posteriores / Implementações adicionais }}
 
 
 
* RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
 
* RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
 
** RF01.5. Selecionar slide específico
 
** RF01.5. Selecionar slide específico
Linha 720: Linha 703:
 
** RF05.7. Gerenciar cotas para arquivos
 
** RF05.7. Gerenciar cotas para arquivos
 
** RF05.8. Compartilhar arquivos com outros usuários
 
** RF05.8. Compartilhar arquivos com outros usuários
 +
{{collapse bottom | Ciclos Posteriores / Implementações adicionais }}
  
 
+
=== Estudo das Tecnologias ===
===Sincronização de Diretórios Utilizando Rsync===
+
====Sincronização de Diretórios Utilizando Rsync====
  
 
{{collapse top| Sincronização de Diretórios Utilizando Rsync [1] - Solução Obsoleta }}
 
{{collapse top| Sincronização de Diretórios Utilizando Rsync [1] - Solução Obsoleta }}
Linha 1 347: Linha 1 331:
 
# and files in /etc/cron.d. These files also have username fields,
 
# and files in /etc/cron.d. These files also have username fields,
 
# that none of the other crontabs do.
 
# that none of the other crontabs do.
+
 
 
SHELL=/bin/sh
 
SHELL=/bin/sh
 
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+
 
 
# m h dom mon dow user command
 
# m h dom mon dow user command
 
17 * * * * root    cd / && run-parts --report /etc/cron.hourly
 
17 * * * * root    cd / && run-parts --report /etc/cron.hourly
Linha 1 356: Linha 1 340:
 
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
 
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
 
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
 
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
00 23  * * 1-5  root   sh  /srv/webba/cfd/script/remove_symlink.sh
+
00 23  * * 1-5  webba    sh  /opt/webba/srv/cfg/script/removels.sh
 +
25 5   * * 1-5  webba    sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
 +
5 7    * * 1-5  webba    sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
 +
20 9    * * 1-5  webba    sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
 +
5 13    * * 1-5  webba    sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
 +
20 15  * * 1-5  webba    sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
 +
5 18    * * 1-5  webba    sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
 +
20 20  * * 1-5  webba    sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
 
#
 
#
 
 
 
</syntaxhighlight>
 
</syntaxhighlight>
 
{{collapse bottom}}
 
{{collapse bottom}}
Linha 1 389: Linha 1 378:
 
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
 
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
 
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
 
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
00 23   * * 1-5 root    sh  /s001/cfg/script/remove_hardlink.sh
+
00 23 * * 1-5 root    sh  /s001/cfg/script/remove_hardlink.sh
30 5  1-5 * * root    sh  /s001/cfg/script/cliente_rsync.sh
+
30 5  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
10 7  1-5 * * root    sh  /s001/cfg/script/cliente_rsync.sh
+
10 7  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
25 9  1-5 * * root    sh  /s001/cfg/script/cliente_rsync.sh
+
25 9  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
10 13  1-5 * * root    sh  /s001/cfg/script/cliente_rsync.sh
+
10 13  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
25 15  1-5 * * root    sh  /s001/cfg/script/cliente_rsync.sh
+
25 15  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
10 18  1-5 * * root    sh  /s001/cfg/script/cliente_rsync.sh
+
10 18  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
25 20  1-5 * *  root    sh  /s001/cfg/script/cliente_rsync.sh   
+
25 20  * * 1-5   root    sh  /s001/cfg/script/cliente_rsync.sh   
 
*/1 * * * * root /      sh  /s001/cfg/script/ntp.sh             
 
*/1 * * * * root /      sh  /s001/cfg/script/ntp.sh             
 
#
 
#
Linha 1 446: Linha 1 435:
 
{{collapse bottom}}
 
{{collapse bottom}}
  
===Exibição de PDF com xpdf em Virtual Display===
+
====Exibição de PDF com xpdf em Virtual Display====
  
 
{{collapse top | Exibição de PDF com xpdf em Virtual Display [1] - Solução obsoleta, substituída por [2]}}
 
{{collapse top | Exibição de PDF com xpdf em Virtual Display [1] - Solução obsoleta, substituída por [2]}}
Linha 1 780: Linha 1 769:
 
{{collapse bottom | Exibição de PDF com xpdf em Virtual Display [2] - Solução obsoleta, substituída por [3]l}}
 
{{collapse bottom | Exibição de PDF com xpdf em Virtual Display [2] - Solução obsoleta, substituída por [3]l}}
  
{{collapse top | Exibição de PDF com xpdf em Virtual Display [3] - Solução atual}}
+
{{collapse top | Exibição de PDF com xpdf em Virtual Display [3] - Solução obsoleta, substituida pelo Web Service}}
  
 
Como parte do ''Detalhamento da Especificação'' referente ao Ciclo 1 de desenvolvimento foi estudada a projeção de processos que utilizem interface gráfica em um virtual display, com ênfase na exibição de arquivos PDF através do visualizador [http://www.foolabs.com/xpdf/ xpdf] e envio de comandos através de um terminal para uma sessão remota da aplicação.
 
Como parte do ''Detalhamento da Especificação'' referente ao Ciclo 1 de desenvolvimento foi estudada a projeção de processos que utilizem interface gráfica em um virtual display, com ênfase na exibição de arquivos PDF através do visualizador [http://www.foolabs.com/xpdf/ xpdf] e envio de comandos através de um terminal para uma sessão remota da aplicação.
Linha 2 052: Linha 2 041:
 
{{collapse bottom | Scrits dos Comandos}}
 
{{collapse bottom | Scrits dos Comandos}}
  
{{collapse bottom | Exibição de PDF com xpdf em Virtual Display [3] - Solução atual}}
+
{{collapse bottom | Exibição de PDF com xpdf em Virtual Display [3] - Solução obsoleta, substituida pelo Web Service}}
  
===Estudo da Raspberry Pi B+===
+
====Estudo da Raspberry Pi B+====
  
 
{{collapse top | Auto Login}}
 
{{collapse top | Auto Login}}
Linha 2 218: Linha 2 207:
 
{{collapse bottom | Utilizar internet na raspberry através de rede via Ubuntu}}
 
{{collapse bottom | Utilizar internet na raspberry através de rede via Ubuntu}}
  
===API Web-Service a ser implementado na Raspberry Pi B+===
+
===API's de implementação===
 +
====API Web-Service a ser implementado na Raspberry Pi B+====
  
 
{{collapse top | API Web-Service a ser implementado na Raspberry Pi B+}}
 
{{collapse top | API Web-Service a ser implementado na Raspberry Pi B+}}
Linha 2 226: Linha 2 216:
 
!scope="col"| URI
 
!scope="col"| URI
 
!scope="col"| Parâmetros
 
!scope="col"| Parâmetros
!scope="col"| Retorno (Json)
+
!scope="col"| Retorno em Sucesso
 +
!scope="col"| Retorno em Fracasso
 
!scope="col"| Descrição
 
!scope="col"| Descrição
  
 
|-
 
|-
|@GET || /projetar || <center>-</center> || [{"NomeDoArquivo":arquivo1.pdf,"TamanhoArquivo1":12345,"NumeroDePaginas":12},{"nomeDoArquivo":arquivo2.opt,"TamanhoDoArquivo":54321,"NumeroDePaginas":26}] || Retorna os arquivos aos quais o usuário tem acesso e informações sobre os mesmos
+
|@GET || /projetar || <center>-</center> || <center> [{"nome":"arquivo1.pdf","numeroPaginas":2},{"nome":"arquivo2.opt","numeroPaginas":33}] </center> || <center> [{'resultado': False}] </center> || Retorna os arquivos aos quais o usuário tem acesso e informações sobre os mesmos
 
|-
 
|-
|@GET || /projetar/{''arquivo''} || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <syntaxhighlight lang=java> int ret </syntaxhighlight> || Inicia a projeção do ''arquivo'' solicitado pelo usuário
+
|@GET || /projetar/{''arquivo''} || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center> || Inicia a projeção do ''arquivo'' solicitado pelo usuário
 
|-
 
|-
|@GET || /projetar/{''arquivo''}/avancarProjecao || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <syntaxhighlight lang=java> int ret </syntaxhighlight> || Faz a projeção da apresentação avançar um slide de ''arquivo''
+
|@GET || /projetar/{''arquivo''}/avancarProjecao || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center> || Faz a projeção da apresentação avançar um slide de ''arquivo''
 
|-
 
|-
|@GET || /projetar/{''arquivo''}/retrocederProjecao || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <syntaxhighlight lang=java> int ret </syntaxhighlight> || Faz a projeção da apresentação retroceder um slide de ''arquivo''
+
|@GET || /projetar/{''arquivo''}/retrocederProjecao || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center> || Faz a projeção da apresentação retroceder um slide de ''arquivo''
 
|-
 
|-
 
|@GET || /projetar/{''arquivo''}/saltarProjecao/{''numeroPagina''}|| <syntaxhighlight lang=java> String nomeDoArquivo
 
|@GET || /projetar/{''arquivo''}/saltarProjecao/{''numeroPagina''}|| <syntaxhighlight lang=java> String nomeDoArquivo
int numeroPagina </syntaxhighlight> || <syntaxhighlight lang=java> int ret </syntaxhighlight> || Vai a uma determinada página de ''arquivo''
+
int numeroPagina </syntaxhighlight> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center> || Vai a uma determinada página de ''arquivo''
 
|-
 
|-
|@GET || /projetar/{''arquivo''}/fechar || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <syntaxhighlight lang=java> int ret </syntaxhighlight> || Fecha a apresentação de ''arquivo''
+
|@GET || /projetar/{''arquivo''}/fechar || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center> || Fecha a apresentação de ''arquivo''
 
|-
 
|-
 
|@GET || /projetar/{''arquivo''}/obterThumb/{''thumb''} || <syntaxhighlight lang=java>String nomeDoArquivo
 
|@GET || /projetar/{''arquivo''}/obterThumb/{''thumb''} || <syntaxhighlight lang=java>String nomeDoArquivo
int thumb </syntaxhighlight>|| [{"NomeDoArquivo":arquivo.pdf,"thumb":thumb1.jpg} || Retorna um determinado thumb (identificado por ''thumb'') referente ao ''arquivo''
+
int thumb </syntaxhighlight>|| <center> [{"thumb":arquivo-1.jpg}] </center> || <center> [{'resultado': False}] </center> || Retorna um determinado thumb (identificado por ''thumb'') referente ao ''arquivo''
 
|-
 
|-
|@GET || /sincronizacao/forcaSincronizacao || <center>-</center> || <syntaxhighlight lang=java> int ret </syntaxhighlight> || Força uma sincronização com o servidor de arquivos
+
|@GET || /sincronizacao/forcaSincronizacao || <center>-</center> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center>|| Força uma sincronização com o servidor de arquivos
 +
|-
 +
|@GET || <font color=darkred>/projetar/ligarProjetor</font> || <center> - </center> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center> || Liga o projetor
 +
|-
 +
|@GET || <font color=darkred>/projetar/desligarProjetor</font> || <center> - </center> || <center> [{'resultado': True}] </center> || <center> [{'resultado': False}] </center> || Desliga o projetor
 
|}
 
|}
  
{{collapse bottom}}
+
{{collapse bottom | API Web-Service a ser implementado na Raspberry Pi B+}}
  
{{collapse top | Descrição das URI do GUI}}
+
====API Web-Service a ser implementado no GUI====
  
===API Web-Service a ser implementado no GUI===
+
{{collapse top | API Web-Service a ser implementado no GUI}}
  
 
{| class="wikitable"
 
{| class="wikitable"
Linha 2 265: Linha 2 260:
 
|@POST || /auth || <syntaxhighlight lang=java> String usuario </syntaxhighlight> <syntaxhighlight lang=java> String senha </syntaxhighlight> || <syntaxhighlight lang=java> boolean resposta </syntaxhighlight>|| Caso seja possível criar o usúario, o servidor retorna a confirmação. Caso não mande os dados corretamente, retorna que não foi possível criar um usuário.
 
|@POST || /auth || <syntaxhighlight lang=java> String usuario </syntaxhighlight> <syntaxhighlight lang=java> String senha </syntaxhighlight> || <syntaxhighlight lang=java> boolean resposta </syntaxhighlight>|| Caso seja possível criar o usúario, o servidor retorna a confirmação. Caso não mande os dados corretamente, retorna que não foi possível criar um usuário.
 
|-
 
|-
|@DELETE || /deletar/{user}|| <syntaxhighlight lang=java> String usuario </syntaxhighlight> <syntaxhighlight lang=java> String senha </syntaxhighlight> || <syntaxhighlight lang=java> int resposta </syntaxhighlight> || Se for o próprio usuário que deseja se remover, então o servidor retorna uma confirmação, informando que foi removido com sucesso. Caso contrário servidor, avisa que não foi possível.
+
|@POST || /auth || <syntaxhighlight lang=java> String usuario </syntaxhighlight> <syntaxhighlight lang=java> String senha </syntaxhighlight> || <syntaxhighlight lang=java> boolean resposta </syntaxhighlight>|| Retorna acesso permitido, caso os dados que o usuário tenha enviado, estiverem corretos, caso contrário acesso é negado.
 
|-
 
|-
|@DELETE || /arquivos/{nomeDoArqivo} || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Se  o arquivo existir, então o servidor retorna uma confirmação,informando que foi removido arquivo foi removido com sucesso. Caso contrário servidor, avisa que não foi possível.
+
|@PUT || /change_passwd || <syntaxhighlight lang=java> String usuário </syntaxhighlight> <syntaxhighlight lang=java> String senha_atual </syntaxhighlight> <syntaxhighlight lang=java> String senha_nova </syntaxhighlight>  || <syntaxhighlight lang=java> boolean resposta </syntaxhighlight> || Retorna se foi possível alterar a senha do usuário, caso contrário a senha antiga permanece.
|-
 
|@POST || /agendamento/{sala} || <syntaxhighlight lang=java> String sala </syntaxhighlight> <syntaxhighlight lang=java> String arquivo </syntaxhighlight> <syntaxhighlight lang=javaTimestamp </syntaxhighlight> || <syntaxhighlight lang=java> int resposta </syntaxhighlight> || Se o usuário informar corretamente: a sala, arquivo, data, então o servidor retorna uma confirmação, informando que foi feito com sucesso, caso contrário informa que não foi possível agendar a aula.
 
 
|-
 
|-
 
|@POST || /auth/{pasta} || <syntaxhighlight lang=java> String nomeDaPasta  </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Caso seja possível criar a subpasta, então o servidor retorna uma confirmação, informando que a pasta foi criada. Caso contrário o servidor, avisa que não foi possível.
 
|@POST || /auth/{pasta} || <syntaxhighlight lang=java> String nomeDaPasta  </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Caso seja possível criar a subpasta, então o servidor retorna uma confirmação, informando que a pasta foi criada. Caso contrário o servidor, avisa que não foi possível.
Linha 2 275: Linha 2 268:
 
|@DELETE || /auth/{pasta} || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Caso a pasta exista, então o servidor retorna uma confirmação, informando que a pasta foi excluida. Caso contrário o servidor, avisa que não foi possível.
 
|@DELETE || /auth/{pasta} || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Caso a pasta exista, então o servidor retorna uma confirmação, informando que a pasta foi excluida. Caso contrário o servidor, avisa que não foi possível.
 
|-
 
|-
|@POST || /upload/{nome} || <syntaxhighlight lang=java> String nomeDoArquivo  </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Caso seja possível fazer upload do arquivo, então o servidor retorna uma confirmação, informando que o arquivo foi colocado corretamente na pasta do usuário. Caso contrário o servidor, avisa que ocorreu um erro durante o upload do arquivo.
+
|@GET || /arquivos/{user} || <syntaxhighlight lang=java> String nomeDoUsuário </syntaxhighlight>  || <syntaxhighlight lang=java> Lista listaDeArquivos </syntaxhighlight>|| Caso  o usuário exista, então o servidor retorna uma lista com todos os arquivos do usuário. Caso contrário o servidor, avisa que não foi possível.
 +
|-
 +
|@POST || /arquivos/{nome} || <syntaxhighlight lang=java> String nomeDoArquivo  </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Caso seja possível fazer upload do arquivo, então o servidor retorna uma confirmação, informando que o arquivo foi colocado corretamente na pasta do usuário. Caso contrário o servidor, avisa que ocorreu um erro durante o upload do arquivo.
 +
|-
 +
|@DELETE || /arquivos/{nome} || <syntaxhighlight lang=java> String nomeDoArquivo </syntaxhighlight>  || <syntaxhighlight lang=java> int resposta </syntaxhighlight>|| Se  o arquivo existir, então o servidor retorna uma confirmação,informando que foi removido arquivo foi removido com sucesso. Caso contrário servidor, avisa que não foi possível.
 
|-
 
|-
|@GET || /arquivos/{user} || <syntaxhighlight lang=java> String nomeDoUsuário </syntaxhighlight> || <syntaxhighlight lang=java> Lista listaDeArquivos </syntaxhighlight>|| Caso  o usuário exista, então o servidor retorna uma lista com todos os arquivos do usuário. Caso contrário o servidor, avisa que não foi possível.
+
|@POST || /agendamento/{user}/{nome} || <syntaxhighlight lang=java> String sala </syntaxhighlight> <syntaxhighlight lang=java> String arquivo </syntaxhighlight> <syntaxhighlight lang=java> String dia </syntaxhighlight> <syntaxhighlight lang=java> String mes </syntaxhighlight> <syntaxhighlight lang=java> String ano </syntaxhighlight> <syntaxhighlight lang=java> String hora </syntaxhighlight> <syntaxhighlight lang=java> String minuto </syntaxhighlight> || <syntaxhighlight lang=java> int resposta </syntaxhighlight> || Se o usuário informar corretamente: a sala, arquivo, data, então o servidor retorna uma confirmação, informando que foi feito com sucesso, caso contrário informa que não foi possível agendar a aula.
 
|-
 
|-
|@GET || /salas/ ||   || <syntaxhighlight lang=java> Lista listaDeSala </syntaxhighlight>|| Então o servidor retorna uma lista com todos as salas.
+
|@DELETE || /deletar/{user}|| <syntaxhighlight lang=java> String usuario </syntaxhighlight> <syntaxhighlight lang=java> String senha </syntaxhighlight> || <syntaxhighlight lang=java> int resposta </syntaxhighlight> || Se for o próprio usuário que deseja se remover, então o servidor retorna uma confirmação, informando que foi removido com sucesso. Caso contrário servidor, avisa que não foi possível.
 
|-
 
|-
 
|}
 
|}
  
===API Web-Service a ser implementado no Celular===
+
{{collapse bottom | API Web-Service a ser implementado no GUI}}
 +
 
 +
=== Implementação do Web Service na Raspberry ===
 +
 
 +
{{collapse top | Instalação dos componentes necessários}}
 +
==== 1. [http://www.foolabs.com/xpdf/ Xpdf] ====
 +
Visualizador de [http://pt.wikipedia.org/wiki/Portable_document_format PDF's].
 +
<syntaxhighlight lang=bash> $ sudo apt-get install xpdf </syntaxhighlight>
 +
==== 2. [https://www.python.org/ Python]====
 +
Linguagem de programação utilizada na implementação do web service.
 +
<syntaxhighlight lang=bash> $ sudo apt-get install python </syntaxhighlight>
 +
==== 3. [https://pypi.python.org/pypi/pip Python-pip] ====
 +
Gerenciador de extensões python.
 +
<syntaxhighlight lang=bash> $ sudo apt-get install python-pip </syntaxhighlight>
 +
==== 4. [https://mail.python.org/mailman/listinfo/python-dev Python-dev] ====
 +
Pacote python para desenvolvedores.
 +
<syntaxhighlight lang=bash> $ sudo apt-get install python-dev </syntaxhighlight>
 +
==== 5. Framework [http://flask.pocoo.org/ Flask] ====
 +
Framework utilizado na implementação de web services.
 +
<syntaxhighlight lang=bash> $ sudo pip install flask </syntaxhighlight>
 +
==== 6. Extensão [https://flask-httpauth.readthedocs.org/en/latest/ HTTPAuth] do Flask ====
 +
Para autenticação via HTTP.
 +
<syntaxhighlight lang=bash> $ sudo pip install flask-httpauth </syntaxhighlight>
 +
==== 7. Extensão [https://pypi.python.org/pypi/netifaces netifaces] para Python ====
 +
Fornece informações sobre as interfaces de conexão.
 +
<syntaxhighlight lang=bash> $ wget https://pypi.python.org/packages/source/n/netifaces/netifaces-0.10.4.tar.gz
 +
$ tar xvzf netifaces-0.10.4.tar.gz
 +
$ cd netifaces-0.10.4
 +
$ python setup.py install </syntaxhighlight>
 +
==== 8. Extensão [https://pypi.python.org/pypi/Flask-Cors/1.10.3 Cors] do Flask ====
 +
Devido a '''[https://pt.wikipedia.org/wiki/Pol%C3%ADtica_de_mesma_origem política de mesma origem] (same origin policy)''', configurada como padrão nos servidores, qualquer requisição feita de diferentes domínios é bloqueada pelos navegadores, isto impede que ataques de [https://pt.wikipedia.org/wiki/Cross-site_scripting Cross-domain] sejam feitos. A habilitação da extensão '''[https://pt.wikipedia.org/wiki/Cross-origin_resource_sharing CORS] (cross-origin resource sharing)''' cria um caminho para que estas requisições sejam feitas de uma maneira mais segura, sem que todas as requisições deste tipo sejam habilitadas. Para habilitar os CORS é necessário primeiramente instalar a biblioteca para o suporte do CORS no servidor.
 +
 
 +
<code> $ pip install -U flask-cors </syntaxhighlight>
 +
 
 +
Depois é necessário apenas a importação da biblioteca e inserir o código para habilitar o CORS nos recursos do servidor.
 +
 
 +
<syntaxhighlight lang=python>
 +
from flask.ext.cors import CORS
 +
 
 +
app = Flask(__name__)
 +
cors = CORS(app)
 +
</syntaxhighlight>
 +
 
 +
====9. Instalação do cec-utils, que utiliza a biblioteca [https://github.com/Pulse-Eight/libcec libcec] ====
 +
Para envio de comandos para dispositivos conectados via [http://www.infowester.com/hdmi.php HDMI]
 +
 
 +
<syntaxhighlight lang=bash> sudo apt-get install cec-utils </syntaxhighlight>
 +
 
 +
{{collapse bottom | Instalação dos componentes necessários}}
 +
 
 +
{{collapse top | Implementação do Web Service}}
 +
 
 +
*Assume-se que o diretório dos usuários estará localizado no diretório do usuário '''root''' da raspberry (/root), e que no diretório de cada usuário haverá um diretório chamado ''thumbs'', que conterá todas as miniaturas necessárias para exibição no dispositivo móvel.
 +
 
 +
<syntaxhighlight lang=python>
 +
#!/usr/bin/python
 +
 +
__author__ = "Matuzalem - Projeto Integrador II - Engenharia de Telecomunicacoes - Junho de 2015"
 +
__date__ = "$11/06/2015 01:09:22$"
 +
 +
import sys
 +
import netifaces # para capturar a interface do servidor automaticamente, caso insira manualmente o ip do servidor e descartavel, desde que comente as linhas de codigo equivalentes
 +
from flask import Flask, jsonify
 +
from flask import abort
 +
from flask import make_response
 +
from flask import request
 +
from flask import url_for
 +
from flask import send_file # enviar arquivos thumbs pela rede
 +
from flask.ext.httpauth import HTTPBasicAuth
 +
from flask.ext.cors import CORS # habilita troca de informacoes cross domain
 +
auth = HTTPBasicAuth()
 +
 +
import subprocess
 +
import os
 +
 +
app = Flask(__name__)
 +
cors = CORS(app)
 +
 
 +
# Este servidor foi desenvolvido considerando a estrutura /root/User para o armazenamento de pdfs na raspberry
 +
#####################[DEVE SER PREENCHIDO]############################
 +
usuario = 'User' # usuario conectado a raspberry
 +
interface='lo' # interface em que o servidor funcionara, para obter o ip automaticamente
 +
porta=5000 # porta em que o servidor ouvira
 +
######################################################################
 +
caminho = "" # diretorio onde esta localizado o diretorio do usuario
 +
pastaUsuario = "" # diretorio usuario
 +
numeroPaginas="" # numero de paginas do arquivo
 +
paginaAtual="" # pagina atual do arquivo
  
{| class="wikitable"
+
### Como listar arquivos em diretorio e seus subdiretorios ###
!scope="col"| Método
+
# curl -i http://localhost:5000/projetar
!scope="col"| URI
+
# Lista os arquivos do tipo pdf em /root/{usuario}/ e o numero de paginas de cada arquivo
!scope="col"| Parâmetros
+
@app.route('/projetar', methods=['GET'])
!scope="col"| Retorno (Json)
+
def obtem_arquivos():
!scope="col"| Descrição
+
    lista = []
 +
    #https://docs.python.org/2/library/os.html
 +
    for root, dirs, files in os.walk(caminho+usuario+'/'):
 +
        for nome in files:
 +
            if nome.endswith(".pdf"):
 +
                path = os.path.join(root, nome)
 +
                size = os.stat(path).st_size # in bytes
 +
                linha = {}
 +
                linha['numeroPaginas'] = subprocess.check_output("/usr/bin/pdfinfo "+path+" | grep -oP '(?<=Pages:          )[ A-Za-z0-9]*'", shell=True)[:-1] # [:-1] remove o ultimo elemento do vetor, no caso \n     
 +
                linha['nome'] = nome
 +
                lista.append(linha)
 +
    return jsonify({'arquivos': lista}), 200
 +
 +
 +
############################ Auxiliares ##############################
 +
 +
# verifica se um arquivo existe em um determinado diretorio
 +
def verifica_existencia(diretorio, arquivo):
 +
    if (os.path.exists(diretorio+arquivo) == True):
 +
        return True
 +
    else:
 +
        return False
 +
 +
######################### Metodos do XPDF ############################
 +
# curl -i http://localhost:5000/projetar/{arquivo.pdf}
 +
# Abre um pdf
 +
@app.route('/projetar/<arquivo>', methods=['GET'])
 +
def abre_pdf(arquivo):
 +
    # Chamada de processo nao bloqueante - fica em background
 +
    local = pastaUsuario+arquivo
 +
    if (verifica_existencia(pastaUsuario,arquivo) == True):
 +
        p1 = os.spawnlp(os.P_NOWAIT,"xpdf","/usr/bin/xpdf","-fullscreen","-remote", arquivo, local)
 +
        # /usr/bin/pdfinfo /root/User/arquivo.pdf | grep -oP '(?<=Pages:          )[ A-Za-z0-9]*'
 +
        # verifica o numero de paginas do pdf
 +
        global numeroPaginas
 +
        global paginaAtual
 +
        numeroPaginas = subprocess.check_output("/usr/bin/pdfinfo "+local+" | grep -oP '(?<=Pages:          )[ A-Za-z0-9]*'", shell=True)
 +
        paginaAtual = 1
 +
        return jsonify({'resultado': True}), 200
 +
    else:
 +
        print 'Usuario '+usuario+' tentou acessar o arquivo '+arquivo+' inexistente!'
 +
        return jsonify({'resultado': False}), 404
 +
 +
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/avancarProjecao
 +
# Avanca uma pagina
 +
@app.route('/projetar/<arquivo>/avancarProjecao', methods=['GET'])
 +
def avanca_pagina(arquivo):
 +
    comando = 'nextPage'
 +
    global paginaAtual
 +
    if(int(paginaAtual) < int(numeroPaginas)):
 +
        # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
 +
        paginaAtual = paginaAtual + 1
 +
        p = subprocess.call(['xpdf.real','-remote',arquivo,'-exec', comando])
 +
        return jsonify({'resultado': True}), 200
 +
    else:
 +
        print 'Usuario '+usuario+' tentou acessar a pagina '+str(paginaAtual+1)+' do pdf '+pastaUsuario+arquivo+' inexistente!'
 +
        return jsonify({'resultado': False}), 404
 +
 +
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/retrocederProjecao
 +
# Retrocede uma pagina
 +
@app.route('/projetar/<arquivo>/retrocederProjecao', methods=['GET'])
 +
def retrocede_pagina(arquivo):
 +
    if(int(paginaAtual) > 1):
 +
        comando = 'prevPage'
 +
        # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
 +
        subprocess.call(['xpdf.real','-remote',arquivo,'-exec', comando])
 +
        return jsonify({'resultado': True}), 200
 +
    else:
 +
        print 'Usuario '+usuario+' tentou acessar a pagina '+str(paginaAtual-1)+' do pdf '+pastaUsuario+arquivo+' inexistente!'
 +
        return jsonify({'resultado': False}), 404
 +
 +
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/saltarProjecao/{numPagina}
 +
# Avanca para uma pagina do pdf, se a pagina nao existir retorna um codigo de erro
 +
@app.route('/projetar/<arquivo>/saltarProjecao/<int:pagina>', methods=['GET'])
 +
def salta_paginas(arquivo,pagina):
 +
    global paginaAtual
 +
    if(pagina <= int(numeroPaginas) and (int(pagina) > 0)):
 +
        comando = 'gotoPage('+str(pagina)+')'
 +
        # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
 +
        subprocess.call(['xpdf.real','-remote',arquivo,'-exec',comando])
 +
        paginaAtual = pagina
 +
        return jsonify({'resultado': True}), 200
 +
    else:
 +
        print 'Usuario '+usuario+' tentou acessar a pagina '+str(pagina)+' do pdf '+pastaUsuario+arquivo+' inexistente!'
 +
        return jsonify({'resultado': False}), 404
 +
 +
 +
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/fechar
 +
# Fechar projecao
 +
@app.route('/projetar/<arquivo>/fechar', methods=['GET'])
 +
def fechar_projecao(arquivo):
 +
    comando = 'quit'
 +
    global paginaAtual
 +
    global numeroPaginas
 +
    paginaAtual = numeroPaginas = ""
 +
    # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
 +
    subprocess.call(['xpdf.real','-remote',arquivo,'-exec', comando])
 +
    return jsonify({'resultado': True}), 200
 +
 
 +
###################### OBTEM THUMB ##########################
 +
 +
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/obterThumb/{thumb}
 +
# Retorna um thumb do tipo jpg identificado por {arquivo}-{thumb}.jpg
 +
@app.route('/projetar/<arquivo>/obterThumb/<int:thumb>', methods=['GET'])
 +
def obter_thumb(arquivo, thumb):
 +
    if((thumb < int(numeroPaginas)) & (thumb >= 0)):
 +
        fileName, fileExtension = os.path.splitext(arquivo)
 +
        caminhoArquivo = pastaUsuario+'thumbs/'+fileName+'-'+(str(thumb))+'.jpg'
 +
        return send_file(caminhoArquivo, mimetype='image/jpg')
 +
    else:
 +
        caminhoArquivo = pastaUsuario+'thumbs/'+'erro.jpg'
 +
        return send_file(caminhoArquivo, mimetype='image/jpg')
 +
 
 +
###########COMANDOS DE CONTROLE DE PROJECAO##################
 +
############OS COMANDOS NAO ESTAO FUNCIONAIS##########################
 +
# curl -i http://localhost:5000/projetar/ligarProjetor
 +
# Retrocede uma pagina
 +
#@app.route('/projetar/ligarProjetor, methods=['GET'])
 +
#def liga_projetor():
 +
#        subprocess.call(['echo "standby 0" | cec-client -s'])
 +
#        return jsonify({'resultado': True}), 200
 +
 
 +
# curl -i http://localhost:5000/projetar/desligarProjetor
 +
# Retrocede uma pagina
 +
#@app.route('/projetar/desligarProjetor, methods=['GET'])
 +
#def desliga_projetor():
 +
#        subprocess.call(['echo "on 0" | cec-client -s'])
 +
#        return jsonify({'resultado': True}), 200
 +
###############################################################
 +
 
 +
@app.errorhandler(404) ## Tratamento de erro
 +
def not_found(error):
 +
    return make_response(jsonify({'Erro': 'Recurso nao encontrado!'}), 404)
 +
 
 +
##############################################################
 +
 +
if __name__ == "__main__":
 +
    print "Servidor no ar!"
 +
    caminho = os.path.expanduser('~')+'/' # obtem o diretorio do usuario do SO
 +
    pastaUsuario = caminho+usuario+'/' # obtem o diretorio do usuario conectado (User)
 +
    ip = netifaces.ifaddresses(interface)[2][0]['addr'] # obtem o ip referente a interface
 +
    app.run(debug=True,host=ip,port=porta)
 +
</syntaxhighlight>
 +
 
 +
*Considerando a instalação correta dos componentes e que o arquivo seja salvo com o nome <font color=darkred> servidor.py </font> basta executar o web service com o comando:
 +
<syntaxhighlight lang=bash> python servidor.py </syntaxhighlight>
 +
 
 +
{{collapse bottom | Implementação do Web Service}}
 +
 
 +
==Resultados obtidos na implementação do projeto==
 +
 
 +
Nessa etapa final, cada integrante do grupo ficou responsável por uma parte do projeto. Sendo que as partes individuais da maioria funcionaram, mas tivemos alguns problemas na parte da integração. relataremos abaixo as partes do trabalho que funcionaram e as que tivemos problemas.
 +
 
 +
* Obtivemos sucesso na parte de manipulação dos slides colocados na raspberry, nessa parte conseguíamos via uma aplicação no celular, avançar ou retroceder nos slides. Só tínhamos uma pequena demora na passagem, pelo fato da demora no processamento das imagens.
  
|-
+
* As partes das aplicações visualizadas pelo usuário, no website, funcionaram em partes:
|@POST || /auth || <syntaxhighlight lang=java> String usuario </syntaxhighlight> <syntaxhighlight lang=java> String senha </syntaxhighlight> || <syntaxhighlight lang=java> boolean resposta </syntaxhighlight>|| Retorna acesso permitido, caso os dados que o usuário tenha enviado, estiverem corretos, caso contrário acesso é negado.
+
** Conseguimos fazer a autenticação dos  usuários, porém não foi possível manter a conexão do usuário
|-
+
** A parte do Upload dos arquivos funcionou perfeitamente, porém como não conseguimos manter a conexão, tivemos que criar um usuário fictício, para assim colocarmos os arquivos na pasta desse usuário, só ressaltamos que não foi implementado a exclusão de arquivos, isso foi deixado para o ciclo 2, que seria para o projeto de ideias inovadoras
|@PUT || /change_passwd || <syntaxhighlight lang=java> String usuário </syntaxhighlight> <syntaxhighlight lang=java> String senha_atual </syntaxhighlight> <syntaxhighlight lang=java> String senha_nova </syntaxhighlight>  || <syntaxhighlight lang=java> boolean resposta </syntaxhighlight> || Retorna se foi possível alterar a senha do usuário, caso contrário a senha antiga permanece.
+
** O agendamento dos arquivos foi feito a parte que estava descrita para ser realizada no ciclo 1 do projeto, mas também tivemos o mesmo problema com o usuário, descrito anteriormente
|}
+
** Tivemos um pequeno problema na hora que fomos tentar realizar o rsync com a raspberry, com isso alteramos o script para relializar a sincronização dos dados. Não foi possível testar a integração completa do sistema Webba devido a problemas técnicos ocorrido no momento. Porém, este mesmo projeto foi inscrito no projeto Ideias Inovadoras do IFSC, caso consiga passar para a etapa de desenvolvimento do projeto a meta da equipe será implementar todos os requisitos propostos previamente para o projeto e torná-lo um produto.

Edição atual tal como às 17h31min de 6 de julho de 2015

Sistema de Automatização de Sala de Aula

Esta página contém a documentação do projeto de uma Sala de Aula Inteligente, desenvolvido no contexto da disciplina de Projeto Integrador II da Engenharia de Telecomunicações do IFSC, no semestre 2015.1. Detalhes de execução do projeto podem ser encontrados nos links abaixo.

Descrição

O projeto consiste no desenvolvimento de um sistema de automatização de sala de aula, controlando o sistema de iluminação (lâmpadas), projeção e refrigeração (ar condicionado) do ambiente, a partir de um dispositivo móvel. Adicionalmente, propõe-se que o Sistema implemente um controle de acesso à sala, podendo ser efetuado através de um sistema de controle de acesso preexistente.

Análise

Levantamento de Requisitos

Funcionais:

Requisitos Funcionais

RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor;

  • RF01.1. O dispositivo móvel deve controlar o projetor (liga/desliga);
  • RF01.2. Carregar arquivo independente da extensão;
  • RF01.3. Manipular arquivos;
  • RF01.4. Passar slides para frente ou para trás;
  • RF01.5. Selecionar slide específico;
  • RF01.6. Congelar projetor;
  • RF01.7. Mudar dispositivo que irá carregar e controlar os slides;
  • RF01.8. Compartilhar slides com outros dispositivos da mesma rede.
  • RF01.9. Utilizar zoom e barra de rolagem.

RF02. O dispositivo móvel deve controlar a iluminação da sala (controle de iluminação das lâmpadas);

  • RF02.1. Fechar/Abrir cortinas;
  • RF02.2. Ligar/Apagar lâmpadas individualmente;
  • RF02.3. Mudar modo de operação;
  • RF02.4. Dimerizar lâmpadas;
  • RF02.5. Integração com sensor de presença e timer;
  • RF02.6. Notificar problemas com lâmpadas;

RF03. O dispositivo móvel deve controlar a climatização do ambiente

  • RF03.1. Ligar/desligar ar condicionado;
  • RF03.2. Aumentar/diminuir a temperatura;
  • RF03.3. Mudar modo de operação do ar condicionado;
  • RF03.4. Abrir/fechar as janelas;
  • RF03.5. Ligar/desligar os ventiladores/exaustores;
  • RF03.6. Ativar Swing do ar condicionado;
  • RF03.7. Ligar/desligar aquecedores;
  • RF03.8. Aumentar/diminuir temperatura dos aquecedores.

RF04. O Sistema deve implementar um controle da acesso ao meio (sala);

RF05. O sistema deve implementar um gerenciador de apresentações

  • RF05.1. Carregar arquivos;
  • RF05.2. Indentificar salas e horários;
  • RF05.3. Verificar conflitos de agendamento;
  • RF05.4. Autenticar usuário;
  • RF05.5. Organizar arquivos em grupos (disciplina);
  • RF05.6. Importar/Exportar agendamentos;
  • RF05.7. Gerenciar cotas para arquivos;
  • RF05.8. Compartilhar arquivos com outros usuários;
  • RF05.9. Manipular arquivos.

Não-funcionais

Requisitos Não-Funcionais

RNF01. Aunteticação: Apenas usuários com permissão podem acessar o Sistema;

RNF02. Integridade: Usuário não pode editar arquivos de outros usuários e uma sala inteligente poderá ser comandada por um único por vez;

RNF03. Desempenho e Eficiência: O Sistema possui um tempo de resposta máximo para cada instrução;

RNF04. Conectividade: O Sistema deve utilizar a infra-estrutura de redes já disponível no campus;

RNF05. Usabilidade: A interface do Sistema deve ser intuitiva;

RNF06. Restrição de Custo: O projeto possui um orçamento de no máximo U$ 100,00 (cem dólares americanos);

RNF07. Escalabilidade: O Sistema deve possuir a capacidade de expandir o número de salas inteligentes de uma maneira simples.

RNF08. Portabilidade: Ausência de dependências de implementações específicas de tecnologias.

Atores

Atores

1. Projetor: Sistema de Terceiro que projeta os arquivos.

2. Ar-condicionado: Sistema de Terceiro que tem por função controlar a climatização do ambiente.

3. Usuário: Indivíduo que tem permissão para controlar as funcionalidades do sistema.

4. Sensor de presença: Sistema de terceiro que detecta a presença de algum indivíduo no ambiente.

5. Ventilador: Sistema de terceiro que ventila o ambiente.

6. Lâmpada: Sistema de terceiro utilizado para iluminação do ambiente.

7. Banco de dados: Servidor para armazenar os dados e arquivos (slides) dos usuários.

8. Aquecedores: Sistema de terceiro que possui a mesma funcionalidade do 2º ator, porém só eleva a temperatura do ambiente.

9. Temporizador: Sistema de terceiro utilizado para iniciar ou encerar um evento.

10. Cortinas: Sistema de terceiro utilizado para adequar a iluminação do ambiente.

11. Controle de acesso ao meio: Sistema de terceiro utilizado para permitir o acesso ao ambiente.

Casos de Uso

Descrição dos Casos de Uso
Caso de uso.png

CSU01

Cadastrar Projetor

Sumário: Usuário cadastra o projetor que a sala possui.

Ator Primário: Usuário

Atores Secundários: Banco de dados

Precondições: Usuário ter sido autenticado.

Fluxo Principal

1. O sistema solicita que o usuário cadastre o dispositivo de projeção.

2. O usuário informa qual o dispositivo que pertence a sala.

3. O usuário nomeia o dispositivo de projeção

4. O sistema cadastra o dispositivo informado pelo usuário.

5. O usuário configura o dispositivo para cadastrar uma configuração default.

6. O sistema ajusta as funcionalidades do dispositivo configurado pelo usuário.

Pós-condições: Dispositivo de projeção cadastrado e pronto para ser utilizado.

CSU02

Carregar Arquivo para Projetor

Sumário: Usuário seleciona o arquivo que será carregado do banco de dados para o projetor.

Ator Primário: Usuário

Atores Secundários: Banco de dados

Precondições: Usuário ter sido autenticado e ter cadastrado dispositivo de projeção.

Fluxo Principal

1. O usuário seleciona no banco de dados qual o arquivo que será carregado, com auxílio de um dispositivo móvel.

2. O banco de dados envia para o projetor o arquivo que será exibido.

Fluxo Alternativo (1): Arquivo não existe.

a. O banco de dados envia uma mensagem para o usuário informando que o arquivo não existe e o usuário deve escolher outro arquivo ou carregar outro arquivo no banco de dados.

Fluxo Alternativo (2): Mudar de dispositivo que irá carregar o arquivo.

a. O usuário se autentica em outro dispositivo para carregar o arquivo

Pós-condições: Arquivo carregado e sendo exibido pelo dispositivo de projeção

CSU03

Compartilhar Arquivo

Sumário: Usuário seleciona o arquivo que será compartilhado com outros usuários que assistem à apresentação.

Ator Primário: Bando de dados

Atores Secundários: Outros usuários

Precondições: Usuário ter sido autenticado, ter cadastrado dispositivo de projeção e ter carregado o arquivo.

Fluxo Principal

1. O banco dados disponibiliza o QR code do arquivo para os usuários.

2. Os outros usuários escaneam o QR code (utilizando um aplicativo próprio para isso) do arquivo e fazem download.

Fluxo Exceção (1): Sem acesso ao banco de dados.

a. O download poderá ser fornecido em outro momento quando o bancos de dados estiver disponível.

Pós-condições: Arquivo compartilhado com todos os usuários autenticados.

CSU04

Controlar Projetor

Sumário: Usuário utiliza o sistema para controlar o projetor.

Ator Primário: Usuário

Atores Secundários: Projetor

Precondições: Usuário ter sido autenticado, ter cadastrado dispositivo de projeção e ter carregado o arquivo.

Fluxo Principal

1. O usuário solicita que o projetor seja ligado, com auxílio do dispositivo móvel.

2. O sistema configura o projetor de acordo com as solicitações do usuário realizadas no CSU01.

3. O usuário pode passar para frente ou para trás os slides.

4. O usuário seleciona um slide específico.

5. O usuário congela a projeção de slides.

6. O usuário utiliza a barra de rolagem ou zoom para melhorar a visualização do slide.

Fluxo Exceção (1): Lâmpada do projetor queimada.

a. O sistema envia uma mensagem ao usuário informando que deve trocar a lâmpada do projetor.

Fluxo Alternativo (1): Mudar dispositivo que irá controlar o dispositivo de projeção.

a. Usuário se autentica em outro dispositivo e passa à manipular o arquivo no novo dispositivo, sem a necessidade de voltar aos casos de uso, CSU01, ou CSU02, ou ainda CSU03.

Fluxo Alternativo (2): Manipular arquivos.

a. Usuario seleciona outro arquivo à ser projetado, o sistema deve executar o CSU02.

Pós-condições: Projetor ligado e funcionando de acordo como o usuário solicitou

Ana4.png

CSU05

Cadastro da sala e dos modos de operação

Sumario: usuário cadastrar os modos de operação de cada sala.

Ator principal: usuário.

Ator secundário: banco de dados

Precondições: o usuário já teve estar autentificado pelo sistema.

Fluxo Principal.

1. O sistema pede para cadastrar as lâmpadas e cortinas da sala.

2. Usuário informa os números de cortinas e lâmpadas.

3. Usuário cadastra as características de cada lâmpada.

4. Usuário nomeia cada lâmpada e cortina.

5.O sistema pede para cadastra os modos de operação de iluminação: cinema, aula e apresentação.

6. Usuário seleciona um modo para cadastrar.

7. Usuário indica quais lâmpadas ficaram acesa.

8.Usuário indica qual é a intensidade das lâmpadas acesa, caso se a lâmpada possui essa característica. .

9. Usuário indica em qual modo as cortinas devem ficar: aberta, fechada ou automática(as cortinas mudam sua inclinação a cada 15min, para aproveitar a luz natural).

10.Informações dos modos de operação são armazenado no banco de dados.

CSU06

Iluminação da sala

Sumario: usuário deseja selecionar um modo de operação.

Ator principal: usuário.

Ator secundário: lâmpadas, cortinas e banco de dados .

Precondições: o usuário já teve estar autentificado pelo sistema, as cortinas e as lâmpadas já devem estar cadastrada no sistema.

Fluxo Principal

1. O sistema apresenta os quatro modos de operação de iluminação: cinema, aula , apresentação e o manual.

2. Usuário seleciona uma das opções.

3. O sistema ajusta cortinas e lâmpadas conforme o modo desejado.

4. Quando a aula acabar, o sistema deve executar caso de uso CSU07.

Fluxo Alternativo (2): Modo de operação manual.

a. Executar modo o caso de uso CSU08.

Fluxo Alternativo (2): Alteração para override.

a. O usuário liga ou desliga as lâmpadas pelo interruptor.

b. O usuário ajusta a posição da cortina conforme sua escolha de forma manual

Fluxo de Exceção (3): Lâmpada queimada.

Caso alguma lâmpada queime, ocorre uma notificação para o sistema, para que possam substitui-la.

CSU07

Desligando a iluminação

Sumario: desligando todas as luzes.

Ator principal: usuário.

Ator secundário: temporizador, sensor de presença, cortinas e lâmpadas.

Precondições: o sensor de presença e temporiozador já devem estar cadastrada no sistema.

Fluxo Principal

1.Após o término da aula, o sistema liga um temporizador por um determinado tempo.

2.Após de passar esse tempo o sensor de presença é ativado.

3.Sensor de presença não detecta a presença de uma pessoa na sala, assim toda iluminação da sala é desligada e as cortinas fechadas.

Fluxo Alternativo (3): Ainda há pessoas na sala.

a. Temporizador fica acionando o sensor de presença até que não haja ninguém na sala .

CSU08

Iluminação da sala no modo manual

Sumario:usuário seleciona modo operação manual.

Ator principal: usuário.

Ator secundário :lâmpadas e cortinas.

Precondições: o usuário já teve estar autentificado pelo sistema, as cortinas e as lâmpadas já devem estar cadastrada no sistema e usuário seleciona modo operação manual.

Fluxo Principal

1. Sistema apresenta todas as lâmpadas da sala.

2. O usuário seleciona as lâmpadas que ele deseja acender.

3. O usuário seleciona as lâmpadas que ele deseja ajustar a sua intensidade, caso a lâmpada possui essa característica.

4. O usuário decide se quer abrir/fechar as cortinas da sala ou elas ficarem mo moto automático(as cortinas mudam sua inclinação a cada 15 minutos, para aproveitar a luz natural).

5. Execute caso de uso CSU07.

Fluxo de Exceção (2): Lâmpada queimada.

a.Caso alguma lampada queime, ocorre uma notificação para o sistema, para que possam substitui-la

Fluxo Alternativo (2): Alteração para override.

a. O usuário liga ou desliga as lâmpadas pelo interruptor.

b. O usuário ajusta a posição da cortina conforme sua escolha de forma manual

Pj17.png

CSU09

Climatizar

Sumário: Usuário utiliza o sistema para ajustar a temperatura da sala.

Ator Primário : Usuário.

Ator Secundário: Ar condicionado, ventilador e aquecedor.

Pré-condições: Usuário esta autenticado no sistema e aparelhos cadastrados no sistema.

Fluxo Principal:

1. O sistema apresenta os aparelho de climatização disponíveis.

2. O usuário escolhe um dos aparelhos.

3. O usuário conforme sua escolha vai para um dos casos de uso, CSU11, CSU12 ou CSU13.

4. O sistema ajustas todas as funcionalidades dos aparelhos que o usuário escolheu.

5. O sistema continua funcionando normalmente.


Fluxo de Alternativo (5): Desativação

a. O usuário solicitou ao sistema o desligamento do dispositivo de climatização. b. O sistema desliga o dispositivo.

Pós-condições: Aparelhos de climatização ligado e funcionando conforme o usuário solicitou.

CSU10

Cadastrar Aparelhos

Sumário: Usuário cadastra o número de aparelhos que a sala possui.

Ator Primário : Usuário.

Ator Secundário: Banco de dados.

Pré-condições: Usuário esta autenticado no sistema.

Fluxo Principal:

1. O usuário informa ao sistema quantos aparelhos de climatização terão na sala, como o número de ventiladores, ar condicionados e aquecedores.

2. O sistema cadastra todos os aparelhos informados pelo usuário e informa as características funcionais de cada aparelho.

3. O sistema salva as informações e as funcionalidades dos aparelhos são armazenadas no banco de dados.

Pós-condições: Aparelhos de climatização cadastrados e prontos para serem usados.

CSU11

Controlar Aquecedores

Sumário: Usuário utiliza o sistema para ajustar a temperatura da sala.

Ator Primário : Usuário.

Ator Secundário: Aquecedores e banco de dados.

Pré-condições: Usuário esta autenticado no sistema e aparelhos cadastrados no sistema.

Fluxo Principal:

1. O usuário solicita que o aquecedor seja ligado, com o auxílio do dispositivo móvel.

2. O sistema liga o aquecedor com uma temperatura padrão, essa que vai ser cadastrada nas configurações padrão que estarão armazenada no banco de dados.

3. O sistema solicita que as janelas e portas sejam fechadas.

4. O usuário volta para CSU09.

Fluxo Alternativo (1): Alteração no modo de controle do sistema.

a. O usuário pode ligar os dispositivos de climatização do modo convencional, ou seja, ouverride.

Fluxo Alternativo (2): Alteração da temperatura do aparelho.

a. O usuário escolhe uma temperatura do aquecedor. b. O sistema altera a temperatura do aparelho.

Pós-condições: Aquecedor ligado e funcionando conforme o usuário solicitou.

CSU12

Controlar Ar Condionados

Sumário: Usuário utiliza o sistema para ajustar a temperatura da sala.

Ator Primário : Usuário.

Ator Secundário: Ar condicionado e banco de dados.

Pré-condições: Usuário esta autenticado no sistema e aparelhos cadastrados no sistema.

Fluxo Principal

1. O usuário solicita que o ar condicionado seja ligado, com o auxílio do dispositivo móvel.

2. O sistema liga o ar condicionado com uma temperatura padrão, essa que vai ser cadastrada nas configurações padrão que estarão armazenada no banco de dados.

3. O sistema solicita que as janelas e portas sejam fechadas.

4. O sistema disponibiliza ao usuários os modos de operação, como ventilação, aquecimento, ativar swing ou modo turbo.

5. O usuário seleciona um dos modos de operação.

6. O usuário volta para CSU09.

Fluxo Alternativo (1): Alteração no modo de controle do sistema.

a. O usuário pode ligar os dispositivos de climatização do modo convencional, ou seja, override.

Fluxo Alternativo (2): Alteração da temperatura do aparelho.

a. O usuário escolhe uma temperatura do ar condicionado. b. O sistema altera a temperatura do aparelho.

Pós-condições: Ar condicionado ligado e funcionando conforme o usuário solicitou.

CSU013

Controlar Ventiladores

Sumário: Usuário utiliza o sistema para ajustar a temperatura da sala.

Ator Primário : Usuário.

Ator Secundário: Ventilador e banco de dados.

Pré-condições: Usuário esta autenticado no sistema e os aparelhos cadastrados no sistema.

Fluxo Principal:

1. O usuário solicita que os ventiladores sejam ligados, com o auxílio do dispositivo móvel.

2. O sistema liga os ventiladores com uma velocidade padrão, essa que vai ser cadastrada nas configurações padrão que estarão armazenada no banco de dados.

3. O sistema solicita que as janelas se abram.

4. O usuário volta para CSU09.

Fluxo Alternativo (1): Alteração no modo de controle do sistema.

a. O usuário pode ligar os dispositivos de climatização do modo convencional, ou seja, ouverride.

Fluxo Alternativo (2): Alteração da velocidade do aparelho.

a. O usuário solicita que a velocidade dos ventiladores sejam aumentadas.


Pós-condições: Ventiladores ligados e funcionando conforme o usuário solicitou.

UseCase Diagram System2.png

CSU014

Carregar Arquivo para o Banco de Dados

Sumário: Usuário utiliza o banco de dados para armazenar o arquivo.

Ator primário: Usuário.

Ator Secundário: Banco de Dados.

Pré-condição: Usuário está autenticado no sistema.

Fluxo Principal:

1. O usuário carrega o arquivo no sistema.

2. O arquivo é armazenado no Banco de Dados.

Fluxo de Exceção: Se o limite de armazenamento do usuário for atingido o sistema emitirá uma aviso sobre a impossibilidade de armazenar o arquivo.

CSU015

Autenticar Usuário

Sumário: Autenticação do usuário no Sistema.

Ator primário: Usuário.

Ator secundário: Banco de Dados.

Fluxo Principal:

1. O usuário conecta-se ao sistema.

2. O usuário fornece suas credenciais.

3. O sistema verifica se as credenciais são válidas, comparando-as com as guardadas no Banco de Dados.

4. O sistema confirma as credenciais do usuário.

Fluxo de Exceção: As credenciais podem ser inválidas e o sistema pode negar o acesso do usuário.

CSU016

Agendar Salas

Sumário: Usuário agenda uma sala para utilização posterior.

Ator primário: Usuário.

Ator secundário: Banco de Dados.

Pré-condição: Usuário está autenticado no sistema.

Fluxo Principal:

1. O usuário identifica salas e horários.

2. O usuário seleciona um horário e sala disponíveis.

3. O usuário confirma o(s) agendamento(s).

Fluxo Alternativo (1): O usuário pode utilizar a interface apenas para identificar as salas e horários disponíveis/agendadas.

Fluxo Alternativo (2): O usuário pode exportar/importar agendamentos e realocá-los na agenda de salas.

Fluxo de Exceção: Se o horário e sala selecionados estiverem ocupados o sistema emitirá um aviso sobre a impossibilidade de agendamento.

CSU017

Manipular Arquivos no Banco de Dados

Sumário: O usuário pode manipular arquivos e diretórios no Banco de Dados.

Ator primário: Usuário.

Ator secundário: Banco de Dados.

Pré-condição: Usuário está autenticado no sistema.

Fluxo Principal:

1. O usuário seleciona o arquivo ou diretório.

2. O usuário seleciona a operação que deseja realizar com ele (excluir, copiar, mover, compartilhar).

Fluxo de Exceção (1): Caso o usuário copie um arquivo e o limite de armazenamento do usuário for atingido, o sistema emitirá uma aviso sobre a impossibilidade de armazenar o arquivo.

Fluxo de Exceção (2): Se o usuário tentar compartilhar um arquivo com um usuário inexistente, o sistema emitirá uma aviso sobre a impossibilidade de compartilhar o arquivo devido a inexistência do usuário selecionado.

CSU018

Carregar Arquivos para o Projetor

Sumário: O temporizador define com base em agendamentos prévios realizados pelo usuário quando carregar o arquivo para o projetor.

Ator primário: Temporizador.

Atores secundários: Projetor, Banco de Dados e Usuário.

Pré-condição: Agendamento prévio realizado pelo usuário.

Fluxo Principal:

1. O temporizador verifica que há um arquivo a ser carregado para um projetor.

2. O temporizador carrega o arquivo do banco de dados para o projetor.

Modelo de Domínio

Modelo de Dominio2.jpg

Arquivo: Diagrama no Astah.

Desenvolvimento

Plano de Desenvolvimento

A execução do projeto, dentro da disciplina de Projeto Integrador II de 2015.1, consistirá de 2 ciclos de desenvolvimentos. Ao final de cada ciclo, os conjuntos de requisitos funcionais abaixo devem ser satisfeitos:

Ciclo 1
  • RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
    • RF01.1. O dispositivo móvel deve controlar o projetor (liga/desliga);
    • RF01.3. Manipular arquivos;
    • RF01.4. Passar slides para frente ou para trás;
    • RF01.5. Selecionar slide específico;
      • A partir do número do slide
  • RF05. O sistema deve implementar um gerenciador de apresentações
    • RF05.1. Carregar arquivos
    • RF05.2. Indentificar salas e horários
    • RF05.4. Autenticar usuário
      • A partir de arquivo de usuário e senha
Ciclo 2
  • RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
    • RF01.2. Carregar arquivo independente da extensão
    • RF01.6. Congelar projetor
    • RF01.7. Mudar dispositivo que irá carregar e controlar os slides
    • RF01.8. Compartilhar slides com outros dispositivos da mesma rede
    • RF01.9. Utilizar zoom e barra de rolagem
  • RF02. O dispositivo móvel deve controlar a iluminação da sala (controle de iluminação das lâmpadas)
    • RF02.6. Notificar problemas com lâmpadas
  • RF05. O sistema deve implementar um gerenciador de apresentações
    • RF05.3. Verificar conflitos de agendamento
    • RF05.4. Autenticar usuário
      • completo
    • RF05.9. Manipular arquivos
Ciclos Posteriores / Implementações adicionais
  • RF01. O dispositivo móvel deve controlar a projeção de arquivos pelo projetor
    • RF01.5. Selecionar slide específico
      • A partir de lista de slides ou Thumbs
    • RF01.9. Utilizar zoom e barra de rolagem
  • RF02. O dispositivo móvel deve controlar a iluminação da sala (controle de iluminação das lâmpadas)
    • RF02.1. Fechar/Abrir cortinas
    • RF02.2. Ligar/Apagar lâmpadas individualmente
    • RF02.3. Mudar modo de operação
    • RF02.4. Dimerizar lâmpadas
    • RF02.5. Integração com sensor de presença e timer
  • RF03. O dispositivo móvel deve controlar a climatização do ambiente
    • RF03.1. Ligar/desligar ar condicionado
    • RF03.2. Aumentar/diminuir a temperatura
    • RF03.3. Mudar modo de operação do ar condicionado
    • RF03.4. Abrir/fechar as janelas
    • RF03.5. Ligar/desligar os ventiladores/exaustores
    • RF03.6. Ativar Swing do ar condicionado
    • RF03.7. Ligar/desligar aquecedores
    • RF03.8. Aumentar/diminuir temperatura dos aquecedores
  • RF04. O Sistema deve implementar um controle da acesso ao meio (sala)
  • RF05. O sistema deve implementar um gerenciador de apresentações
    • RF05.5. Organizar arquivos em grupos (disciplina)
    • RF05.6. Importar/Exportar agendamentos
    • RF05.7. Gerenciar cotas para arquivos
    • RF05.8. Compartilhar arquivos com outros usuários

Estudo das Tecnologias

Sincronização de Diretórios Utilizando Rsync

Sincronização de Diretórios Utilizando Rsync [1] - Solução Obsoleta
1. Primeiramente no servidor e no cliente tem que estar instalado a ferramenta rsync. Caso não esteja:
$ sudo apt-get install rsync

2. Também no servidor deve estar instalado o servidor ssh

$ sudo apt-get install openssh-server

3. Crie o arquivo /etc/rsyncd.conf configuração para rsync.

  • A seguir tem um exemplo da configuração do arquivo rsyncd.conf para nosso projeto:
# /etc/rsyncd: configuration file for rsync daemon mode

# configuration:

# limitar o acesso aonde os usuários podem enviar arquivos
use chroot = yes
# número máximo de conexões
max connections = 2
# hosts (ips) que podem ser conectar ao servidor rsync
hosts allow = 192.168.1.0/255.255.255.0
timeout = 600
# ignorar arquivos que não podem ser lidos
ignore nonreadable = yes
# usuários que podem operações de send e recv.
auth users = karol
# arquivo com os usuários e senhas 
secrets file = /etc/rsyncd.secrets
# não há nenhuma restrição para manipular os arquivos e pastas 
uid = root
gid = root
dont compress   = *
# ativar o log de send e recv
transfer logging = yes
# formato do arquivo de log de transferência
log format = %t: host %h (%a) %o %f %L (%l bytes). Total %b bytes.
log file = /etc/log/rsyncd.log
# pastas que não serão mostradas ao adim e usuários do servidor
exclude = lost+found/
#pid file = /var/run/rsyncd.pid

[backup]

	path = /home/karol/raiz
	read only = no
	comment = diretório do projetor

4. Criar /etc/rsyncd.secrets para a senha do usuário. Usuário deve ser o mesmo que o anterior, com a senha usada para fazer login na máquina remota como o usuário indicado.

$ Sudo gedit /etc/rsyncd.secrets 
user: password
  • Um exemplo do que foi feito:
# /etc/rsync.secrets
# Usuários e senhas que se conectarão ao servidor
# Formato:
# <usuario>:<senha>
karol:karol0802

5. Criar /etc/rsyncd.log onde esse irá gravar:

%t: o tempo que foi feito o download.
%h: o nome do host.
%a: o ip do servidor remoto.
%o: qual foi a operação que o cliente realizou (send, receive, delete).
%f: nome do arquivo.
%L: qual será o symlink => hardlink.
%l: tamanho do arquivo em bytes.
%b: número de bytes realmente transmitidos.

6. Transferindo arquivos com rsync:

  • Upload para o servidor:
$ rsync -LCravzp /path_origem/ user@hostname:/path_destino/
  • Exemplo prático:
$ rsync -LCravzp /home/karol/backup/ karol@192.168.1.7:/home/karol/raiz/equipamentos/projetor/projetor1/
  • Download do servidor para o cliente:
$ rsync -LCravzp /path_destino/ user@hostname:/path_origem/
  • Exemplo prático:
$ rsync -LCravzp /home/karol/raiz/equipamentos/projetor/projetor1/ karol@192.168.1.7:/home/karol/backup/
  • Explicação das flags:
-L: transforma link simbólico de origem  em um hard link  no destino.
-C: auto-ignora arquivos idênticos.
-r: recursividade, faz ele buscar arquivos nas subpastas.
-a: indica que estarão sendo copiados arquivos.
-v: modo verboso, mais informações da cópia.
-z: comprime os arquivos durante a cópia.
-p: indicador de progresso de cópia

7. Para criar um link simbólico da pasta do usuário para um projetor deve executar o seguinte comando.

$ ln -s /path_origem/arquivo  /path_destino/ nome_do_link_simbolico
  • Exemplo prático:
 $ ln -s /home/karol/raiz/usuarios/ana/redes/lista.pdf /home/karol/raiz/equipamentos/projetor/projetor1/sb_lista.pdf
Sincronização de Diretórios Utilizando Rsync [2] - Solução Atual
Exemplo da Estrutura de Diretórios no Servidor
Dire1.png
Sincronização de Relógio - NTP
Instalar NTP daemon
# sudo apt-get install ntp

Observação: Cliente e servidor devem instalar o ntp.

Configurando NTP daemon - Servidor NTP

1.Escolher servidores NTP.

  server 3.br.pool.ntp.org
  server 1.south-america.pool.ntp.org
  server 0.south-america.pool.ntp.org

2. Arquivo de configuração do servidores NTP

  • Abrir o arquivo de configuração do Servidor NTP e substituir pela configuração abaixo:
# /etc/ntp.conf
  • Configuração
# For more information about this file, see the man pages
# ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5).

driftfile /var/lib/ntp/drift

# Permit time synchronization with our time source, but do not
# permit the source to query or modify the service on this system.
restrict default nomodify notrap nopeer noquery

# Permit all access over the loopback interface.  This could
# be tightened as well, but to do so would effect some of
# the administrative functions.
restrict 127.0.0.1

# Hosts on local network are less restricted.
#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
restrict 192.168.0.0 mask 255.255.255.0 nomodify notrap # permite que somente clientes da mesma subrede sincronizem com o servidor

# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
#server 0.fedora.pool.ntp.org iburst
#server 1.fedora.pool.ntp.org iburst
#server 2.fedora.pool.ntp.org iburst
#server 3.fedora.pool.ntp.org iburst

server 3.br.pool.ntp.org # NTP server on Brazil
server 1.south-america.pool.ntp.org # NTP server on Brazil
server 0.south-america.pool.ntp.org # NTP server on Brazil

# Enable public key cryptography.
#crypto

includefile /etc/ntp/crypto/pw

# Key file containing the keys and key identifiers used when operating
# with symmetric key cryptography. 
keys /etc/ntp/keys

# Specify the key identifiers which are trusted.
#trustedkey 4 8 42

# Specify the key identifier to use with the ntpdc utility.
#requestkey 8

# Specify the key identifier to use with the ntpq utility.
#controlkey 8

# Enable writing of statistics records.
#statistics clockstats cryptostats loopstats peerstats

# Disable the monitoring facility to prevent amplification attacks using ntpdc
# monlist command when default restrict does not include the noquery flag. See
# CVE-2013-5211 for more details.
# Note: Monitoring will not be disabled with the limited restriction flag.
disable monitor

logfile /var/log/ntp.log - log file for NTP server

3. Configurar o Firewall

# firewall-cmd --add-service=ntp --permanent
# firewall-cmd --reload

4. Iniciar servidor NTP

# systemctl start ntpd
# systemctl enable ntpd
# systemctl status ntpd

5.Configurar para iniciar quando o servidor reiniciar

# chkconfig ntpd on
Configurar Cliente NTP

1. Arquivo de configuração do Cliente NTP

  • Abrir o arquivo de configuração do Cliente NTP e inserir o código abaixo:
# /etc/ntp.conf
  • Código
server 192.168.0.103

2 Comando para sincronização dos relógios entre o cliente e servidor

  1. ntpdate [IP-SERVIDOR]

</syntaxhighlight>

Arquivo de Configuração do Rsync

1. Edita o arquivo /etc/rsyncd.conf com a configuração logo baixo para o rsync.

# /etc/rsyncd: configuration file for rsync daemon mode

# configuration:

max connections = 4
timeout = 600
uid = root
gid = root
#motd file = /srv/webba/conf/rsyncd.motd
secrets file = /srv/webba/conf/rsyncd.secrets
log file = /srv/webba/conf/log/rsyncd.log
exclude = lost+found/

[session-rasp1]

	path = /srv/webba//equipamentos/projetor
	use chroot = yes	
	read only = no
	auth users = session-rasp1
	dont compress   = *
	transfer logging = yes
	log format = %t: host %h (%a) %o %f %L (%l bytes). Total %b bytes.
	hosts allow = 192.168.0.0/255.255.255.0
	ignore nonreadable = yes 
	comment = diretório da sala 1

[session-rasp2]

	path = /srv/webba//equipamentos/projeto
	use chroot = yes		
	read only = no
	dont compress = *
	transfer logging = yes
	log format = %t: host %h (%a) %o %f %L (%l bytes). Total %b bytes.
	auth users = session-rasp2
	hosts allow = 192.168.0.0/255.255.255.0
	ignore nonreadable = yes 
	comment = diretório da sala 2		

[session-rasp3]

	path = /srv/webba//equipamentos/projeto
	use chroot = yes	
	read only = no
	dont compress  = *
	transfer logging = yes	
	log format = %t: host %h (%a) %o %f %L (%l bytes). Total %b bytes.
	auth users = session-rasp3
	hosts allow = 192.168.0.0/255.255.255.0
	ignore nonreadable = yes 
	comment = diretório da sala 3

[session-rasp4]

	path = /srv/webba//equipamentos/projeto
	use chroot = yes	
	read only = no
	dont compress  = *
	transfer logging = yes
	log format = %t: host %h (%a) %o %f %L (%l bytes). Total %b bytes.
	auth users = session-rasp4
	hosts allow = 192.168.0.0/255.255.255.0
	ignore nonreadable = yes 
	comment = diretório da sala 4
Scripts para Teste
1. Script que o servidor precisa executar:
#!/bin/bash
##############################################################
# Sistema de Sincronização de Diretórios                     #
# Autor............: Guilherme, Karoline e Ana Luiza         #
# Data Criacao.....: 26/03/2015                              #
# Versao...........: 1.0.0                                   #
##############################################################

##############################################################
# Dando permissão para só o root acessar o arquivo de senhas #
##############################################################

chown root /srv/webba/cfg/rsyncd.secrets

################################################################
#Subindo o daemon para o cliente poder iniciar a sincronização #
################################################################

rsync --daemon --config=/etc/rsyncd.conf --port=873

echo " Servidor disponível para iniciar sincronização! " 

exit
2. Script para o cliente
#!/bin/bash
##############################################################
# Sistema de Sincronização de Diretórios                     #
# Autor............: Guilherme, Karoline e Ana Luiza         #
# Data Criacao.....: 26/03/2015                              #
# Versao...........: 1.0.0                                   #
##############################################################

##############################################################
# VARIAVEIS DO SISTEMA                                       #
##############################################################

#modelo de execução -> /caminho_para_script/b_rynsc.sh server module user dest

if [ $# -lt 3 ]; then
   echo "Passagem de argumentos incorreta!"
   exit 1
fi

# $0 é o próprio script

# IP ou Hostname do servidor de backup
server=$1

#Módulo referente ao cliente
module=$2

#Usuário deste módulo
user=$3

#Destino de Sincronização
dest="$4"

#Servidor de Sincronização
src="$user@$server::$module/"

#Execução do rsync
rsync='/usr/bin/rsync -LCPravzp --delete'

# Arquivos de Log
log=/srv/webba/cfg/log/`date +%Y-%m-%d`.log

##############################################################
# SINCRONIZAÇÃO                                              #
##############################################################

echo " " >> $log
echo " " >> $log

echo "---------------------- Iniciando o Sincronismo ----------------------" >> $log
date "+Sistema de Sincronismo iniciado em %d-%m-%Y as %H:%M" >> $log

$rsync $src $dest >> $log

date "+Sistema de sincronismo terminado em %d-%m-%Y as %H:%M" >> $log
echo " ---------------------- Fim do Sincronismo --------------------------" >> $log
echo "Sincronismo concluido com sucesso - Por Favor consultar os arquivos de Logs" >> $log

echo " " >> $log
echo " " >> $log

exit
3. Script para criação do symlinks
#!/bin/bash
 
##############################################################
# Sistema de Sincronização de Diretórios                     #
# Autor............: Guilherme, Karoline e Ana Luiza         #
# Data Criacao.....: 26/03/2015                              #
# Versao...........: 1.0.0                                   #
##############################################################
 
 
#ordem dos parâmetros: usuário, pasta, arquivo e projetor
 
user=$1
pasta=$2
arq=$3
proj=$4 
 
origem="/home/heisenberg/srv/webba/usuarios/${user}/${pasta}/${arq}"
 
date=`date +%Y-%m-%d:%H:%M:%S` 
echo $date
 
destino="/home/heisenberg/srv/webba/equipamentos/projetor/${proj}/${arq}_${date}"
 
 
 
#echo $destino
 
 
file="$destino"

if [ -f "$file" ]
then
 
	#echo "$file Arquivo já exisistente, remomeação automatica."
 
            destino2="/home/heisenberg/srv/webba/equipamentos/projetor/${proj}/${user}_${pasta}_${arq}_${date}"         
 
            if [  -f "$destino2" ];
            then
 
 		echo " Arquivo já exisistente ";
 
 
	    else
 
 		#echo "Arquivo renomeado e criado ";
                  ln -s  $origem  $destino2 
		  find -L /home/heisenbergl/srv/webba/equipamentos/projetor/${proj} -maxdepth 1 -type l -delete	
 
	  fi
 
 
 else
       echo "Arquivo criado "; 
        ln -s  $origem  $destino
	find -L /home/heisenberg/srv/webba/equipamentos/projetor/${proj} -maxdepth 1 -type l -delete
 fi
4. Script para remoção de todos os link simbólicos que estão dentro do projetor
#!/bin/bash

find /srv/webba/equipamentos/projetor -type l -exec rm {} \;
5. Script para remoção dos hard links que estão na central da sala
#!/bin/bash

find /S001/projetor -type f -exec rm {} \;
5. Script para Sincronização do Tempo - NTP
#!/bin/bash
##############################################################
# Sistema de Sincronização de Diretórios                     #
# Autor............: Guilherme, Karoline e Ana Luiza         #
# Data Criacao.....: 26/03/2015                              #
# Versao...........: 1.0.0                                   #
##############################################################

#ntpdate [IP-SERVIDOR]

ntpdate 200.135.233.8
Plano de Sincronização
Pla1.png

OBS.: O restante dos horários o usuário estará permitido para realizar upload de arquivos para o servidor e de forçar sincronizações.

Crontab
Sintaxe

Dentro do arquivo que se abre após o comando existe uma sintaxe conforme a seguir

mm hh dd MM ss script

Onde

mm = minuto(0-59)
hh = hora(0-23)
dd = dia(1-31)
MM = mes(1-12)
ss = dia_da_semana(0-6)
script = comando a ser executado.
Obs 1: Em dia_da_Semana, 0 refere-se a domingo; e 6, ao sábado. 
       No caso de dia da semana funciona também as três primeiras letras 
       (em inglês) do dia da semana (SUN,MON,TUE,WED,THU,FRI,SAT)
Obs 2: Em qualquer posição pode-se usar o * (asterisco) quando não se 
       importar com o campo em questão.
Obs 3: Pode-se utilizar intervalos nesses campos. O caracter para intervalo
       é o - (hifen).
Obs 4: Pode-se utilizar lista de valores nesses campos. O caracter para a
       lista é a , (vírgula).
Obs 5: Qualquer texto colocado após o programa que será executado será
       considerado comentário e não será interpretado pelo cron


Configurar Crontab
Servidor
  • Para configurar um crontab no servidor, utiliza-se o comando:
# crontab -e
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
00 23   * * 1-5  webba     sh  /opt/webba/srv/cfg/script/removels.sh 
25 5    * * 1-5  webba     sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
5 7     * * 1-5  webba     sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
20 9    * * 1-5  webba     sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
5 13    * * 1-5  webba     sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
20 15   * * 1-5  webba     sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
5 18    * * 1-5  webba     sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
20 20   * * 1-5  webba     sh  /opt/webba/srv/cfg/script/chama_agendamento.sh
#
Cliente
  • Para configurar um crontab no cliente, utiliza-se o comando:
# crontab -e
#Configurando o cliente
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
 
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
00 23  * * 1-5 root    sh  /s001/cfg/script/remove_hardlink.sh
30 5   * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
10 7   * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
25 9   * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
10 13  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
25 15  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
10 18  * * 1-5  root    sh  /s001/cfg/script/cliente_rsync.sh
25 20  * * 1-5   root    sh  /s001/cfg/script/cliente_rsync.sh  
*/1 * * * * root /      sh  /s001/cfg/script/ntp.sh             
#
SSH - Par de Chaves

Par de chaves do SSH são criptograficamente seguras e são utilizadas para autenticar um cliente num servidor. Cada par consiste em numa chave pública e em uma chave privada.

Ssh.png

1. Primeiro passo é gerar um par de chaves de SSH no computador local (no caso o cliente)

$ ssh-keygen

2.Seleciona um local aonde as chaves serão geradas. Por padrão, as chaves serão armazenadas em ~/.ssh. A chave privada será id_rsa e a chave pública id_rsa.pub

$ Enter file in which to save the key (/home/username/.ssh/id_rsa):

3.Isso é uma senha opicional que pode ser usada para criptografar a chave privada

$ Created directory '/home/username/.ssh'.
$ Enter passphrase (empty for no passphrase):
$ Enter same passphrase again:

4.Para enviar a chave pública para o servidor remoto

$ ssh-copy-id username@remote_host

5.Disabilitar Autenticação por Senha no Servidor

  • Acessar o arquivo abaixo
$ sudo vi /etc/ssh/sshd_config
  • Editar a linha que contém PasswordAuthentication, isso irá a sua capacidade de se autenticar através de senhas.
PasswordAuthentication no

Exibição de PDF com xpdf em Virtual Display

Exibição de PDF com xpdf em Virtual Display [1] - Solução obsoleta, substituída por [2]

Como parte do Detalhamento da Especificação referente ao Ciclo 1 de desenvolvimento foi estudada a projeção de processos que utilizem interface gráfica em um virtual display, com ênfase na exibição de arquivos PDF através do visualizador xpdf e envio de comandos para o mesmo através de outro terminal.

Procedimentos realizados com uma instalação normal do Ubuntu 64bits (versões Gnome e padrão 12.04 e 14.04), e com a instalação dos pacotes referentes ao xpdf.

1. Instalação do xpdf

Instalação do xpdf, visualizador de PDF's que pretende-se utilizar no projeto:

$ sudo apt-get install xpdf
2. Permissão de acesso ao startx

Permissão para que um usuário comum tenha acesso à projeção no virtual display tty8 com o startx (Opcional, mas caso esta instrução não seja seguida o usuário terá que executar a maioria dos comandos como administrador [sudo])

$ sudo chmod 555 /usr/bin/startx

Onde o código 555 refere-se ao acesso de todos os usuários para execução e escrita do arquivo.

3. Virtual Display

O virtual display refere-se ao dispositivo /dev/tty8, acessado através do comando Ctrl+AltF8.

Para exibir um processo com interface gráfica no virtual display deve-se utilizar o seguinte comando:

$ startx ${HOME}/terminal.sh -- :1 &

Onde startx refere-se à aplicação que faz a inicialização do servidor xorg, :1 refere-se ao virtual display /dev/tty8 e terminal.sh é um script shell com o conteúdo a seguir:

#!/bin/bash
env DISPLAY=:1 /usr/bin/gnome-terminal -x ${HOME}/loop.sh

gnome-terminal -x é o processo que deseja-se abrir em modo gráfico e loop.sh é um script que será explicado no item 4

4. Inicialização do terminal remoto

O arquivo loop.sh possui o seguinte código:

#!/bin/bash

while :

do	mkfifo ${HOME}/pipe
	eval $(cat pipe)
	rm ${HOME}/pipe
done

Seu funcionamento é simples, ele cria um arquivo pipe para a troca de mensagens entre o terminal local (onde serão dados os comandos) e o remoto (executando em /dev/tty8).

Após a criação do arquivo o terminal remoto monitora o arquivo, a espera de alguma modificação a ser feita pelo terminal local. Quando o terminal local modifica o arquivo (com a adição de um comando), o terminal remoto toma como um comando o que foi escrito no arquivo pipe, e o executa. Após isso, ele exclui o arquivo e recria-o para a obtenção de um comando posterior.

5. Envio de comandos para o terminal remoto

Para o envio de comandos para o terminal remoto utiliza-se o comando echo, e direciona-se sua saída para o arquivo pipe, como é demonstrado a seguir:

echo "gnome-terminal -x xpdf -fullscreen -remote servidor slide.pdf" > ${HOME}/pipe

Onde o comando gnome-terminal -x refere-se a abrir uma nova instância do terminal em /dev/tty8, xpdf -fullscreen -remote servidor refere-se a abrir o xpdf em modo fullscreen e como um servidor (de nome servidor) que pode receber comandos externos, e slide.pdf é um exemplo de slide que pode ser aberto.

Com o xpdf aberto e o terminal disponível para receber comandos (pois a abertura do xpdf é executada por outra instância do gnome-terminal), é possível manipular a apresentação de slides, podendo passar para o próximo slide, com a execução do comando a seguir, por exemplo:

echo "gnome-terminal -x xpdf.real -remote servidor -exec nextPage" > ${HOME}/pipe

Note que o comando torna-se xpdf.real para manipular os slides, o parâmetro -remote servidor refere-se a sessão aberta e o comando -exec nextPage infere na projeção da próxima página pdf do arquivo.

6. Finalizar execução do terminal remoto

Para finalizar a execução no virtual display basta escrever no arquivo pipe a instrução exit, que será interpretada como um comando pelo terminal remoto, como segue abaixo:

echo "exit" > ${HOME}/pipe

Antes de finalizar a sessão no shell deve-se garantir que as outras aplicações que executam remotamente (como o xpdf) tenham sido finalizadas!

Exibição de PDF com xpdf em Virtual Display [2] - Solução obsoleta, substituída por [3]

Como parte do Detalhamento da Especificação referente ao Ciclo 1 de desenvolvimento foi estudada a projeção de processos que utilizem interface gráfica em um virtual display, com ênfase na exibição de arquivos PDF através do visualizador xpdf e envio de comandos através de um terminal para uma sessão remota da aplicação.

Procedimentos realizados com uma instalação normal do Ubuntu 64bits (versões Gnome e padrão 12.04 e 14.04), e com a instalação dos pacotes referentes ao xpdf. Os procedimentos também foram testados em uma placa Raspberry Pi B+, utilizando a distribuição Minibian e instalando os pacotes referentes ao Xorg e xpdf.

Procedimentos realizados no Ubuntu

Assuma que os scripts executáveis e os arquivos a serem projetados estejam na pasta pessoal do usuário!

1. Instalação do xpdf

Instalação do xpdf, visualizador de PDF's que pretende-se utilizar no projeto:

$ sudo apt-get install xpdf

2. Permissão de acesso ao startx

Permissão para que um usuário comum tenha acesso à projeção no virtual display tty8 com o startx (Opcional, mas caso esta instrução não seja seguida o usuário terá que executar a maioria dos comandos como administrador [sudo])

$ sudo chmod 555 /usr/bin/startx

Onde o código 555 refere-se ao acesso de todos os usuários para execução e escrita do arquivo.

3. Virtual Display

O virtual display refere-se ao dispositivo /dev/tty8, acessado através do comando Ctrl+AltF8.

Para exibir um processo com interface gráfica no virtual display deve-se utilizar o seguinte comando:

$ startx ${HOME}/terminal.sh -- :1 &

Onde startx refere-se à aplicação que faz a inicialização do servidor xorg, :1 refere-se ao virtual display /dev/tty8 e terminal.sh é um script shell com o conteúdo a seguir:

#!/bin/bash
env DISPLAY=:1 /bin/bash ${HOME}/loop.sh

/bin/bash é o processo que receberá as instruções a serem executadas na exibição do PDF, e loop.sh é um script que será explicado no tópico abaixo

4. Inicialização do terminal remoto

O arquivo loop.sh possui o seguinte código:

#!/bin/bash

while :

do	mkfifo ${HOME}/pipe
	eval $(cat pipe)
	rm ${HOME}/pipe
done

Seu funcionamento é simples, ele cria um arquivo pipe para a troca de mensagens entre o terminal local (onde serão dados os comandos) e o remoto (executando em /dev/tty8).

Após a criação do arquivo o terminal remoto monitora o arquivo, a espera de alguma modificação a ser feita pelo terminal local. Quando o terminal local modifica o arquivo (com a adição de um comando), o terminal remoto toma como um comando o que foi escrito no arquivo pipe, e o executa. Após isso, ele exclui o arquivo e recria-o para a obtenção de um comando posterior.

5. Envio de comandos para o terminal remoto

Para o envio de comandos para o terminal remoto utiliza-se o comando echo, e direciona-se sua saída para o arquivo pipe, como é demonstrado a seguir:

echo "/bin/bash -c 'xpdf -fullscreen -remote servidor ${HOME}/slide.pdf &'" > ${HOME}/pipe

Onde o comando /bin/bash refere-se a abrir uma nova instância do processo para executar a aplicação desejada (xpdf), e slide.pdf é um exemplo de slide que pode ser aberto.

Com o xpdf aberto e o terminal disponível para receber comandos (pois a abertura do xpdf é executada por outra instância do bash), é possível manipular a apresentação de slides, podendo passar para o próximo slide, com a execução do comando a seguir, por exemplo:

echo "/bin/bash -c 'xpdf.real -remote servidor -exec nextPage &'" > ${HOME}/pipe

Note que o comando torna-se xpdf.real para manipular os slides, o parâmetro -remote servidor refere-se a sessão aberta e o comando -exec nextPage infere na projeção da próxima página do arquivo.

6. Finalizar execução do terminal remoto

Para finalizar a execução no virtual display basta escrever no arquivo pipe a instrução exit, que será interpretada como um comando pelo terminal remoto, como segue abaixo:

echo "exit" > ${HOME}/pipe

Antes de finalizar a sessão no shell deve-se garantir que as outras aplicações que executam remotamente (como o xpdf) tenham sido finalizadas!

Procedimentos realizados na Raspberry Pi

A conta padrão para acesso na distribuição Minibian possui permissões de superusuário, portanto não houve preocupação com relação a permissionamento de ações do usuário. Em outra etapa do projeto tal limitação deverá ser estudada/resolvida. (Login: root, Password: raspberry).

Assuma que os scripts executáveis e os arquivos a serem projetados estejam na pasta pessoal do usuário!

1. Instalação do xpdf

$ apt-get install xpdf

2. Instalação do Xorg

$ apt-get install xorg

3. Virtual Display

O virtual display refere-se ao dispositivo /dev/tty7, acessado através do comando Ctrl+AltF7.

Para exibir um processo com interface gráfica no virtual display deve-se utilizar o seguinte comando:

$ startx ${HOME}/terminal.sh -- :1 &

Onde startx refere-se à aplicação que faz a inicialização do servidor xorg, :1 refere-se ao virtual display /dev/tty7 e terminal.sh é um script shell com o conteúdo a seguir:

#!/bin/bash
env DISPLAY=:1 /bin/bash ${HOME}/loop.sh

/bin/bash é o processo que receberá as instruções a serem executadas na exibição do PDF, e loop.sh é um script que será explicado no tópico abaixo

4. Inicialização do terminal remoto

O arquivo loop.sh possui o seguinte código:

#!/bin/bash

while :

do	mkfifo ${HOME}/pipe
	eval $(cat pipe)
	rm ${HOME}/pipe
done

Seu funcionamento é simples, ele cria um arquivo pipe para a troca de mensagens entre o terminal local (onde serão dados os comandos) e o remoto (executando em /dev/tty8).

Após a criação do arquivo o terminal remoto monitora o arquivo, a espera de alguma modificação a ser feita pelo terminal local. Quando o terminal local modifica o arquivo (com a adição de um comando), o terminal remoto toma como um comando o que foi escrito no arquivo pipe, e o executa. Após isso, ele exclui o arquivo e recria-o para a obtenção de um comando posterior.

5. Envio de comandos para o terminal remoto

Para o envio de comandos para o terminal remoto utiliza-se o comando echo, e direciona-se sua saída para o arquivo pipe, como é demonstrado a seguir:

$ echo "/bin/bash -c 'xpdf -fullscreen -remote servidor ${HOME}/slide.pdf &'" > ${HOME}/pipe

Onde o comando /bin/bash refere-se a abrir uma nova instância do processo para executar a aplicação desejada (xpdf), e slide.pdf é um exemplo de slide que pode ser aberto.

Com o xpdf aberto e o terminal disponível para receber comandos (pois a abertura do xpdf é executada por outra instância do bash), é possível manipular a apresentação de slides, podendo passar para o próximo slide, com a execução do comando a seguir, por exemplo:

$ echo "/bin/bash -c 'xpdf.real -remote servidor -exec nextPage &'" > ${HOME}/pipe

Note que o comando torna-se xpdf.real para manipular os slides, o parâmetro -remote servidor refere-se a sessão aberta e o comando -exec nextPage infere na projeção da próxima página do arquivo.

6. Finalizar execução do terminal remoto

Para finalizar a execução no virtual display basta escrever no arquivo pipe a instrução exit, que será interpretada como um comando pelo terminal remoto, como segue abaixo:

$ echo "exit" > ${HOME}/pipe

Antes de finalizar a sessão no shell deve-se garantir que as outras aplicações que executam remotamente (como o xpdf) tenham sido finalizadas!

Exibição de PDF com xpdf em Virtual Display [3] - Solução obsoleta, substituida pelo Web Service

Como parte do Detalhamento da Especificação referente ao Ciclo 1 de desenvolvimento foi estudada a projeção de processos que utilizem interface gráfica em um virtual display, com ênfase na exibição de arquivos PDF através do visualizador xpdf e envio de comandos através de um terminal para uma sessão remota da aplicação.

Procedimentos realizados com uma instalação normal do Ubuntu 64bits (versões Gnome e padrão 12.04 e 14.04), e com a instalação dos pacotes referentes ao xpdf. Os procedimentos também foram testados em uma placa Raspberry Pi B+, utilizando a distribuição Minibian e instalando os pacotes referentes ao Xorg e xpdf.

Procedimentos realizados no Ubuntu

Assuma que os scripts executáveis e os arquivos a serem projetados estejam na pasta pessoal do usuário!

1. Instalação do xpdf

Instalação do xpdf, visualizador de PDF's que pretende-se utilizar no projeto:

$ sudo apt-get install xpdf

2. Permissão de acesso ao startx

Permissão para que um usuário comum tenha acesso à projeção no virtual display tty8 com o startx (Opcional, mas caso esta instrução não seja seguida o usuário terá que executar a maioria dos comandos como administrador [sudo])

$ sudo chmod 555 /usr/bin/startx

Onde o código 555 refere-se ao acesso de todos os usuários para execução e escrita do arquivo.

3. Virtual Display

O virtual display refere-se ao dispositivo /dev/tty8, acessado através do comando Ctrl+Alt+F8.

Para exibir um processo com interface gráfica no virtual display deve-se utilizar o seguinte comando:

$ startx ${HOME}/terminal.sh -- :1 &

Onde startx refere-se à aplicação que faz a inicialização do servidor xorg, :1 refere-se ao virtual display /dev/tty8 e terminal.sh é um script shell com o conteúdo a seguir:

#!/bin/bash
env DISPLAY=:1 /bin/bash ${HOME}/loop.sh

/bin/bash é o processo que receberá as instruções a serem executadas na exibição do PDF, e loop.sh é um script que será explicado no tópico abaixo

4. Inicialização do terminal remoto

O arquivo loop.sh possui o seguinte código:

#!/bin/bash

while :

do	mkfifo ${HOME}/pipe
	eval $(cat pipe)
	rm ${HOME}/pipe
done

Seu funcionamento é simples, ele cria um arquivo pipe para a troca de mensagens entre o terminal local (onde serão dados os comandos) e o remoto (executando em /dev/tty8).

Após a criação do arquivo o terminal remoto monitora o arquivo, a espera de alguma modificação a ser feita pelo terminal local. Quando o terminal local modifica o arquivo (com a adição de um comando), o terminal remoto toma como um comando o que foi escrito no arquivo pipe, e o executa. Após isso, ele exclui o arquivo e recria-o para a obtenção de um comando posterior.

5. Envio de comandos para o terminal remoto

Para o envio de comandos para o terminal remoto executa-se os scripts que serão descritos no próximo tópico.

Abrir um pdf
$ ./xpdf.sh slide.pdf &

Com o xpdf aberto e o terminal disponível para receber comandos (pois a abertura do xpdf é executada por outra instância do bash), é possível manipular a apresentação de slides, podendo passar para o próximo slide, com a execução do script a seguir:

Passar slide
$ ./nextPage.sh &

6. Finalizar execução do terminal remoto

Para finalizar a execução no virtual display basta escrever no arquivo pipe a instrução exit, que será interpretada como um comando pelo terminal remoto, como segue abaixo:

echo "exit" > ${HOME}/pipe

Antes de finalizar a sessão no shell deve-se garantir que as outras aplicações que executam remotamente (como o xpdf) tenham sido finalizadas!

Procedimentos realizados na Raspberry Pi

A conta padrão para acesso na distribuição Minibian possui permissões de superusuário, portanto não houve preocupação com relação a permissionamento de ações do usuário. Em outra etapa do projeto tal limitação deverá ser estudada/resolvida. (Login: root, Password: raspberry).

Assuma que os scripts executáveis e os arquivos a serem projetados estejam na pasta pessoal do usuário!

1. Instalação do xpdf

$ apt-get install xpdf

2. Instalação do Xorg

$ apt-get install xorg

3. Virtual Display

O virtual display refere-se ao dispositivo /dev/tty7, acessado através do comando Ctrl+Alt+F7.

Para exibir um processo com interface gráfica no virtual display deve-se utilizar o seguinte comando:

$ startx ${HOME}/terminal.sh -- :1 &

Onde startx refere-se à aplicação que faz a inicialização do servidor xorg, :1 refere-se ao virtual display /dev/tty7 e terminal.sh é um script shell com o conteúdo a seguir:

#!/bin/bash
env DISPLAY=:1 /bin/bash ${HOME}/loop.sh

/bin/bash é o processo que receberá as instruções a serem executadas na exibição do PDF, e loop.sh é um script que será explicado no tópico abaixo

4. Inicialização do terminal remoto

O arquivo loop.sh possui o seguinte código:

#!/bin/bash

while :

do	mkfifo ${HOME}/pipe
	eval $(cat pipe)
	rm ${HOME}/pipe
done

Seu funcionamento é simples, ele cria um arquivo pipe para a troca de mensagens entre o terminal local (onde serão dados os comandos) e o remoto (executando em /dev/tty8).

Após a criação do arquivo o terminal remoto monitora o arquivo, a espera de alguma modificação a ser feita pelo terminal local. Quando o terminal local modifica o arquivo (com a adição de um comando), o terminal remoto toma como um comando o que foi escrito no arquivo pipe, e o executa. Após isso, ele exclui o arquivo e recria-o para a obtenção de um comando posterior.

5. Envio de comandos para o terminal remoto

Para o envio de comandos para o terminal remoto executa-se os scripts que serão descritos no próximo tópico.

Abrir um pdf
$ ./xpdf.sh slide.pdf &

Com o xpdf aberto e o terminal disponível para receber comandos (pois a abertura do xpdf é executada por outra instância do bash), é possível manipular a apresentação de slides, podendo passar para o próximo slide, com a execução do script a seguir, por exemplo:

Passar slide
$ ./nextPage.sh &

6. Finalizar execução do terminal remoto

Para finalizar a execução no virtual display basta escrever no arquivo pipe a instrução exit, que será interpretada como um comando pelo terminal remoto, como segue abaixo:

$ echo "exit" > ${HOME}/pipe

Antes de finalizar a sessão no shell deve-se garantir que as outras aplicações que executam remotamente (como o xpdf) tenham sido finalizadas!

Scrits dos Comandos

1. Abrir PDF

#!/bin/bash

echo "/bin/bash -c 'xpdf -fullscreen -remote servidor ${HOME}/$1 &'" > $HOME/pipe

Onde o comando /bin/bash refere-se a abrir uma nova instância do processo para executar a aplicação desejada (xpdf), e ${HOME}/$1 é o caminho referente ao pdf passado como parâmetro ($1) ao script.

2. Pular para próximo slide

#!/bin/bash

echo "/bin/bash -c 'xpdf.real -remote servidor -exec nextPage &'" > $HOME/pipe

3. Pular para slide anterior

#!/bin/bash

echo "/bin/bash -c 'xpdf.real -remote servidor -exec prevPage &'" > $HOME/pipe

4. Saltar slide

#!/bin/bash 

echo "/bin/bash -c 'xpdf.real -remote servidor -exec gotoPage\($1\) &'" > $HOME/pipe

5. Fechar Xpdf

#!/bin/bash

echo "/bin/bash -c 'xpdf.real -remote servidor -exec quit &'" > $HOME/pipe

Note que o comando xpdf.real é usado para manipular os slides, o parâmetro -remote servidor refere-se a sessão aberta.

Estudo da Raspberry Pi B+

Auto Login

Para realizar login automático basta editar o arquivo inittab em etc:

$ vim /etc/inittab

Comente a linha:

# 1:2345:respawn:/sbin/getty 115200 tty1

E insira logo abaixo da mesma:

1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1

Onde pi é o nome do usuário que deseja iniciar a sessão automaticamente.

Expansão do sistema de arquivos no SD

Algumas distribuições raspberry não utilizam completamente o espaço de armazenamento do cartão SD, havendo um espaço livre que pode ser "anexado" ao sistema de arquivos da distribuição. Para realizar a expansão há diversos procedimentos, mas a que destaca-se pela facilidade é a instalação do raspi-config, que possui comandos para configuração/personalização do sistema. Para a instalação da aplicação em um sistema derivado do Debian (como o Minibian), basta executar o seguinte comando:

$ apt-get install raspi-config

A ferramenta oferece opções de configuração referentes a idioma, interface do teclado, expansão do sistema de arquivos, gerenciamento da frequência do clock, entre outros.

Para expandir o sistema de arquivos basta apenas selecionar a opção Expand Filesystem e confirmar a operação.

O sistema também pode ser redimensionado utilizando um editor de partições, como o gparted

Instalação do Xorg

Para a instalação do Xorg basta executar o comando abaixo:

$ apt-get install xorg
Instalação do xpdf

Para a instalação do xpdf basta executar o comando abaixo:

$ apt-get install xpdf
Instalação do rsync

Para a instalação do Rsync basta executar o comando abaixo:

$ apt-get install rsync
Instalação do openssh-server

Para a instalação do openssh-server basta executar o comando abaixo:

$ apt-get install openssh-server
Instalação do python 2.7

Para instalação do python 2.7 basta executar o comando abaixo:

$ apt-get install python
Instalação do python pip

Para instalação do python pib basta executar o comando abaixo:

$ apt-get install python-pip
Instalação do crontab

O Crontab já está presente na distribuição utilizada (minibian), mas caso seja necessário instalar em algum sistema:

$ apt-get install cron
Criação de usuário

Para criar um usuário basta executar o comando:

$ adduser user

Onde user refere-se ao nome de usuário que deseja-se criar.

Utilizar internet na raspberry através de rede via Ubuntu
  • Cenário: Ubuntu conectado em rede Wireless, e raspberry não possui um roteador/ponto de rede para conexão.
  • Procedimento: Conectar o cabo de rede na porta ethernet da raspberry e do computador. Ir até a opção Edit Connections, no Network Manager do Ubuntu. Selecionar a rede que foi estabelecida na aba Wired, escolher a opção Edit e ir até a aba IpV4 Settings. Nesta aba, selecionar a opção Shared to Other Computers. Fechar a janela de configuração, e reiniar a raspberry, caso seja necessário.

API's de implementação

API Web-Service a ser implementado na Raspberry Pi B+

API Web-Service a ser implementado na Raspberry Pi B+
Método URI Parâmetros Retorno em Sucesso Retorno em Fracasso Descrição
@GET /projetar
-
[{"nome":"arquivo1.pdf","numeroPaginas":2},{"nome":"arquivo2.opt","numeroPaginas":33}]
[{'resultado': False}]
Retorna os arquivos aos quais o usuário tem acesso e informações sobre os mesmos
@GET /projetar/{arquivo}
 String nomeDoArquivo
[{'resultado': True}]
[{'resultado': False}]
Inicia a projeção do arquivo solicitado pelo usuário
@GET /projetar/{arquivo}/avancarProjecao
 String nomeDoArquivo
[{'resultado': True}]
[{'resultado': False}]
Faz a projeção da apresentação avançar um slide de arquivo
@GET /projetar/{arquivo}/retrocederProjecao
 String nomeDoArquivo
[{'resultado': True}]
[{'resultado': False}]
Faz a projeção da apresentação retroceder um slide de arquivo
@GET /projetar/{arquivo}/saltarProjecao/{numeroPagina}
 String nomeDoArquivo
int numeroPagina
[{'resultado': True}]
[{'resultado': False}]
Vai a uma determinada página de arquivo
@GET /projetar/{arquivo}/fechar
 String nomeDoArquivo
[{'resultado': True}]
[{'resultado': False}]
Fecha a apresentação de arquivo
@GET /projetar/{arquivo}/obterThumb/{thumb}
String nomeDoArquivo
int thumb
[{"thumb":arquivo-1.jpg}]
[{'resultado': False}]
Retorna um determinado thumb (identificado por thumb) referente ao arquivo
@GET /sincronizacao/forcaSincronizacao
-
[{'resultado': True}]
[{'resultado': False}]
Força uma sincronização com o servidor de arquivos
@GET /projetar/ligarProjetor
-
[{'resultado': True}]
[{'resultado': False}]
Liga o projetor
@GET /projetar/desligarProjetor
-
[{'resultado': True}]
[{'resultado': False}]
Desliga o projetor

API Web-Service a ser implementado no GUI

API Web-Service a ser implementado no GUI
Método URI Parâmetros Retorno (Json) Descrição
@POST /auth
 String usuario
 String senha
 boolean resposta
Caso seja possível criar o usúario, o servidor retorna a confirmação. Caso não mande os dados corretamente, retorna que não foi possível criar um usuário.
@POST /auth
 String usuario
 String senha
 boolean resposta
Retorna acesso permitido, caso os dados que o usuário tenha enviado, estiverem corretos, caso contrário acesso é negado.
@PUT /change_passwd
 String usuário
 String senha_atual
 String senha_nova
 boolean resposta
Retorna se foi possível alterar a senha do usuário, caso contrário a senha antiga permanece.
@POST /auth/{pasta}
 String nomeDaPasta
 int resposta
Caso seja possível criar a subpasta, então o servidor retorna uma confirmação, informando que a pasta foi criada. Caso contrário o servidor, avisa que não foi possível.
@DELETE /auth/{pasta}
 String nomeDoArquivo
 int resposta
Caso a pasta exista, então o servidor retorna uma confirmação, informando que a pasta foi excluida. Caso contrário o servidor, avisa que não foi possível.
@GET /arquivos/{user}
 String nomeDoUsuário
 Lista listaDeArquivos
Caso o usuário exista, então o servidor retorna uma lista com todos os arquivos do usuário. Caso contrário o servidor, avisa que não foi possível.
@POST /arquivos/{nome}
 String nomeDoArquivo
 int resposta
Caso seja possível fazer upload do arquivo, então o servidor retorna uma confirmação, informando que o arquivo foi colocado corretamente na pasta do usuário. Caso contrário o servidor, avisa que ocorreu um erro durante o upload do arquivo.
@DELETE /arquivos/{nome}
 String nomeDoArquivo
 int resposta
Se o arquivo existir, então o servidor retorna uma confirmação,informando que foi removido arquivo foi removido com sucesso. Caso contrário servidor, avisa que não foi possível.
@POST /agendamento/{user}/{nome}
 String sala
 String arquivo
 String dia
 String mes
 String ano
 String hora
 String minuto
 int resposta
Se o usuário informar corretamente: a sala, arquivo, data, então o servidor retorna uma confirmação, informando que foi feito com sucesso, caso contrário informa que não foi possível agendar a aula.
@DELETE /deletar/{user}
 String usuario
 String senha
 int resposta
Se for o próprio usuário que deseja se remover, então o servidor retorna uma confirmação, informando que foi removido com sucesso. Caso contrário servidor, avisa que não foi possível.

Implementação do Web Service na Raspberry

Instalação dos componentes necessários

1. Xpdf

Visualizador de PDF's.

 $ sudo apt-get install xpdf

2. Python

Linguagem de programação utilizada na implementação do web service.

 $ sudo apt-get install python

3. Python-pip

Gerenciador de extensões python.

 $ sudo apt-get install python-pip

4. Python-dev

Pacote python para desenvolvedores.

 $ sudo apt-get install python-dev

5. Framework Flask

Framework utilizado na implementação de web services.

 $ sudo pip install flask

6. Extensão HTTPAuth do Flask

Para autenticação via HTTP.

 $ sudo pip install flask-httpauth

7. Extensão netifaces para Python

Fornece informações sobre as interfaces de conexão.

 $ wget https://pypi.python.org/packages/source/n/netifaces/netifaces-0.10.4.tar.gz
$ tar xvzf netifaces-0.10.4.tar.gz
$ cd netifaces-0.10.4
$ python setup.py install

8. Extensão Cors do Flask

Devido a política de mesma origem (same origin policy), configurada como padrão nos servidores, qualquer requisição feita de diferentes domínios é bloqueada pelos navegadores, isto impede que ataques de Cross-domain sejam feitos. A habilitação da extensão CORS (cross-origin resource sharing) cria um caminho para que estas requisições sejam feitas de uma maneira mais segura, sem que todas as requisições deste tipo sejam habilitadas. Para habilitar os CORS é necessário primeiramente instalar a biblioteca para o suporte do CORS no servidor.

$ pip install -U flask-cors </syntaxhighlight>

Depois é necessário apenas a importação da biblioteca e inserir o código para habilitar o CORS nos recursos do servidor.

from flask.ext.cors import CORS

app = Flask(__name__)
cors = CORS(app)

9. Instalação do cec-utils, que utiliza a biblioteca libcec

Para envio de comandos para dispositivos conectados via HDMI

 sudo apt-get install cec-utils
Implementação do Web Service
  • Assume-se que o diretório dos usuários estará localizado no diretório do usuário root da raspberry (/root), e que no diretório de cada usuário haverá um diretório chamado thumbs, que conterá todas as miniaturas necessárias para exibição no dispositivo móvel.
#!/usr/bin/python
 
__author__ = "Matuzalem - Projeto Integrador II - Engenharia de Telecomunicacoes - Junho de 2015"
__date__ = "$11/06/2015 01:09:22$"
 
import sys
import netifaces # para capturar a interface do servidor automaticamente, caso insira manualmente o ip do servidor e descartavel, desde que comente as linhas de codigo equivalentes
from flask import Flask, jsonify
from flask import abort
from flask import make_response
from flask import request
from flask import url_for
from flask import send_file # enviar arquivos thumbs pela rede
from flask.ext.httpauth import HTTPBasicAuth
from flask.ext.cors import CORS # habilita troca de informacoes cross domain
auth = HTTPBasicAuth()
 
import subprocess
import os
 
app = Flask(__name__)
cors = CORS(app)

# Este servidor foi desenvolvido considerando a estrutura /root/User para o armazenamento de pdfs na raspberry
#####################[DEVE SER PREENCHIDO]############################
usuario = 'User' # usuario conectado a raspberry
interface='lo' # interface em que o servidor funcionara, para obter o ip automaticamente
porta=5000 # porta em que o servidor ouvira
######################################################################
caminho = "" # diretorio onde esta localizado o diretorio do usuario
pastaUsuario = "" # diretorio usuario
numeroPaginas="" # numero de paginas do arquivo
paginaAtual="" # pagina atual do arquivo

### Como listar arquivos em diretorio e seus subdiretorios ###
# curl -i http://localhost:5000/projetar
# Lista os arquivos do tipo pdf em /root/{usuario}/ e o numero de paginas de cada arquivo
@app.route('/projetar', methods=['GET'])
def obtem_arquivos():
    lista = []
    #https://docs.python.org/2/library/os.html
    for root, dirs, files in os.walk(caminho+usuario+'/'):
        for nome in files:
            if nome.endswith(".pdf"):
                path = os.path.join(root, nome)
                size = os.stat(path).st_size # in bytes
                linha = {}
                linha['numeroPaginas'] = subprocess.check_output("/usr/bin/pdfinfo "+path+" | grep -oP '(?<=Pages:          )[ A-Za-z0-9]*'", shell=True)[:-1] # [:-1] remove o ultimo elemento do vetor, no caso \n       
                linha['nome'] = nome
                lista.append(linha)
    return jsonify({'arquivos': lista}), 200
 
 
############################ Auxiliares ##############################
 
# verifica se um arquivo existe em um determinado diretorio
def verifica_existencia(diretorio, arquivo):
    if (os.path.exists(diretorio+arquivo) == True):
        return True
    else:
        return False
 
######################### Metodos do XPDF ############################
# curl -i http://localhost:5000/projetar/{arquivo.pdf}
# Abre um pdf
@app.route('/projetar/<arquivo>', methods=['GET'])
def abre_pdf(arquivo):
    # Chamada de processo nao bloqueante - fica em background
    local = pastaUsuario+arquivo
    if (verifica_existencia(pastaUsuario,arquivo) == True):
        p1 = os.spawnlp(os.P_NOWAIT,"xpdf","/usr/bin/xpdf","-fullscreen","-remote", arquivo, local)
        # /usr/bin/pdfinfo /root/User/arquivo.pdf | grep -oP '(?<=Pages:          )[ A-Za-z0-9]*'
        # verifica o numero de paginas do pdf
        global numeroPaginas
        global paginaAtual
        numeroPaginas = subprocess.check_output("/usr/bin/pdfinfo "+local+" | grep -oP '(?<=Pages:          )[ A-Za-z0-9]*'", shell=True)
        paginaAtual = 1
        return jsonify({'resultado': True}), 200
    else:
        print 'Usuario '+usuario+' tentou acessar o arquivo '+arquivo+' inexistente!'
        return jsonify({'resultado': False}), 404
 
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/avancarProjecao
# Avanca uma pagina
@app.route('/projetar/<arquivo>/avancarProjecao', methods=['GET'])
def avanca_pagina(arquivo):
    comando = 'nextPage'
    global paginaAtual
    if(int(paginaAtual) < int(numeroPaginas)):
        # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
        paginaAtual = paginaAtual + 1
        p = subprocess.call(['xpdf.real','-remote',arquivo,'-exec', comando])
        return jsonify({'resultado': True}), 200
    else:
        print 'Usuario '+usuario+' tentou acessar a pagina '+str(paginaAtual+1)+' do pdf '+pastaUsuario+arquivo+' inexistente!'
        return jsonify({'resultado': False}), 404
 
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/retrocederProjecao
# Retrocede uma pagina
@app.route('/projetar/<arquivo>/retrocederProjecao', methods=['GET'])
def retrocede_pagina(arquivo):
    if(int(paginaAtual) > 1):
        comando = 'prevPage'
        # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
        subprocess.call(['xpdf.real','-remote',arquivo,'-exec', comando])
        return jsonify({'resultado': True}), 200
    else:
        print 'Usuario '+usuario+' tentou acessar a pagina '+str(paginaAtual-1)+' do pdf '+pastaUsuario+arquivo+' inexistente!'
        return jsonify({'resultado': False}), 404
 
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/saltarProjecao/{numPagina}
# Avanca para uma pagina do pdf, se a pagina nao existir retorna um codigo de erro
@app.route('/projetar/<arquivo>/saltarProjecao/<int:pagina>', methods=['GET'])
def salta_paginas(arquivo,pagina):
    global paginaAtual
    if(pagina <= int(numeroPaginas) and (int(pagina) > 0)):
        comando = 'gotoPage('+str(pagina)+')'
        # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
        subprocess.call(['xpdf.real','-remote',arquivo,'-exec',comando])
        paginaAtual = pagina
        return jsonify({'resultado': True}), 200
    else:
        print 'Usuario '+usuario+' tentou acessar a pagina '+str(pagina)+' do pdf '+pastaUsuario+arquivo+' inexistente!'
        return jsonify({'resultado': False}), 404
 
 
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/fechar
# Fechar projecao
@app.route('/projetar/<arquivo>/fechar', methods=['GET'])
def fechar_projecao(arquivo):
    comando = 'quit'
    global paginaAtual
    global numeroPaginas
    paginaAtual = numeroPaginas = ""
    # chamada de processo bloqueante, porem o xpdf termina logo apos a execucao
    subprocess.call(['xpdf.real','-remote',arquivo,'-exec', comando])
    return jsonify({'resultado': True}), 200

###################### OBTEM THUMB ########################## 
 
# curl -i http://localhost:5000/projetar/{arquivo.pdf}/obterThumb/{thumb}
# Retorna um thumb do tipo jpg identificado por {arquivo}-{thumb}.jpg
@app.route('/projetar/<arquivo>/obterThumb/<int:thumb>', methods=['GET'])
def obter_thumb(arquivo, thumb):
    if((thumb < int(numeroPaginas)) & (thumb >= 0)):
        fileName, fileExtension = os.path.splitext(arquivo)
        caminhoArquivo = pastaUsuario+'thumbs/'+fileName+'-'+(str(thumb))+'.jpg'
        return send_file(caminhoArquivo, mimetype='image/jpg')
    else:
        caminhoArquivo = pastaUsuario+'thumbs/'+'erro.jpg'
        return send_file(caminhoArquivo, mimetype='image/jpg')

###########COMANDOS DE CONTROLE DE PROJECAO##################
############OS COMANDOS NAO ESTAO FUNCIONAIS########################## 
# curl -i http://localhost:5000/projetar/ligarProjetor
# Retrocede uma pagina
#@app.route('/projetar/ligarProjetor, methods=['GET'])
#def liga_projetor():
#        subprocess.call(['echo "standby 0" | cec-client -s'])
#        return jsonify({'resultado': True}), 200

# curl -i http://localhost:5000/projetar/desligarProjetor
# Retrocede uma pagina
#@app.route('/projetar/desligarProjetor, methods=['GET'])
#def desliga_projetor():
#        subprocess.call(['echo "on 0" | cec-client -s'])
#        return jsonify({'resultado': True}), 200
###############################################################

@app.errorhandler(404) ## Tratamento de erro
def not_found(error):
    return make_response(jsonify({'Erro': 'Recurso nao encontrado!'}), 404)

############################################################## 
 
if __name__ == "__main__":
    print "Servidor no ar!"
    caminho = os.path.expanduser('~')+'/' # obtem o diretorio do usuario do SO
    pastaUsuario = caminho+usuario+'/' # obtem o diretorio do usuario conectado (User)
    ip = netifaces.ifaddresses(interface)[2][0]['addr'] # obtem o ip referente a interface
    app.run(debug=True,host=ip,port=porta)
  • Considerando a instalação correta dos componentes e que o arquivo seja salvo com o nome servidor.py basta executar o web service com o comando:
 python servidor.py

Resultados obtidos na implementação do projeto

Nessa etapa final, cada integrante do grupo ficou responsável por uma parte do projeto. Sendo que as partes individuais da maioria funcionaram, mas tivemos alguns problemas na parte da integração. relataremos abaixo as partes do trabalho que funcionaram e as que tivemos problemas.

  • Obtivemos sucesso na parte de manipulação dos slides colocados na raspberry, nessa parte conseguíamos via uma aplicação no celular, avançar ou retroceder nos slides. Só tínhamos uma pequena demora na passagem, pelo fato da demora no processamento das imagens.
  • As partes das aplicações visualizadas pelo usuário, no website, funcionaram em partes:
    • Conseguimos fazer a autenticação dos usuários, porém não foi possível manter a conexão do usuário
    • A parte do Upload dos arquivos funcionou perfeitamente, porém como não conseguimos manter a conexão, tivemos que criar um usuário fictício, para assim colocarmos os arquivos na pasta desse usuário, só ressaltamos que não foi implementado a exclusão de arquivos, isso foi deixado para o ciclo 2, que seria para o projeto de ideias inovadoras
    • O agendamento dos arquivos foi feito a parte que estava descrita para ser realizada no ciclo 1 do projeto, mas também tivemos o mesmo problema com o usuário, descrito anteriormente
    • Tivemos um pequeno problema na hora que fomos tentar realizar o rsync com a raspberry, com isso alteramos o script para relializar a sincronização dos dados. Não foi possível testar a integração completa do sistema Webba devido a problemas técnicos ocorrido no momento. Porém, este mesmo projeto foi inscrito no projeto Ideias Inovadoras do IFSC, caso consiga passar para a etapa de desenvolvimento do projeto a meta da equipe será implementar todos os requisitos propostos previamente para o projeto e torná-lo um produto.