Escolar Documentos
Profissional Documentos
Cultura Documentos
SÃO PAULO
2021
2
SÃO PAULO
2021
3
Aprovado em:
BANCA EXAMINADORA
AGRADECIMENTOS
Agradecemos a Deus, pela vida que me deu, e por seu infinito amor.
A todos nossos familiares que nos apoiaram nesta empreitada, pela sua
paciência e compreensão nas horas em que estivemos ausentes desenvolvendo este
trabalho.
Ao professores Álvaro Prado e Miryam de Moraes, por seus ensinamentos e
pelo apoio para nos podermos concluir todos os trabalhos, especialmente esta
monografia.
Aos colegas de curso, pela amizade, companheirismo e colaboração recebidos
durante o curso. E aos demais colegas que de alguma forma contribuição em diversos
trabalhos.
5
RESUMO
ABSTRACT
Although there are several websites and NGOs that help in locating animals,
often in large cities it is very difficult to retrieve the pet. The solutions usually adopted
are to stay several days to locate the animal and often the search is unsuccessful.
The present work presents the development of a location application for tracking
pets, with the aim of facilitating the search for animals through a mobile device. The
project was divided into two parts, the first in the construction of the collar for the use
of the animal, and the second refers to the creation of a mobile application for
monitoring and locating the animal through the data transmitted by the collar.
LISTA DE ILUSTRAÇÃO
LISTA DE TABELAS
SUMÁRIO
1 INTRODUÇÃO .................................................................................................... 13
1.1 Contextualização ............................................................................................. 13
1.1.1 Problema ...................................................................................................... 13
1.1.2 Hipótese........................................................................................................ 13
1.2 Motivação ........................................................................................................ 13
1.3 Justificativa ...................................................................................................... 14
1.4 Objetivos .......................................................................................................... 16
1.4.1 Objetivos Gerais ........................................................................................... 16
1.4.2 Objetivos Específicos.................................................................................... 16
1.5 Procedimentos Metodológicos ......................................................................... 16
2 REFERENCIAL TEÓRICO ................................................................................. 18
2.1 UML (Unified Modeling Language) .................................................................. 18
2.1.1 Itens estruturais ............................................................................................ 19
2.1.2 Itens comportamentais.................................................................................. 19
2.2 Java ................................................................................................................. 23
2.2.1 Orientação a objetos ..................................................................................... 25
2.2.1.1 Objeto ........................................................................................................ 26
2.2.1.2 Classe ........................................................................................................ 27
2.2.1.3 Herança ..................................................................................................... 27
2.3 Jpa ................................................................................................................... 28
2.3.1 Orm ............................................................................................................... 28
2.3.2 Anotações da JPA. ....................................................................................... 28
2.4 Spring .............................................................................................................. 30
2.5 Computação em Nuvem .................................................................................. 31
2.5.1 Nuvem pública .............................................................................................. 32
2.5.2 Nuvem privada .............................................................................................. 33
2.4.3 Nuvem híbrida .............................................................................................. 33
2.5 Scrum .............................................................................................................. 34
2.6 Kanban ............................................................................................................ 36
11
1 INTRODUÇÃO
1.1 Contextualização
1.1.1 Problema
No ponto de vista do desenvolvimento a viabilidade e a exequibilidade, contribui
para projetar um sistema e equipamentos de rastreio, com objetivo de fornecer uma
localização do cachorro doméstico, e diminuir as chances de desaparecimento, e em
último caso para evitar um problema, ajuda a resgatar o animal de estimação perdido.
1.1.2 Hipótese
No item de exequibilidade, é buscado compreender quais dificuldades práticas
enfrentadas para projetar e desenvolver a solução proposta enquanto na viabilidade
busca-se delimitar a eficiência operativa da solução.
Apesar do grande avanço teórico no que concerne a quais melhores práticas e
métodos para o desenvolvimento de soluções informáticas, há problemas de
aprendizado e adaptabilidade, dado a renovação constante nas preferências
majoritárias, quanto a utilização otimizada de ferramentas emergentes.
Outro ponto a salientar se deve quanto à disponibilidade que a solução irá
ofertar dado que sistemas distribuídos pervasivos não possuem estabilidade dado a
sua característica e necessidade de se adequar a ambientes não otimizados.
Por fim, temos expectativas quanto ao volume de dados, os quais, ao extrapolar
a solução para milhares de pessoas, criaria um volume de dados difícil de administrar,
possuindo potencial de afetar sua viabilidade.
1.2 Motivação
Animais de estimação perdidos não encontrados por seus responsáveis são
um importante fator de contribuição para as populações de animais de estimação
desabrigados, selvagens, abrigos e vadios. Até recentemente, os tutores ficavam por
conta própria com o mínimo de conselhos e nenhuma assistência prática para ajudá-
los a recuperar um animal de estimação perdido. Saber o que fazer nas primeiras 24
14
1.3 Justificativa
As estatísticas de animais perdidos aumentam a cada ano. Com isso, a
organização American Society for the Prevention of Cruelty to Animals (ASPCA)
realizou uma pesquisa com um grupo de donos de animais a respeito de seus animais
de estimação perdidos. No estudo, os pesquisadores coletaram dados sobre quantas
vezes os animais de estimação se perdem de suas casas, a porcentagem de animais
que foram recuperados e, provavelmente, os dados mais importantes que existem: os
métodos que os proprietários usaram para encontrar seus cães ou gatos perdidos.
Havia 1.015 participantes, e todos eles tiveram um cachorro ou gato de estimação nos
últimos cinco anos. De acordo com os participantes, cerca de 14% dos cães e 15%
dos gatos sumiram pelo menos uma vez nos últimos cinco anos. E desse número de
animais perdidos, 93% dos cães e 75% dos gatos foram recuperados. Isso significa
que 7% dos cães e 25% dos gatos nunca foram encontrados. (WEISS, 2012)
De acordo com estatísticas de animais perdidos divulgadas pela ASPCA,
existem 86,4 milhões de gatos e 78,2 milhões de cães nos Estados Unidos. Com base
nas estatísticas acima, o número de animais perdidos que acabam em abrigos todos
os anos é de 5 a 7 milhões.
Existem várias soluções possíveis para esses casos, que resultam no
reencontro dos donos com seus animais de estimação, como animais que são
encontrados na vizinhança, alguns voltam para casa por conta própria e outros foram
devolvidos graças a etiquetas de identificação/coleiras ou microchips.
15
1.4 Objetivos
1.4.1 Objetivos Gerais
Partindo do princípio de que o assunto é desaparecimento de animais de
estimação, a aplicação tem por objetivo facilitar a recuperação ou evitar que os
animais se percam de seus donos com um dispositivo de rastreio. O sistema emprega
a técnica de geolocalização, onde é possível encontrar no mapa a localização do
animal em tempo real. Possibilitando ser possível centralizar todas as informações em
uma única aplicação.
2 REFERENCIAL TEÓRICO
2.1 UML (Unified Modeling Language)
Segundo (Booch, Rumbaugh, & Jacobson, 2012), a UML (Unified Modeling
Language) é uma linguagem-padrão para a elaboração da estrutura de projetos e
software. Essa linguagem tem como intuito ser empregada para a visualização, a
especificação, a construção e a documentação de artefatos que fazem uso de
sistemas complexos de software.
Essa linguagem é pertinente para modelagem de software, demonstrada
através de diagramas, independentemente da finalidade e complexidade dos
sistemas. Possivelmente, o uso mais comum para criar modelos de sistema de
software, contudo é bastante utilizada também para representar qualquer outro
domínio como telecomunicações, transportes, serviços bancários e financeiros que
não esteja relacionado com software.
Não obstante, a UML não está restrita à modelagem de software. De fato, a
UML é totalmente importante para modelar sistemas que não sejam de software, como
o fluxo de trabalho no sistema legal, a estrutura e o comportamento de sistema de
saúde e o projeto de software. (Booch, Rumbaugh, & Jacobson, 2012)
(Booch, Rumbaugh, & Jacobson, 2012), ainda destaca que a UML é apenas
uma linguagem, portanto, é somente uma parte de um método para desenvolvimento
de software. A UML é independente do processo de software, podendo ser
perfeitamente utilizada em processo orientado a casos de uso, centrado na
arquitetura, iterativo e incremental.
O UML é composto por três tipos de blocos de construção, sendo eles os itens,
relacionamentos e diagramas. Os itens são abstrações como cidadãos de primeira
classe em um modelo; os relacionamentos reúnem esses itens; os diagramas
agrupam coleções de itens. (Booch, Rumbaugh, & Jacobson, 2012)
Dentro do bloco de construção do UML existem quatro tipos de itens, sendo
eles:
1. Itens estruturais
2. Itens comportamentais
3. Itens de agrupamentos
4. Itens anotacionais
19
2.2 Java
O Java é uma linguagem de programação de alto nível que utiliza o paradigma
de orientação a objetos, desenvolvida para sanar as necessidades do
24
uma grande relevância em comparativo com as outras linguagens por ser útil e
eficiente, podendo proporcionar funções necessárias para o desenvolvimento de
diversos tipos de aplicações.
2.2.1.1 Objeto
Objeto é uma abstração encapsulada que tem um estado interno dado por uma
lista de atributos cujos valores são únicos para o objeto. O objeto também conhece
uma lista de mensagens que ele pode responder e sabe como responder cada uma.
Um objeto ou instância é uma materialização da classe, sendo assim pode ser
utilizado para representar dados e executar operações. (Claro & Sobral, 2008)
É possível perceber através da figura 15, uma caneta é um objeto da classe
“ClasseCaneta”, que possui atributos e métodos específicos vinculados a ele. No caso
abaixo, os atributos são: modelo, cor, ponta, carga e tampada. Já os métodos
expostos para a chamada no objeto são: escrever, rabiscar, pintar, tampar e
destampar.
2.2.1.2 Classe
Segundo (Sintes, 2002), uma classe define todas as características comuns a
um tipo de objeto. Especificamente, a classe define todos os atributos e
comportamentos expostos pelo objeto. Como por exemplo, cachorro, aranha e galo
podem ser todos considerados classes herdadas de animais, mas diferenciam-se em
alguns atributos como tamanho, patas e espécies, podendo assim serem classificados
como parte de uma mesma classe superior.
2.2.1.3 Herança
A herança é um mecanismo onde permite que você possa espelhar uma nova
classe na definição de uma classe existente. Segundo (Sintes, 2002), usando a
herança, sua nova classe herda todos os atributos e comportamentos presentes na
classe previamente existente. Quando uma classe herda todos os atributos que
aparecem na interface da classe previamente existente aparecerão automaticamente
na interface da nova classe.
Através da FIGURA 16, um exemplo de herança onde as classes cachorro e
gato são herdadas de uma classe mamíferos, onde terão as mesmas características
como a presença de pelos, glândulas mamárias, diafragma e dentes diferenciados
que são características exclusivas dos mamíferos.
2.3 Jpa
2.3.1 Orm
“[...] é uma técnica de programação para conversão do modelo relacional para
o modelo orientado a objetos” (FARIA; AFONSO, 2020, p. 12).
Em banco de dados, as tabelas representam as entidades cujas propriedades
são armazenadas por suas colunas. Uma tabela pode se associar com outras e criar
diversos relacionamentos. Já em linguagens orientada a objetos, como Java,
entidades são classes, e objetos dessas classes representam elementos que existem
no mundo real (FARIA; AFONSO, 2020, p. 13).
Para a conversão ocorrer um mapeamento na classe usando metadados que
relacionam a classe com o modelo relacional do banco é necessário. As operações
CRUD (Create, Read, Update and Delete) são oferecidas pelo ORM através de sua
API apoiadas no relacionamento previamente criado. Os comandos SQL são gerados
durante o uso da API (FARIA; AFONSO, 2020, p. 12-13).
2.4 Spring
O Spring é um framework Java, criado com o objetivo de facilitar o
desenvolvimento de aplicações, Segundo (WALLS & Breidenbach, 2008).
a execução de serviços que não são necessariamente exigidos pela empresa, sendo
assim, que podem ser repassados para uma empresa terceira, hospedada em uma
nuvem pública e mantendo os principais aplicativos e dados confidenciais
armazenados internamente em uma nuvem privada. (Mather, Kumaraswamy, & Latif,
2009).
2.5 Scrum
Scrum é uma forma ágil de gerenciar um projeto, geralmente o
desenvolvimento de software. O desenvolvimento ágil de software com Scrum é
frequentemente percebido como uma metodologia/uma estrutura para gerenciar um
processo. (ABRAHAMSSON, 2002)
Em vez de fornecer descrições completas e detalhadas de como tudo deve ser
feito em um projeto, muito disso é deixado para a equipe de desenvolvimento de
software Scrum. Isso ocorre porque a equipe saberá melhor como resolver o problema
que lhes é apresentado. (ALMEIDA, 2019)
35
No final de uma sprint, a equipe conduz uma revisão de sprint durante a qual a
equipe demonstra a nova funcionalidade para o product owner ou qualquer outra parte
interessada que deseja fornecer feedback que possa influenciar a próxima sprint. Este
ciclo de feedback dentro do desenvolvimento do software Scrum pode resultar em
mudanças na funcionalidade recém-entregue, mas também pode resultar na revisão
ou adição de itens ao backlog do produto. (ALMEIDA, 2019)
Outra atividade no gerenciamento de projetos Scrum é a retrospectiva da sprint
ao final de cada sprint. Toda a equipe participa dessa reunião, incluindo o
ScrumMaster e o PO. A reunião é uma oportunidade para refletir sobre a sprint
encerrado e identificar oportunidades de melhoria.
O principal artefato no desenvolvimento do Scrum é, obviamente, o próprio
produto. O modelo Scrum espera que a equipe traga o produto ou sistema a um estado
potencialmente entregável ao final de cada sprint. O 'backlog' do produto é outro
artefato do Scrum. Esta é a lista completa das funcionalidades que ainda precisam ser
adicionadas ao produto. O product owner prioriza o backlog para que a equipe sempre
trabalhe nos recursos mais valiosos primeiros. (ALMEIDA, 2019)
2.6 Kanban
O método Kanban é um meio de projetar, gerenciar e melhorar os sistemas de
fluxo para o trabalho do conhecimento. O método também permite que as
organizações comecem com seu fluxo de trabalho existente e conduzam mudanças
evolutivas. Eles podem fazer isso visualizando seu fluxo de trabalho, limitar o trabalho
em andamento e interromper o início e começar a terminar. (SERENO, 2011)
Kanban é uma metodologia ágil que não é necessariamente iterativa.
Processos como Scrum têm iterações curtas que imitam o ciclo de vida de um projeto
em pequena escala, tendo um início e um fim distintos para cada iteração voltado para
a entrega just-in-time para evitar sobrecarga da equipe. Kanban permite que o
software seja desenvolvido em um grande ciclo de desenvolvimento. (JUNIOR, 2008)
O princípio por trás do Kanban, que permite que ele seja incremental e ágil, é
o rendimento limitado. Sem iterações, um projeto Kanban não tem pontos de início ou
término definidos para itens de trabalho individuais; cada um pode começar e terminar
independentemente um do outro, e os itens de trabalho não têm duração
predeterminada para esse assunto. Em vez disso, cada fase do ciclo de vida é
37
2.7 Mvp
Um produto mínimo viável (MVP) é um conceito que enfatiza o impacto do
aprendizado no desenvolvimento de novos produtos. Essa metodologia é bastante
popular no mundo do desenvolvimento de software. Ele pressupõe a divisão do projeto
em partes menores chamadas iterações. O resultado de cada iteração é um software
funcional que permite coletar o feedback, analisá-lo e seguir em frente. Este termo
significa simplesmente: a coisa com o mínimo de recursos que você pode construir
que irá abordar a oportunidade bem o suficiente para a maioria de seus clientes-alvo
e validar seu mercado e produto. (FARIA, 2017)
Com essa abordagem, você constrói a coisa mais simples possível, reúne
dados sobre como os clientes os usam e, em seguida, refina o produto, se necessário.
Isso permitirá que você trabalhe com bastante eficácia, criando apenas os recursos
que os clientes desejam e usarão, em vez de perder tempo criando coisas com as
quais os clientes não se importam. (FARIA, 2017)
38
se concentrar em tarefas básicas, como tipos de objetivos que seus usuários finais
têm quando usam seu produto, suas expectativas, etc. Depois de definir o fluxo do
usuário, você pode passar para o wireframing, que é simplesmente uma ilustração de
uma página da web ou de um aplicativo. Um wireframe é um layout que articula que
tipo de elementos de interface encontrarão um lugar em páginas importantes.
(FERENTZ, 2021)
Passando para o estágio de desenvolvimento, você precisa testar seu produto
e trabalhar para melhorar sua qualidade. Após a aprovação dos Wireframes, você
deve começar a trabalhar na arquitetura de configuração, banco de dados e começar
a desenvolver API e todo o back-end. (FARIA, 2017)
Quando um produto que está pronto para o mercado, é necessário fazer testes
beta abertos ou fechados, onde convidamos usuários relevantes para o programa de
teste beta e coletamos feedback sobre funcionalidades e bugs. (FARIA, 2017)
Como o aplicativo está recebendo mais usuários, alguns bugs podem aparecer
e temos a certeza de consertar tudo o mais rápido possível. Normalmente, lançamos
novas compilações a cada dois dias. Depois que o aplicativo estiver estável e tivermos
uma taxa de usuários sem falhas de mais de 99,9%, poderá começar com o marketing
para adquirir mais usuários. (FERENTZ, 2021)
2.8 Okr
Os OKRs podem trabalhar em qualquer nível, do corporativo ao individual. Os
níveis mais altos são avaliados uma vez por ano, enquanto os grupos menores podem
ser avaliados com mais frequência. As notas são baseadas em um resultado (como
lucratividade), em uma escala de 0 a 1, em que 1 é o cumprimento de 100% da meta
para o período. (SANTANA, 2019)
Essas metas se propagam desde a visão da empresa até a forma como as
equipes apoiam essa visão. Isso é chamado de cascata porque esses objetivos são
negociados. Os departamentos podem propor uma medição diferente ou um objetivo
diferente. Isso significa que uma equipe pode ser dona de suas metas e planos.
(SANTANA, 2019)
Estar alinhado e garantir que sua equipe esteja avançando na mesma direção
não é uma tarefa fácil. Os números falam por si - apenas 41% dos funcionários sabem
o que sua organização representa e apenas 38% dos trabalhadores se sentem
40
2.9 Arduino
O Arduino é uma plataforma de hardware open source, projetada sobre o
microcontrolador Atmel AVR, que pode ser utilizado para programar através de uma
linguagem de programação similar a C/C++, permitindo a elaboração de projetos com
um conhecimento mínimo ou mesmo nenhum de eletrônica, com isso, foi criado com
o objetivo de fornecer uma plataforma de fácil prototipação de projetos interativos,
unindo software e hardware, com as características da Computação Física. Visto que,
a Computação Física é uma área da Computação na qual o software se comunica
diretamente com o hardware, podendo controlar componentes eletrônicos, como
sensores e atuadores, permitindo construir sistemas que consigam perceber e
interagir com ambientes reais. (ZANETTI, 2015)
A placa Arduino é muito similar à de um computador de pequeno porte, sendo
composto por um microcontrolador, memória RAM, armazenamento secundário
(memória flash) e clock, entre outras funcionalidades. Na placa do Arduino, temos o
modelo Uno, que é um dos modelos mais vendidos e bastante indicado para os
iniciantes na plataforma. Este modelo apresenta 14 pinos que podem ser utilizados
como entradas ou saídas digitais (pinos 1 a 14), e os pinos 3, 5, 6, 9, 10 e 11 podem
42
ser utilizados para gerar um conjunto de valores inteiros entre 0 e 1.023 pela técnica
de Pulse Width Modulation (PWM), os pinos A0 a A5 correspondem as entradas
analógicas, enquanto os 3, 3 V, 5V e GND (Terra) permitem alimentar os componentes
dos circuitos conectados ao Arduino. Possui um microprocessador ATmega328, com
uma memória RAM de 2 KB, memória Flash de 32 KB e velocidade de clock de 16
MHz. (ZANETTI, 2015)
“No entanto, não fornece meios explícitos para lidar com estado [de dados] na
visão, (item) que não faz parte do modelo” (SYROMIATNIKOV; WEYNS, 2014, p. 24).
Isso culmina em “uma lógica de estado de visão inadequada” (SYROMIATNIKOV;
WEYNS, 2014, p. 30).
O termo Internet das Coisas (Internet of Things) tem por volta de 22 anos. Mas
a ideia real de dispositivos conectados já existia há mais tempo, pelo menos desde os
anos 70. Naquela época, a ideia era frequentemente chamada de “internet
incorporada” ou “computação pervasiva”. Mas o termo real “Internet das Coisas” foi
criado por Kevin Ashton em 1999 durante seu trabalho na Procter & Gamble. Ashton,
que trabalhava na otimização da cadeia de suprimentos, queria atrair a atenção da
gerência sênior para uma nova tecnologia interessante chamada RFID. Como a
internet era a nova tendência mais quente em 1999 e de alguma forma fazia sentido,
ele chamou sua apresentação de “Internet das Coisas”. Embora Kevin tenha
despertado o interesse de alguns executivos da P&G, o termo Internet das Coisas não
recebeu grande atenção nos 10 anos seguintes. (SANTOS, 2018)
Segundo Neil Gross, no próximo século, o planeta Terra vestirá uma “pele”
eletrônica. Ele usará a Internet como um andaime para apoiar e transmitir suas
sensações. Essa pele já está sendo costurada. É composta por milhões de
dispositivos de medição eletrônicos embutidos: termostatos, medidores de pressão,
detectores de poluição, câmeras, microfones, sensores de glicose, EKGs,
eletroencefalógrafos. Eles sondarão e monitorarão cidades e espécies ameaçadas de
extinção, a atmosfera, nossos navios, rodovias e frotas de caminhões, nossas
conversas, nossos corpos - até mesmo nossos sonhos. (GROSS, 1999)
No ano de 2013, a Internet das Coisas evoluiu para um sistema que usa várias
tecnologias, que vão desde a Internet à comunicação sem fio e de sistemas
microeletromecânicos (MEMS) a sistemas embarcados. Os campos tradicionais de
automação (incluindo a automação de edifícios e residências), redes de sensores sem
fio, GPS, sistemas de controle e outros, todos suportam a IoT. Em termos simples, a
Internet das Coisas consiste em qualquer dispositivo com um botão liga / desliga
conectado à Internet. Isso inclui quase tudo que você possa imaginar, desde telefones
celulares até manutenção de prédios e motores a jato de um avião. (TEIXEIRA, 2018)
Os Dispositivos médicos, pode ajudar com um implante de monitor cardíaco ou
um transponder biochip em um animal de fazenda, podem transferir dados por meio
de uma rede e são membros da IoT. Se tiver um botão liga / desliga, pode,
teoricamente, fazer parte do sistema. A IoT consiste em uma rede gigantesca de
“coisas” e dispositivos conectados à Internet. Ring, uma campainha com link para seu
smartphone, é um excelente exemplo de uma adição recente à Internet das Coisas.
50
O toque avisa quando a campainha é pressionada e permite que você veja quem é e
fale com eles. (TEIXEIRA, 2018)
3 COMPOSIÇÃO DO PROJETO
3.1 Ferramentas
3.1.1 Ec2 (aws)
Uma instância EC2 é um servidor virtual no Elastic Compute Cloud (EC2) da
Amazon para a execução de aplicativos na infraestrutura Amazon Web Services
(AWS). AWS é uma plataforma de computação em nuvem abrangente e em evolução;
EC2 é um serviço que permite que assinantes comerciais executem programas de
aplicativos no ambiente de computação. Ele pode servir como um conjunto
praticamente ilimitado de máquinas virtuais (VMs). (AWS Amazon)
52
3.1.3 Spring
O Spring é um framework Java, criado com o objetivo de facilitar o
desenvolvimento de aplicações. (TREINAWEB)
O Spring é um framework de código aberto criado por Rod Johnson. Foi criado
para lidar com a complexidade de desenvolvimento de aplicativos corporativos. O
Spring torna possível usar simples JavaBeans para conseguir coisas que só eram
possíveis com EJBs. Porém, a utilidade do Spring não é limitada ao desenvolvimento
do lado servidor. Qualquer aplicativo Java pode se beneficiar do Spring em termos de
simplicidade, testabilidade e baixo acoplamento. Spring fornece muitas
funcionalidades de estrutura como gerenciamento de transações, integração de
frameworks de persistências de objetos, e é considerado um container que gerencia
o ciclo de vida e a configuração de objetos do aplicativo. (TREINAWEB)
A utilização do Spring traz um ganho considerável com relação a qualidade de
software em termos de design patterns. (TREINAWEB)
3.1.6 Postman
Postman é um aplicativo usado para teste de API. É um cliente HTTP que testa
requisições HTTP, utilizando uma interface gráfica de usuário, através da qual
obtemos diferentes tipos de respostas que precisam ser posteriormente validadas.
Torna mais fácil para os desenvolvedores criar, compartilhar, testar e documentar
APIs. Isso é feito permitindo que os usuários criem e salvem solicitações HTTP’s
simples e complexas, bem como leiam suas respostas. (CIELO)
Postman oferece a possibilidade de agrupar diferentes pedidos. Esse recurso
é conhecido como ‘coleções’ e ajuda a organizar os testes. (CIELO)
Essas coleções são pastas onde as solicitações são armazenadas e podem ser
estruturadas da maneira que a equipe preferir. Também é possível exportar-importar.
55
3.1.7 Git
Git é um sistema de controle de versão distribuída de código aberto. É uma
ferramenta DevOps usada para gerenciamento de código-fonte. É um sistema de
controle de versão gratuito e de código aberto usado para lidar com projetos pequenos
a muito grandes com eficiência. Git é usado para rastrear alterações no código-fonte,
permitindo que vários desenvolvedores trabalhem juntos no desenvolvimento não
linear. (BETRYBE)
Pode ser um sistema de controle, significa que o Git é um rastreador de
conteúdo. Portanto, o Git pode ser usado para armazenar conteúdo - ele é usado
principalmente para armazenar código devido aos outros recursos que fornece.
(BETRYBE)
Também pode ser um sistema de controle de versão, o código armazenado no
Git muda continuamente à medida que mais código é adicionado. Além disso, muitos
desenvolvedores podem adicionar código em paralelo. Portanto, o Sistema de
Controle de Versão ajuda a lidar com isso, mantendo um histórico das mudanças que
aconteceram. Além disso, o Git fornece recursos como branches e merges, que
abordarei mais tarde. (BETRYBE)
E por fim, pode ser um sistema de controle de versão distribuída, o Git possui
um repositório remoto que fica armazenado em um servidor e um repositório local que
fica armazenado no computador de cada desenvolvedor. Isso significa que o código
não é apenas armazenado em um servidor central, mas a cópia completa do código
está presente em todos os computadores dos desenvolvedores. (BETRYBE)
3.1.8 Github
GitHub é uma interface baseada na web que usa Git, o software de controle de
versão de código aberto que permite que várias pessoas façam alterações separadas
em páginas da web ao mesmo tempo. Incentiva as equipes a trabalharem juntas para
construir e editar o conteúdo do site. (HOSTINGER)
56
3.1.9 Fritzing
Fritzing é um simulador de circuitos eletrônicos digitais com iniciativa de
hardware de código aberto que torna a eletrônica acessível como um material criativo.
Este software permite que sejam criados layouts de circuitos eletrônicos de maneira
simples e rápida. Estes layouts permitem a documentação dos esquemáticos por
pesquisadores, designers, artistas e hobbistas. (Fritizing)
O Fritzing foi utilizado para implantação do sistema, que permitiu a montagem,
prototipação e visualização dos componentes antes mesmo de ser construído o
circuito físico, garantindo maior segurança e direcionamento para prototipação.
3.2 Materiais
3.2.1 Arduino
Dentre as várias opções de modelos da placa open source, foi escolhido o
modelo Arduino Nano por ser uma placa controladora de pequenas dimensões,
específica para atender a proposta do projeto de ser um dispositivo discreto.
Pela razão acima que se deu fundamentalmente o uso do Arduino Nano mas
além disso, a sua acessibilidade e a facilidade que se tem ao utilizar sua IDE para a
programação foi um fator de peso para sua aplicação.
Esse módulo foi escolhido para ser conectado no Arduino, com o intuito de
inserir um chip de operadora de telefonia móvel, com a necessidade de obter sinal de
internet e transmitir os dados de localização para a aplicação com uma possibilidade
maior de sempre manter o componente conectado com a internet.
Características gerais
• Peso: 1,3g
3.4 Métodos
3.4.1 Construção Do Software
Para atender os requisitos anteriormente apresentados foram modelados dois
diagramas gerais que possuem por objetivo nortear o desenvolvimento futuro do
projeto. São eles os diagramas de casos de uso e o de classe.
66
4 PLANO DE TESTABILIDADE
Os modelos de testes utilizados foram os de caixa branca e de caixa preta,
sendo duas interpelações de testes da aplicação, validando tanto a parte interna da
aplicação (como a codificação por exemplo), quanto a parte externa (como a
perspectiva final do usuário).
1. Teste de retorno para quando o usuário já for existente, se sim, qual será a
mensagem de retorno para o usuário;
5 TESTES E RESULTADOS
Os testes foram realizados em ambiente fechado, com estrutura e ferramentas
adequadas para evitar qualquer tipo de dano físico, com relação aos participantes e
aos materiais.
Devido a Pandemia do Covid-19, não foi possível que todos os integrantes
estivessem presentes em todos os testes, mas o compromisso na maioria das vezes
foi honrado. Nos momentos em que os testes não foram realizados fisicamente,
utilizamos o Zoom para fazer as validações possíveis.
77
Porém o teste (que seria o final) feito no dia 07/10, realizado com o GSM, houve
uma identificação da operadora que os dados móveis foram utilizados indevidamente,
e o IMEI acabou sendo bloqueado. Esse problema resultou em um atraso parcial na
finalização do protótipo, pois tivemos que buscar novos recursos para recomeçar o
hardware.
6 CONCLUSÃO
Dada à importância do assunto, o desenvolvimento do presente estudo
possibilitou uma análise de como a junção de um software e um hardware podem
melhorar a capacidade de localizar imediatamente seu animal de estimação no caso
de ele se afastar de você ou se perder, além de poder economizar nos custos pela
procura do animal. Nesse sentido, a utilização de recursos digitais é muito importante
para evitar complicações com os pets e até para soluções pensando nas piores
possibilidades, visto que essas situações influenciam diretamente nos sentimentos e
nos comportamentos dos seres humanos, além de preservar o bem-estar dos animais.
O sistema tratado neste trabalho tem como objetivo priorizar a segurança de
animais usando a tecnologia para auxiliar nessa difícil missão, tendo em vista a
quantidade alta de animais que acabam se perdendo de seus donos ou que são
roubados em alguns casos. já que a maioria das pessoas tem uma relação sentimental
muito forte com seus animais, e qualquer coisa que possa acontecer com eles, pode
acabar afetando na vida daquela pessoa, então se for possível, é necessário tentar
evitar a perca desses animais de estimação, para que as pessoas tenham uma
expectativa de qualidade de vida melhor, juntos com os seus animais.
Além disso, o dispositivo de rastreio apresenta o desenvolvimento de um
sistema de geolocalização que acompanha a localização dos animais de estimação,
e traz o objetivo de localizar o animal, através de um dispositivo em que o protótipo foi
segmentado em duas partes, que engloba o Arduino em sua composição de hardware
e Software que engloba linguagem Java, em que contribuiu na construção do sistema
para localizar os animais. Nessa situação, a aplicação utilizada por diversos
conhecimentos sendo eles teóricos e tecnológicos obtidos no curso de ciência da
computação, trouxe também para o projeto uma experiencia bastante satisfatória,
para a equipe envolvida, e as diferentes disciplinas que estudamos como modelagem
de dados, programação, banco de dados e engenharia de software, contribuiu em
diversos pontos da construção protótipo.
80
7 REFERÊNCIA BIBLIOGRÁFICA
ALLEN, Daniel; Peacock, Adam; Arathoon, Jamie. Spatialities of Dog Theft: A Critical
Perspective. Animals, v. 9, n. 5, p. 209. https://doi.org/10.3390/ani9050209
BETRYBE. Git: o que é, para que serve e principais comandos Git. Disponível em: <
https://blog.betrybe.com/git/>. Acesso em: 31 de outubro de 2021
FARIA, Thiago; AFONSO, Alexandre. JPA - Guia Definitivo. ed. 2, 2020. Disponível
em:http://alga.works/livro-jpa
GROSS, Neil. 14: The Earth Will Don an Electronic Skin. 1999. Bloomberg.
Disponível em: https://www.bloomberg.com/news/articles/1999-08-29/14-the-
earth-will-don-an-electronic-skin. Último acesso: 26 de maio de 2021
83
KUMAR, Santosh; SINGH, Sanjay K. Monitoring of pet animal in smart cities using
animal biometrics. Future Generation Computer Systems, v. 83, p. 553-563, jun.
2018.
STORER, Rhi. Stolen dogs in mugshot line-up as police try to locate owners.
2021. Disponível em: https://www.theguardian.com/uk-news/2021/apr/20/stolen-
dogs-in-uk- mugshot-line-up-as-police-try-to-locate-owners. Acesso em: 23 de abril
de 2021.
VERAS, Manoel. Cloud Computing: Nova Arquitetura da TI. Brasport., 2012. ISBN:
9788574525327
WEISS, Emily. How many pets are lost? How many find their way home? 2012.
Disponível em: https://www.aspca.org/about-us/press-releases/how-many-pets-
are-lost- how-many-find-their-way-home-aspca-survey-has-answers. Acesso em:
17 de abril de 2021.
ZHANG, Cheng; Budgen, David. What do we know about the effectiveness of software
design patterns?. Transactions on Software Engineering. vol 38. n. 5. p. 1213-31.
setembro/outubro 2012. https://doi.org/10.1109/TSE.2011.79
87
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PetFinderApplication {
/petFinder/src/main/java/com/lino4000/petFinder/model/User.java
package com.lino4000.petFinder.model;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonManagedReference;
88
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@Builder
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name="users")
@SuppressWarnings("serial")
public class User implements Serializable{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(unique=true)
public String username;
@NonNull
private String password;
@Column(unique=true) @NonNull
private String email;
private String info;
@OneToMany(mappedBy="user", cascade = CascadeType.REMOVE)
@JsonManagedReference
private List<Device> devices;
/petFinder/src/main/java/com/lino4000/petFinder/model/Device.java
package com.lino4000.petFinder.model;
89
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@Builder
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name="devices")
@SuppressWarnings("serial")
public class Device implements Serializable{
@Column(unique=true)
private String serial;
private String name;
@ManyToOne @NonNull
@JsonBackReference
private User user;
@OneToMany(mappedBy="device",cascade = CascadeType.REMOVE)
@JsonManagedReference
private List<Sensor> sensores;
}
/petFinder/src/main/java/com/lino4000/petFinder/model/Sensor.java
package com.lino4000.petFinder.model;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
91
import lombok.NoArgsConstructor;
import lombok.NonNull;
@Builder
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name="sensors", uniqueConstraints = { @UniqueConstraint(columnNames =
{"device_id", "type"}) })
@SuppressWarnings("serial")
public class Sensor implements Serializable{
/petFinder/src/main/java/com/lino4000/petFinder/model/SensorStatus.java
92
package com.lino4000.petFinder.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@Builder
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@SuppressWarnings("serial")
public class SensorStatus implements Serializable{
@ManyToOne @NonNull
@JsonBackReference
private Sensor sensor;
@NonNull
private String value;
}
/petFinder/src/main/java/com/lino4000/petFinder/model/VerificationToken.java
package com.lino4000.petFinder.model;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.ForeignKey;
@Entity
public class VerificationToken {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public VerificationToken() {
super();
}
this.token = token;
this.expiryDate = calculateExpiryDate(EXPIRATION);
}
this.token = token;
this.user = user;
this.expiryDate = calculateExpiryDate(EXPIRATION);
}
//
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getExpiryDate() == null) ? 0 :
getExpiryDate().hashCode());
result = prime * result + ((getToken() == null) ? 0 : getToken().hashCode());
result = prime * result + ((getUser() == null) ? 0 : getUser().hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final VerificationToken other = (VerificationToken) obj;
if (getExpiryDate() == null) {
if (other.getExpiryDate() != null) {
return false;
}
} else if (!getExpiryDate().equals(other.getExpiryDate())) {
return false;
}
if (getToken() == null) {
97
if (other.getToken() != null) {
return false;
}
} else if (!getToken().equals(other.getToken())) {
return false;
}
if (getUser() == null) {
if (other.getUser() != null) {
return false;
}
} else if (!getUser().equals(other.getUser())) {
return false;
}
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Token
[String=").append(token).append("]").append("[Expires").append(expiryDate).append(
"]");
return builder.toString();
}
/petFinder/src/main/java/com/lino4000/petFinder/config/SecurityConfiguration.java
package com.lino4000.petFinder.config;
import java.util.HashMap;
import java.util.Map;
98
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfig
urerAdapter;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoders = new HashMap<>();
}
if (!registry.hasMappingForPattern("/js/**")) {
registry.addResourceHandler("/js/**").addResourceLocations(
"classpath:/static/js/");
}
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(
"/console/**",
"/img/**",
"/js/**",
"/theme/style.css",
"/theme/favicon.png"
);
}
.loginProcessingUrl("/auth").permitAll()
.defaultSuccessUrl("/dashboard/welcome")
.and()
.authorizeRequests()
.antMatchers("/register").permitAll()
.antMatchers("/view/*").permitAll()
.antMatchers(HttpMethod.GET,"/device/**").permitAll()
.antMatchers(HttpMethod.POST,"/device/**").permitAll()
.antMatchers(HttpMethod.PUT,"/device/**").permitAll()
.anyRequest().authenticated();
}
}
/petFinder/src/main/java/com/lino4000/petFinder/config/WebConfig.java
package com.lino4000.petFinder.config;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import
org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
101
registry.addViewController("/notFound").setViewName("forward:/dashboard/welcome
");
}
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
containerCustomizer() {
return container -> {
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
"/notFound"));
};
}
/petFinder/src/main/java/com/lino4000/petFinder/validation/EmailValidator.java
package com.lino4000.petFinder.validation;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
@Override
102
/petFinder/src/main/java/com/lino4000/petFinder/validation/ValidEmail.java
package com.lino4000.petFinder.validation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
/petFinder/src/main/java/com/lino4000/petFinder/error/DeviceNotFoundException.jav
a
package com.lino4000.petFinder.error;
@SuppressWarnings("serial")
public class DeviceNotFoundException extends RuntimeException {
public DeviceNotFoundException() {
super();
}
/petFinder/src/main/java/com/lino4000/petFinder/error/EmailAlreadyExistException.ja
va
package com.lino4000.petFinder.error;
104
@SuppressWarnings("serial")
public class EmailAlreadyExistException extends RuntimeException {
public EmailAlreadyExistException() {
super();
}
/petFinder/src/main/java/com/lino4000/petFinder/error/PasswordMatchException.java
package com.lino4000.petFinder.error;
@SuppressWarnings("serial")
public class PasswordMatchException extends RuntimeException {
public PasswordMatchException() {
super();
}
/petFinder/src/main/java/com/lino4000/petFinder/error/UserAlreadyExistException.jav
a
package com.lino4000.petFinder.error;
@SuppressWarnings("serial")
public class UserAlreadyExistException extends RuntimeException{
public UserAlreadyExistException() {
super();
}
/petFinder/src/main/java/com/lino4000/petFinder/event/OnRegistrationCompleteEven
t.java
package com.lino4000.petFinder.event;
import java.util.Locale;
import org.springframework.context.ApplicationEvent;
import com.lino4000.petFinder.model.User;
@SuppressWarnings("serial")
public class OnRegistrationCompleteEvent extends ApplicationEvent {
//
/petFinder/src/main/java/com/lino4000/petFinder/event/RegistrationListener.java
package com.lino4000.petFinder.event;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.MessageSource;
import org.springframework.core.env.Environment;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import com.lino4000.petFinder.model.User;
import com.lino4000.petFinder.service.UserService;
@Component
public class RegistrationListener implements
ApplicationListener<OnRegistrationCompleteEvent> {
@Autowired
private UserService userService;
@Autowired
108
@Autowired
private JavaMailSender mailSender;
@Autowired
private Environment env;
// API
@Override
public void onApplicationEvent(final OnRegistrationCompleteEvent event) {
this.confirmRegistration(event);
}
//
/petFinder/src/main/java/com/lino4000/petFinder/repository/UserRepository.java
package com.lino4000.petFinder.repository;
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import com.lino4000.petFinder.model.User;
/petFinder/src/main/java/com/lino4000/petFinder/repository/VerificationTokenReposit
ory.java
110
package com.lino4000.petFinder.repository;
import java.util.Date;
import java.util.stream.Stream;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import com.lino4000.petFinder.model.User;
import com.lino4000.petFinder.model.VerificationToken;
@Modifying
@Query("delete from VerificationToken t where t.expiryDate <= ?1")
void deleteAllExpiredSince(Date now);
}
/petFinder/src/main/java/com/lino4000/petFinder/repository/DeviceRepository.java
package com.lino4000.petFinder.repository;
import org.springframework.data.repository.CrudRepository;
111
import com.lino4000.petFinder.model.Device;
/petFinder/src/main/java/com/lino4000/petFinder/repository/SensorRepository.java
package com.lino4000.petFinder.repository;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import com.lino4000.petFinder.model.Device;
import com.lino4000.petFinder.model.Sensor;
import com.lino4000.petFinder.model.Sensor.SensorType;
}
112
/petFinder/src/main/java/com/lino4000/petFinder/repository/SensorStatusRepository.j
ava
package com.lino4000.petFinder.repository;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import com.lino4000.petFinder.model.Sensor;
import com.lino4000.petFinder.model.SensorStatus;
/petFinder/src/main/java/com/lino4000/petFinder/service/UserService.java
package com.lino4000.petFinder.service;
import java.security.Principal;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
113
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.lino4000.petFinder.dto.RegisterRequest;
import com.lino4000.petFinder.error.EmailAlreadyExistException;
import com.lino4000.petFinder.error.UserAlreadyExistException;
import com.lino4000.petFinder.model.Device;
import com.lino4000.petFinder.model.User;
import com.lino4000.petFinder.model.VerificationToken;
import com.lino4000.petFinder.repository.DeviceRepository;
import com.lino4000.petFinder.repository.UserRepository;
import com.lino4000.petFinder.repository.VerificationTokenRepository;
@Service
@Transactional
public class UserService implements UserDetailsService{
@Autowired
private UserRepository userRepository;
@Autowired
private DeviceRepository deviceRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private MessageSource messages;
@Autowired
private VerificationTokenRepository tokenRepository;
@Override
114
return new
org.springframework.security.core.userdetails.User(user.get().getUsername(),
user.get().getPassword(), true, true, true, true, new HashSet<>());
}
if ( usernameExists( registerRequest.getUsername() ) ) {
throw new
UserAlreadyExistException(messages.getMessage("user.username.alreadExists",nul
l,null));
}
if ( emailExists( registerRequest.getEmail() ) ) {
throw new
EmailAlreadyExistException(messages.getMessage("user.email.alreadExists",null,nu
ll));
}
userRepository.save(
User.builder()
.username(registerRequest.getUsername())
.password(passwordEncoder.encode(registerRequest.getPassword()))
.email(registerRequest.getEmail())
.build()
115
);
return true;
}
deviceRepository.deleteBySerial(serial);
return true;
}
/petFinder/src/main/java/com/lino4000/petFinder/service/DeviceService.java
package com.lino4000.petFinder.service;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lino4000.petFinder.dto.DeviceReceiveLocation;
import com.lino4000.petFinder.dto.PathToGoogleMaps;
import com.lino4000.petFinder.model.Device;
import com.lino4000.petFinder.model.Sensor.SensorType;
import com.lino4000.petFinder.model.SensorStatus;
import com.lino4000.petFinder.repository.DeviceRepository;
import com.lino4000.petFinder.repository.SensorRepository;
import com.lino4000.petFinder.repository.SensorStatusRepository;
@Service
@Transactional
public class DeviceService {
@Autowired
private DeviceRepository deviceRepository;
117
@Autowired
private SensorRepository sensorRepository;
@Autowired
private SensorStatusRepository sensorStatusRepository;
sensorStatusRepository.save(statusLat);
sensorStatusRepository.save(statusLon);
sensorStatusRepository.save(statusAcc);
return location;
}
118
return locations;
}
119
/petFinder/src/main/java/com/lino4000/petFinder/dto/RegisterRequest.java
package com.lino4000.petFinder.dto;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.lino4000.petFinder.validation.ValidEmail;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;
@Builder
@Value
@AllArgsConstructor
public class RegisterRequest {
String username;
@ValidEmail
@NotNull
@NotEmpty
String email;
String password;
String passwordConfirmation;
String info;
String device;
}
/petFinder/src/main/java/com/lino4000/petFinder/dto/DeviceReceiveLocation.java
120
package com.lino4000.petFinder.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;
@Builder
@Value
@AllArgsConstructor
public class DeviceReceiveLocation {
/petFinder/src/main/java/com/lino4000/petFinder/dto/DeviceResponse.java
package com.lino4000.petFinder.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeviceResponse {
private String serial;
private String name;
}
121
/petFinder/src/main/java/com/lino4000/petFinder/dto/GenericResponse.java
package com.lino4000.petFinder.dto;
import lombok.Builder;
import lombok.Value;
@Builder
@Value
public class GenericResponse {
/petFinder/src/main/java/com/lino4000/petFinder/dto/PathToGoogleMaps.java
package com.lino4000.petFinder.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;
@Builder
@Value
@AllArgsConstructor
public class PathToGoogleMaps {
/petFinder/src/main/java/com/lino4000/petFinder/controller/PublicController.java
package com.lino4000.petFinder.controller;
122
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import com.lino4000.petFinder.dto.GenericResponse;
import com.lino4000.petFinder.dto.RegisterRequest;
import com.lino4000.petFinder.error.EmailAlreadyExistException;
import com.lino4000.petFinder.error.UserAlreadyExistException;
import com.lino4000.petFinder.service.UserService;
@Controller
public class PublicController {
@Autowired
public UserService userService;
@Autowired
private MessageSource messages;
@GetMapping("/login")
public String loginPage(ModelMap map, final HttpServletRequest request) {
123
map.addAttribute("errMessage",
messages.getMessage("user.tryToLogin.failure", null, request.getLocale() ) );
return "login";
}
@GetMapping("/register")
public String registerPage(@ModelAttribute("user") RegisterRequest
registerRequest) {
return "register";
}
@PostMapping("/register")
@ResponseBody
public GenericResponse registering(@RequestBody @Valid final RegisterRequest
registerRequest, final HttpServletRequest request, final Errors errors) {
try {
userService.registerNewUser(registerRequest);
return GenericResponse.builder()
.title( messages.getMessage("user.registration.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
return GenericResponse.builder()
.title( messages.getMessage("user.registration.failure", null,
request.getLocale()) )
124
.message( ex.getMessage() )
.build();
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
} catch (final RuntimeException ex) {
return GenericResponse.builder()
.title( messages.getMessage("user.registration.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
}
return GenericResponse.builder()
.title( messages.getMessage("user.registration.success.title", null,
request.getLocale()) )
.message(
messages.getMessage("user.registration.success.message", null,
request.getLocale()) )
.build();
}
@GetMapping("/view/{serial}")
public String viewDevice(@PathVariable("serial") String serial, ModelMap map)
{
if(null == serial)
return "redirect:/login";
125
if(null == userService.getDevice(serial))
return "redirect:/dashboard/device/add?serial="+serial;
map.addAttribute("info",
userService.getDevice(serial).getUser().getInfo());
return "device";
}
/petFinder/src/main/java/com/lino4000/petFinder/controller/PrivateController.java
package com.lino4000.petFinder.controller;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.lino4000.petFinder.dto.DeviceResponse;
import com.lino4000.petFinder.dto.GenericResponse;
import com.lino4000.petFinder.dto.RegisterRequest;
import com.lino4000.petFinder.model.Device;
126
import com.lino4000.petFinder.model.User;
import com.lino4000.petFinder.service.DeviceService;
import com.lino4000.petFinder.service.UserService;
@Controller
@RequestMapping("/dashboard")
public class PrivateController {
@Autowired
private UserService userService;
@Autowired
private DeviceService deviceService;
@Autowired
private MessageSource messages;
@GetMapping("/welcome")
public String index(ModelMap map, Principal principal) {
map.addAttribute("devices",
userService.getDeviceList(principal.getName()));
map.addAttribute("device",
Device.builder().user(userService.getUser(principal)).build());
return "welcome";
}
@GetMapping("/account")
public String account(ModelMap map, Principal principal, RegisterRequest
user) {
User u = userService.getUser(principal);
map.addAttribute("user", RegisterRequest.builder()
.username(u.getUsername())
.email(u.getEmail())
127
.info(u.getInfo())
.password("")
.passwordConfirmation("")
.device("")
.build()
);
return "account";
}
@GetMapping("/view")
public String viewDevice(Principal principal, ModelMap map) {
map.addAttribute("info", userService.getUser(principal).getInfo());
return "device";
}
@GetMapping("/device/add")
public String deviceAdd(@RequestParam(required = false) String serial,
ModelMap map, DeviceResponse device) {
map.addAttribute("serial", serial);
map.addAttribute("device", DeviceResponse.builder().build());
return "device-add";
}
@PostMapping("/device/add")
@ResponseBody
public GenericResponse deviceAdding(@RequestBody DeviceResponse
device, Principal principal, final HttpServletRequest request) {
try {
deviceService.addDevice(device, principal.getName());
} catch (final IllegalArgumentException ex) {
return GenericResponse.builder()
128
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( messages.getMessage("generic.message.failure",
null, request.getLocale()) )
.build();
}
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.device.add.success", null,
request.getLocale()))
.build();
}
@GetMapping("/device/{serial}/finder")
public String getMapPage(@PathVariable("serial") String serial, ModelMap
map) {
map.addAttribute("path", deviceService.getPath(serial));
return "finder";
}
@PostMapping("/device/{serial}/change-name")
@ResponseBody
public GenericResponse changeDeviceName(@PathVariable("serial") String
serial, @RequestBody DeviceResponse device,final HttpServletRequest request) {
129
try {
userService.changeDeviceName(serial, device.getName());
} catch (final IllegalArgumentException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
} catch (final RuntimeException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( messages.getMessage("generic.message.failure",
null, request.getLocale()) )
.build();
}
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.device.changeName.success",
null, request.getLocale()))
.build();
}
@PostMapping("/device/{serial}/delete")
@ResponseBody
public GenericResponse deleteDevice(@PathVariable("serial") String serial,
final HttpServletRequest request) {
try {
130
deviceService.deleteDevice(serial);
} catch (final IllegalArgumentException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
} catch (final RuntimeException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( messages.getMessage("generic.message.failure",
null, request.getLocale()) )
.build();
}
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.device.delete.success", null,
request.getLocale()))
.build();
}
@PostMapping("/user/change-username")
@ResponseBody
public GenericResponse changeUsername( @RequestBody RegisterRequest
user, Principal principal, final HttpServletRequest request) {
try {
userService.changeUsername(principal.getName(), user.getUsername());
} catch (final IllegalArgumentException ex) {
131
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
} catch (final RuntimeException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( messages.getMessage("generic.message.failure",
null, request.getLocale()) )
.build();
}
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.changeUsername.success",
null, request.getLocale()))
.build();
@PostMapping("/user/change-email")
@ResponseBody
public GenericResponse changeEmail(@RequestBody RegisterRequest user,
Principal principal, final HttpServletRequest request) {
try {
userService.changeEmail(principal.getName(), user.getEmail());
} catch (final IllegalArgumentException ex) {
132
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
} catch (final RuntimeException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( messages.getMessage("generic.message.failure",
null, request.getLocale()) )
.build();
}
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.changeUsername.success",
null, request.getLocale()))
.build();
}
@PostMapping("/user/change-info")
@ResponseBody
public GenericResponse changeInfo(@RequestBody User user, Principal
principal, final HttpServletRequest request) {
try {
userService.changeInfo(principal.getName(), user.getInfo());
} catch (final RuntimeException ex) {
return GenericResponse.builder()
133
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.changeInfo.success", null,
request.getLocale()))
.build();
@PostMapping("/user/change-password")
@ResponseBody
public GenericResponse changePassword(@RequestBody RegisterRequest
user, Principal principal, final HttpServletRequest request) {
try {
userService.changePassword(principal.getName(),
user.getPassword(),user.getPasswordConfirmation());
} catch (final IllegalArgumentException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( ex.getMessage() )
.build();
} catch (final RuntimeException ex) {
return GenericResponse.builder()
134
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.changeInfo.success", null,
request.getLocale()))
.build();
@PostMapping("/user/delete")
@ResponseBody
public GenericResponse deleteDevice(@RequestBody RegisterRequest user,
Principal principal, final HttpServletRequest request) {
try {
userService.deleteUser(principal.getName());
} catch (final RuntimeException ex) {
return GenericResponse.builder()
.title( messages.getMessage("generic.title.failure", null,
request.getLocale()) )
.message( messages.getMessage("generic.message.failure",
null, request.getLocale()) )
.build();
}
135
return GenericResponse.builder()
.title( messages.getMessage("generic.title.success", null,
request.getLocale()) )
.message( messages.getMessage("user.delete.success", null,
request.getLocale()) )
.build();
}
/petFinder/src/main/java/com/lino4000/petFinder/controller/DeviceController.java
package com.lino4000.petFinder.controller;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.lino4000.petFinder.dto.DeviceReceiveLocation;
import com.lino4000.petFinder.dto.PathToGoogleMaps;
import com.lino4000.petFinder.service.DeviceService;
136
@Controller
@RequestMapping("/device")
public class DeviceController {
@Autowired
DeviceService deviceService;
@PutMapping("{serial}/newlocation")
@ResponseBody
public DeviceReceiveLocation newLocation(@PathVariable("serial") String serial,
@RequestBody @Valid final DeviceReceiveLocation locationReceived,
@Param("nonce") long nonce) {
@GetMapping("{serial}/path")
@ResponseBody
public List<PathToGoogleMaps> getPath(@PathVariable("serial") String serial,
@Param("nonce") long nonce) {
return deviceService.getPath(serial);
}
/petFinder/src/main/resources/templates/login.html
<!doctype html>
<html lang="pt-br">
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PetFinder</title>
<link rel="stylesheet" href="/theme/style.css">
137
</div>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-
/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ"
crossorigin="anonymous"></script>
</body>
</html>
/petFinder/src/main/resources/templates/register.html
<!doctype html>
<html lang="pt-br">
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PetFinder</title>
<link rel="stylesheet" href="/theme/style.css">
<link rel="shortcut icon" href="/theme/favicon.png" />
<script type="text/javascript" src="/js/functions.js"></script>
</head>
<body class="dark register">
<div id="responser" class="modal fade" tabindex="-1" role="dialog" aria-
hidden="true">
<div class="modal-dialog modal-dialog-centered">
139
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"></h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p></p>
</div>
</div>
</div>
</div>
<div class="wrapper h-100 container-fluid">
<div class="row h-100 justify-content-center align-items-center">
<div class="login-form col">
<div class="logo">
<img src="/img/logo.png" />
</div>
<form class="json" th:action="@{/register}"
th:object="${user}" method="post">
<div class="mb-3">
<label for="user" class="form-
label">Usuário</label>
<span class="input-group-text bi bi-
person-fill">
</span>
<input type="text" class="form-
control" id="user" aria-describedby="userlHelp" th:field="*{username}" >
</div>
<div class="mb-3">
<label for="email" class="form-
label">Email</label>
140
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-
/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ"
crossorigin="anonymous"></script>
</body>
</html>
/petFinder/src/main/resources/templates/welcome.html
<!doctype html>
<html lang="pt-br">
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PetFinder</title>
<link rel="stylesheet" href="/theme/style.css">
<link rel="shortcut icon" href="/theme/favicon.png" />
<script type="text/javascript" src="/js/functions.js"></script>
</head>
<body class="light dashboard welcome">
<div class="wrapper h-100 container-flex">
<header class="row justify-content-center g-0">
<div class="logo py-5 text-center col">
<img src="/img/logo.png" />
</div>
</header>
<main class="container">
<div class="row gy-4">
<div class="col col-12">
<div id="alert" class="panel p-3 bg-light
rounded">
<div class="panel-header">
142
<h2>Bem vindo!</h2>
<button type="button"
class="btn-close" aria-label="Close" data-target="#alert" data-bs-
dismiss="alert"></button>
</div>
<div class="panel-body">
<p>Parabéns pela excelente
aquisição!</p>
</div>
</div>
</div>
<div class="col col-12 col-sm-6">
<a href="#" class="btn btn-block btn-primary
w-100 bg-light bi bi-person-circle" title="Configurações de conta">
</a>
</div>
<div class="col col-12 col-sm-6">
<a href="#" type="button" class="btn btn-
block btn-primary w-100 bg-light bi bi-plus-square-dotted" title="Adicionar novo
dispositivo">
</a>
</div>
<div class="col col-12">
<div class="devices">
<h2>Dispositivos</h2>
<div class="list-group">
<!--/*/<th:block
th:each="device : ${devices}"> /*/-->
<div class="list-group-item list-
group-item-action function btn btn-primary hstack gap-2" title="Dispositivo
"Cachorro"">
<h4>[(${device.name})]</h4>
143
<a
th:href="@{device/}+${device.serial}+@{/finder}" class="icon rounded ms-auto">
<svg
xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor"
class="bi bi-geo-alt-fill" viewBox="0 0 16 16">
<path
d="M8 16s6-5.686 6-10A6 6 0 0 0 2 6c0 4.314 6 10 6 10zm0-7a3 3 0 1 1 0-6 3 3 0 0 1
0 6z"/>
</svg>
</a>
<a
th:href="@{device/}+${device.serial}+@{/change-name}" class="icon rounded">
<svg
xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor"
class="bi bi-pencil-square" viewBox="0 0 16 16">
<path
d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707
0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0
0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
<path fill-
rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0
0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-
1H2.5A1.5 1.5 0 0 0 1 2.5v11z"/>
</svg>
</a>
<a
th:href="@{device/}+${device.serial}+@{/delete}" class="icon rounded">
<svg
xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor"
class="bi bi-trash-fill" viewBox="0 0 16 16">
144
<path
d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1
1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1
.5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5
0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"/>
</svg>
</a>
</div>
<!--/*/</th:block> /*/-->
</div>
</div>
</div>
</div>
</main>
<footer>
</footer>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-
/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ"
crossorigin="anonymous"></script>
</body>
</html>
/petFinder/src/main/resources/templates/finder.html
<!doctype html>
<html lang="pt-br">
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PetFinder</title>
<link rel="stylesheet" href="/theme/style.css">
145
flightPath.setMap(map);
/*]]>*/
}
</script>
</head>
146
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPx
aFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly&channel=2"
async
></script>
<footer>
</footer>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-
/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ"
crossorigin="anonymous"></script>
</body>
</html>
147
/petFinder/src/main/resources/static/theme/scss/style.scss
@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-
icons.css");
@import "../bootstrap/functions";
$primary:#4365C9;
$secondary:#728CD7;
@import "../bootstrap/bootstrap";
@import "../bootstrap/variables";
@import "../bootstrap/utilities";
$custom-height: (
"10": 10%,
"20": 20%,
"30": 30%,
"40": 40%,
"50": 50%,
"60": 60%,
"70": 70%,
"80": 80%,
"90": 90%,
);
$utilities: map-merge(
$utilities,
(
"height": map-merge(
map-get($utilities, "height"),
(
values: map-merge(
map-get(map-get($utilities, "height"), "values"),
$custom-height,
148
),
),
),
)
);
$utilities: map-merge(
$utilities,
(
"max-height": map-merge(
map-get($utilities, "max-height"),
(
values: map-merge(
map-get(map-get($utilities, "max-height"), "values"),
$custom-height,
),
),
),
)
);
@import "../bootstrap/bootstrap";
html, body{height:100%}
body {background-color:#4365C9;color:#FFF;}
main{padding-bottom:20px;}
.panel{color:#607ED2;}
.panel-header{
display:flex;
justify-content: space-between;
}
149
.panel-body p:last-child{margin-bottom:0}
body{
& .modal p, & .modal h5{color:#607ED2;}
& .modal p{margin-bottom:0}
.login-form .logo{text-align:center;padding-bottom:30px;}
body.finder header.container{
height:180px;box-sizing:border-box;
& img{}
}
#map{min-height:80%}
.input-group-text{
background:none;
border:none;
color:#607ED2;
font-size:26px;
padding: .375rem 0.55rem;
position: absolute;
&::before{font-size:26px;}
&.bi-envelope-fill{padding: .600rem 0.70rem;}
}
150
.mb-3 + .btn{margin-top:1rem;}
.mb-3 + .btn:last-child{margin-top:0;}
.btn + .mb-3{margin-top:1rem;}
.devices{
& h2{color:#FFF}
& .list-group-item{padding: 0.5rem 0.5rem;}
& .list-group-item + .list-group-item{margin-top:10px;}
& .list-group-item h4{margin-bottom:0}
& .list-group-item .icon{border:1px solid #728CD7;padding:5px;}
}
/petFinder/src/main/resources/static/js/functions.js
var modal;
window.onload = function(){
prepareForms();
var responser = document.getElementById('responser');
}
})
event.preventDefault();
};
function responseDelegator(response){
responser.querySelector('.modal-body p').innerHTML =
response.message;
if(response.action && response.action !== undefined)
responser.querySelector('.modal-body p').innerHTML = response.action;
modal.show();
}
function prepareForms(){
document.querySelectorAll('form.json').forEach(
(e)=> e.addEventListener( 'submit', sendForm )
)
}
153
void setup() {
Serial.begin(9600);
Serial.println("Start");
delay(200);
Serial.println("Setup done");
void loop() {
char bssid[6];
DynamicJsonBuffer jsonBuffer;
Serial.println("scan start");
if (more_text) {
155
Serial.println("\"wifiAccessPoints\": [");
for (int i = 0; i < n; ++i)
{
Serial.println("{");
Serial.print("\"macAddress\" : \"");
Serial.print(WiFi.BSSIDstr(i));
Serial.println("\",");
Serial.print("\"signalStrength\": ");
Serial.println(WiFi.RSSI(i));
if (i < n - 1)
{
Serial.println("},");
}
else
{
Serial.println("}");
}
}
Serial.println("]");
Serial.println("}");
}
Serial.println(" ");
}
// Construção do JSON
jsonString = "{\n";
jsonString += "\"considerIp\": false,\n";
jsonString += "\"wifiAccessPoints\": [\n";
for (int j = 0; j < n; ++j)
{
jsonString += "{\n";
jsonString += "\"macAddress\" : \"";
jsonString += (WiFi.BSSIDstr(j));
156
jsonString += "\",\n";
jsonString += "\"signalStrength\": ";
jsonString += WiFi.RSSI(j);
jsonString += "\n";
if (j < n - 1)
{
jsonString += "},\n";
}
else
{
jsonString += "}\n";
}
}
jsonString += ("]\n");
jsonString += ("}\n");
client.print("Content-Length: ");
client.println(jsonString.length());
client.println();
client.print(jsonString);
delay(1000);
}
WiFiClient wifiClient;
HTTPClient http;
if (http.begin(wifiClient,"http://ec2-18-222-181-104.us-east-
2.compute.amazonaws.com:8080/device/1234/newlocation?nonce=2389749874798"
)){
Serial.println("http.begin OK");
}
delay(500);
http.addHeader("Content-Type", "application/json");
http.addHeader("Accept", "application/json");
jsonLocation += latitude;
jsonLocation += "\",";
jsonLocation += "\"longitude\":\"";
jsonLocation += longitude;
jsonLocation += "\",";
jsonLocation += "\"accuracy\":\"";
jsonLocation += accuracy;
jsonLocation += "\"";
jsonLocation += ("}");
// Envio
case 200:
Serial.println("Requisicao concluída com sucesso");
break;
case 201:
Serial.println("Requisicao id2 POST!");
break;
case 404:
Serial.println("Site não encontrado!");
break;
159
default:
break;
}
}
else {
Serial.println ("FAIL REQUEST");
}
http.end();
}
}
Serial.println("closing connection");
Serial.println();
client.stop();
Serial.println(jsonLocation);
delay(120000);