Avaliação de Candidatos
Projetos
Cenário do Projeto
Um produto na área de Internet das Coisas (IoT) e Sensoreamento Remoto está sendo desenvolvido. Trata-se de um serviço para gerenciar o estado de sensores IoT distribuídos e alertar situações ou emergências condicionados a esses objetos através de um aplicativo.
Por exemplo, um usuário pode ser alertado através de seu smartphone sobre o superaquecimento de um equipamento ou produto sensível que estava sendo monitorado através de um sensor previamente instalado e conectado à plataforma. Ao adquirir um sensor compatível com o serviço e instalá-lo, é possível associá-lo à conta de usuário do dono, assim, ele estará disponível no dashboard do app para acompanhamento, sendo informado de quais grandezas (ou streams) estão sendo monitoradas e seus valores mais recentes. Em outra área do app (fora do escopo deste cenário) seria possível configurar alertas combinando condições sobre essas grandezas, ex: alertar usuário quando a temperatura do sensor 985bf2cde9b54a54b8fcd3423d89ad89 (rotulado como Freezer do depósito) ultrapassar -4 ºC.
Domínio
Arquiteturalmente, o domínio estabelece que cada usuário (User) possui um conjunto de sensores (representações de um sensor físico) e tais sensores (Sensor) podem apresentar diferentes streams de dados (Stream) como temperatura, umidade, pressão atmosférica, luminosidade, etc (label), cada um com sua unidade pré-estabelecida (Unit: ºC, hPa, %, lux, etc). Espera-se que para uma stream ativa (enabled), novos dados (Data), que representam leituras num determinado momento (timestamp, UNIX time) sejam publicados ao longo da atividade do sensor instalado, de modo que, novos objetos Data cheguem à stream na ordem de segundos ou minutos. O diagrama abaixo representa o parte do modelo conceitual da plataforma IoT proposta:
Prototipação de UI
História
John Doe adquiriu 3 sensores compatíveis com a plataforma proposta. Ao abrir o aplicativo, com sua conta, registrou os 3 sensores no app, cada um para um propósito diferente, o primeiro "Controle de ambiente do escritório", monitorando "Temperatura", em ºC, e "Luminosidade", em lux. O segundo, "Freezer do armazém", medindo apenas "Temperatura", em ºC. O terceiro, "Oxigenação do aquário", monitorando a concentração de "Oxigênio", em mg/L.
De acordo com o modelo de domínio, cada sensor e stream recebe uma chave de identificação (key), uma string alfanumérica semelhante a 10dd35008a0f4d838c3dc22856660928 , com essa chave a ativação dos sensores físicos pode ser concluída, e considerando os sensores do John Doe já funcionando, seus dados já estão sendo publicados na plataforma IoT e consequentemente podem ser acompanhados no app.
Objetivo
Prototipação parcial do aplicativo Android. A estética do material design deve ser levada em consideração.
Parte I - Prototipação
Prototipação não-funcional (3 telas: layout de login + dois layouts internos) usando ferramenta de design. Weapon of choice: Figma.
Entregável: projeto Figma com layouts completados.
Help:
- https://www.materialdesignkit.com/android-gui (UI Kit)
- https://www.uplabs.com (Inspiration)
- https://www.youtube.com/channel/UCQsVmhSa4X-G3lHlUtejzLA/feed (Figma youtube channel)
Parte II - Implementação de Layouts
Utilizar Android Studio para implementar layouts da tela mais significativa do app (uma das 3 prototipadas anteriormente).
Entregável: projeto Android com layouts implementados.
Help:
- https://www.udacity.com/course/android-basics-user-interface--ud834 (básico sobre layouts do Android)
Exemplos:
- https://www.youtube.com/watch?v=Eh0OkzDEQJs
- https://www.youtube.com/watch?v=lUymjX4K7FM
- https://www.youtube.com/watch?v=CgX7DAyeMXM
RESTFul API
História
Os desenvolvedores de front-end da plataforma IoT proposta (Web, iOS e Android) precisam acessar uma RESTful API que suporte as operações que o usuário é capaz de desempenhar nos aplicativos.
É esperado que através dos apps o usuário possa visualizar sensores e streams ativos, registrar novos sensores e vincular/registrar novas streams aos mesmos. Para as streams, é possível consultar o fluxo de dados que vai sendo publicado pelos sensores reais ao longo do tempo.
É esperado que a RESTful API permita interagir com duas entidades principais sensor e stream através de mensagens em JSON. Foi definido um conjunto de requisitos mínimos que a API deve atender bem como determinados os formatos das mensagens de cada requisição, como listadas no fim do documento.
Objetivo
Implementar um serviço de backend (com um modelo e persistência de dados) que provê uma RESTFul API para os desenvolvedores de front-end atendendo as necessidades em anexo.
Implementação do Serviço
À implementação do serviço não impõe restrições tecnológicas, nem sobre banco de dados nem sobre linguagem/framework para desenvolvimento, algumas sugestões são:
- Express, Loopback, Restify (JS),
- Play Framework, Spark Framework, Restlet (Java)
- Django, Flask (Python)
- Ruby on Rails (Ruby)
Ferramentas
Entregável
O candidato deve apresentar o serviço implementado e demonstrar o funcionamento dos endpoints sugeridos em anexo, bem como apresentar a maneira como a base foi modelada.
Definição da API
[GET] Consultar unidades de grandeza (unit)
<= response
[
{
"oid": 1,
"label": "ºC"
}
{
"oid": 2,
"label": "mg/m³"
},
{
"oid": 3,
"label": "hPA"
},
{
"oid": 4,
"label": "lux"
},
{
"oid": 5,
"label": "%"
}
]
[GET] Consultar Sensores (sensor) de um Usuário (user)
<= response
[
{
"oid": 1,
"key": "10dd35008a0f4d838c3dc22856660928",
"label": "sensor 001",
"description": "Isaac's Room control",
"streams": [
{
"oid": 1,
"key": "b4ea3ba494644200b679ac593f55cb87",
"label": "temperature",
"unit": 1,
"sensor": 1,
"totalSize": 84
},
{
"oid": 3,
"key": "ae194d2b61e0496fbf601f9edcf8b0c5",
"name": "humidity",
"unit": 5,
"sensor": 1,
"totalSize": 6
},
{
"oid": 4,
"key": "3170f851fd9045ed99e5d86ababdb80e",
"label": "carbon dioxide",
"unit": 2,
"sensor": 1,
"totalSize": 7
}
]
},
{
"oid": 2,
"key": "27b26e48cd674cc38ec45808cf48fa07",
"label": "Kitchen's freezer sensor (Arduino)",
"description": "Kitchen's freezer sensor (Arduino)",
"streams": [
{
"oid": 2,
"key": "8961bd9a4d1e439ebf3b86af5b9d5c1f",
"label": "temperature",
"unit": 1,
"sensor": 2,
"totalSize": 19
}
]
}
]
[GET] Consulta de um Sensor (sensor) específico. Ex: key: 27b26e48cd674cc38ec45808cf48fa07
<= response
{
"oid": 2,
"key": "27b26e48cd674cc38ec45808cf48fa07",
"label": "Kitchen's freezer sensor (Arduino)",
"description": "Kitchen's freezer sensor (Arduino)",
"streams": [
{
"oid": 2,
"key": "8961bd9a4d1e439ebf3b86af5b9d5c1f",
"label": "temperature",
"unit": 1,
"sensor": 2,
"totalSize": 19,
"data": [
{
"timestamp": 1506455591,
"data": -6.56
},
{
"timestamp": 1506455566,
"data": -6.54
},
{
"timestamp": 1506455551,
"data": -6.56
},
{
"timestamp": 1506455530,
"data": -6.55
},
{
"timestamp": 1506455510,
"data": -6.56
},
]
}
]
}
obs: a consulta individual de um sensor retorna adicionalmente os 5 dados mais recentes de cada stream que o mesmo possui.
[GET] Consulta de dados de um Stream (stream) específico. Ex: key: 8961bd9a4d1e439ebf3b86af5b9d5c1f
<= response
{
"oid": 2,
"key": "8961bd9a4d1e439ebf3b86af5b9d5c1f",
"label": "temperature",
"unit": 1,
"sensor": 2,
"totalSize": 19,
"data": [
{
"timestamp": 1506455591,
"data": -6.56
},
{
"timestamp": 1506455566,
"data": -6.54
},
{
"timestamp": 1506455551,
"data": -6.56
},
{
"timestamp": 1506455530,
"data": -6.55
},
{
"timestamp": 1506455510,
"data": -6.56
},
...
]
}
[POST] Registrar Sensor (sensor)
request =>
{
"label": "Kitchen's freezer sensor (Arduino)",
"description": "Kitchen's freezer sensor (Arduino)",
}
<= response
{
"oid": 2,
"key": "8961bd9a4d1e439ebf3b86af5b9d5c1f",
"label": "Kitchen's freezer sensor (Arduino)",
"description": "Kitchen's freezer sensor (Arduino)",
}
obs: oid (identificador interno) e key (chave de identificação) são atribuídos no momento do registro do sensor pelo serviço.
[POST] Registrar Stream (stream) para Sensor (sensor). Ex: key: 27b26e48cd674cc38ec45808cf48fa07
request =>
{
"label": "temperature",
"unit": 1
}
<= response
{
"oid": 2,
"key": "8961bd9a4d1e439ebf3b86af5b9d5c1f",
"label": "temperature",
"unit": 1,
"sensor": 2,
"totalSize": 0
}
obs: oid (identificador interno) e key (chave de identificação) são atribuídos no momento do registro da stream pelo serviço.
[POST] Publicar dado em um Stream (stream). Ex: key: 8961bd9a4d1e439ebf3b86af5b9d5c1f
request =>
{
"timestamp": 1506521102,
"value": 28.5
}
<= response
{
"oid": 123,
"timestamp": 1506521102,
"value": 28.5
}
obs: oid (identificador interno) e key (chave de identificação) são atribuídos no momento do registro da stream pelo serviço.
Arquitetura de Front-End
PADRÃO ARQUITETÔNICO MODEL-VIEW-PRESENTER
A plataforma Android não advoga por um tipo de arquitetura ou organização específica para desenvolver um aplicativo. O desenvolvedor é livre para utilizar padrões como MVC (Model-View-Controller), MVVM (Model-View-ViewModel) ou MVP(Model-View-Presenter) ou até mesmo não utilizar nenhuma arquitetura.
Nesse contexto, utilizar o padrão MVP significa seguir princípios que permitem a separação entre a camada de apresentação e a camada de dados da aplicação, proporcionando o código ser reutilizável e testável de maneira simples. O MVP divide os componentes da arquitetura baseado em papéis, seguindo o princípio da separação de conceitos(https://en.wikipedia.org/wiki/Separation_of_concerns).
O padrão MVP divide a aplicação em 3 componentes básicos:
- Model: responsável por lidar com a camada de dados da sua aplicação.
- View: responsável por apresentar os componentes de interface.
- Presenter: responsável por fazer a conexão entre Model e View (o middle-man entre os dois).
O padrão MVP também define algumas regras a serem seguidas:
- A única responsabilidade da View é mostrar os componentes de interface com seus respectivos valores na tela, de acordo com os dados enviados pelo Presenter. A View é portanto, totalmente passiva.
- A View delega todas as ações provenientes de interações do usuário para o Presenter.
- A View não se comunica diretamente com o Model e vice-versa.
- Toda a comunicação entre Presenter e View é feita através de interfaces.
- O Presenter é responsável por delegar requisições da View para o Model e também por instruir a View com ações para eventos específicos.
- O Model é responsável por lidar com requisições de dados de servidor, banco de dados e sistema de arquivos. O Modelpode inclusive ser uma interface que se comunica com outros módulos que realizam essas funções.
A figura a seguir mostra as dependências entre cada componente do padrão MVP:
Links úteis (sobre implementação do MVP no Android):
- https://blog.mindorks.com/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40
- https://medium.com/@cervonefrancesco/model-view-presenter-android-guidelines-94970b430ddf
- https://antonioleiva.com/mvp-android/
- http://www.tinmegali.com/en/model-view-presenter-android-part-1/
ANDROID BÁSICO
-
RecyclerView
- Intents
- Criação de interfaces de usuário no Android:
CHAMANDO A API RESTFUL
Utilizar a biblioteca FastAndroidNetworking. Alguns exemplos de uso estão disponíveis neste link.
Engenharia de Front-end Mobile
História
John Doe adquiriu 3 sensores compatíveis com a plataforma proposta. Ao abrir o aplicativo, com sua conta, registrou os 3 sensores no app, cada um para um propósito diferente, o primeiro "Controle de ambiente do escritório", monitorando "Temperatura", em ºC, e "Luminosidade", em lux. O segundo, "Freezer do armazém", medindo apenas "Temperatura", em ºC. O terceiro, "Oxigenação do aquário", monitorando a concentração de "Oxigênio", em mg/L.
De acordo com o modelo de domínio, cada sensor e stream recebe uma chave de identificação (key), uma string alfanumérica (semelhante a 10dd35008a0f4d838c3dc22856660928 ) ao ser cadastrada. Com essa chave a ativação dos sensores físicos pode ser concluída, e considerando os sensores do John Doe já funcionando, seus dados já estão sendo publicados na plataforma IoT e consequentemente podem ser acompanhados no app.
A equipe de back-end da plataforma desenvolveu uma RESTful API que suporta as operações que o usuário deve ser capaz de desempenhar através dos aplicativos, de forma que cabe a equipe de front-end mobile desenvolver os aplicativos utilizando esta API.
Objetivo
Desenvolver um aplicativo Android do ponto de vista funcional, que permita (I) listar os sensores já existentes na conta do usuário, (II) visualizar os detalhes de um sensor, (III) acompanhar os dados mais recentes de uma stream, (IV) além de registrar, tanto novos sensores quanto novas streams.
Quanto a característica funcional da proposta, significa que o projeto deve ser voltado para a arquitetura da aplicação e design, UI e UX não estão no escopo da atividade. Considere que o aprimoramento visual do app será realizado por outra equipe ou em outra iteração.
É solicitado que o desenvolvimento do aplicativo empregue a arquitetura MVP (Model-View-Presenter), considerando a familiaridade da equipe mobile da Evológica a esse design pattern. Abaixo algumas telas de como ao final do sprint a aplicação deveria se comportar.
|
Sensores do Usuário |
Detalhe do Sensor |
Detalhe da Stream |
|
|
|
|
Ferramentas e Ajuda
MVP (Model-View-Presenter)
- https://blog.mindorks.com/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40 (apenas a parte I)
- https://medium.com/@cervonefrancesco/model-view-presenter-android-guidelines-94970b430ddf
- https://antonioleiva.com/mvp-android/
- http://www.tinmegali.com/en/model-view-presenter-android-part-1/
Android Básico
-
RecyclerView
- Intents
- Criação de interfaces de usuário no Android:
Rest API
- Postman (https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en)
- FastAndroidNetworking. (https://amitshekhariitbhu.github.io/Fast-Android-Networking/get_request.html).
Após iterações de desenvolvimento com a equipe de design o app (fora do scopo do seu projeto) se aproximaria desse layout:
| Sensores do Usuário | Detalhe do Sensor | Detalhe da Stream |
|
|
|
|
RESTful API
Primeiramente, para utilizar a API, é necessário enviar um token de autenticação (X-AUTH-TOKEN) no header de cada requisição HTTP. A URL base dos resources da API é http://multicast.vix.br:8082. O token que você deve utilizar é:
cba991ae0c38408a84cf01687c60d075
Ex:
curl --request GET \
--url http://multicast.vix.br:8082/sensors \
--header 'content-type: application/json' \
--header 'x-auth-token: cba991ae0c38408a84cf01687c60d075'
Endpoints
| GET | /sensors |
| Get user sensors | |
<= response[
|
|
| POST | /sensors |
|
Register new sensor |
|
|
{
{
|
|
| GET | /sensors/{sensorOid} |
|
Get user sensor by Id |
|
|
{
|
|
| POST | /sensors/{sensorOid}/streams |
|
Register new stream |
|
|
{
{
|
|
| GET | /sensors/{sensorOid}/streams/{streamOid} |
| Get stream info and recent data | |
<= response{
|
|