Skip to content

Commit

Permalink
Merge branch 'docs/wireflow' of https://github.com/Inteli-College/202…
Browse files Browse the repository at this point in the history
…5-1A-T12-EC05-G05 into docs/wireflow
  • Loading branch information
davidijesus committed Mar 5, 2025
2 parents 9f612f6 + 1c2420c commit 416b216
Show file tree
Hide file tree
Showing 59 changed files with 9,751 additions and 5,358 deletions.
13 changes: 13 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

### What is this PR doing?

Write here!!!

---

- [ ] Was testing performed on your machine?
- [ ] Are you confident about this PR?

## If any of the options are not checked, please write the reason below:

Write here!!!
68 changes: 68 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Backend and Frontend CI

on:
push:
branches:
- develop
- main
pull_request:
branches:
- develop
- main

jobs:
build-and-test:
runs-on: ubuntu-latest
env:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
steps:
- name: Checkout code
uses: actions/checkout@v3

# Backend steps (Python)
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
cache: 'pip'

- name: Install backend dependencies
working-directory: src/backend/app
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Check backend server
working-directory: src/backend/app
run: |
# Inicia o servidor em segundo plano
nohup python app.py &
SERVER_PID=$!
# Aguarda 5 segundos para o servidor subir
sleep 5
# Obtém o código de status da rota /@me
status_code=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5000/@me)
echo "Status code: $status_code"
# Aceita 401 como resposta válida (pois indica que o servidor está funcionando sem usuário logado)
if [ "$status_code" -ne 401 ]; then
kill $SERVER_PID
exit 1
fi
kill $SERVER_PID
# Frontend steps (React)
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20.11.0'
cache: 'npm'
cache-dependency-path: src/frontend/package-lock.json


- name: Install frontend dependencies
working-directory: src/frontend
run: npm install

- name: Build Frontend
working-directory: src/frontend
run: npm run build
52 changes: 52 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Deploy Documentation

on:
push:
branches: [main , feat/cria-auto-deploy-docs]
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest

defaults:
run:
shell: bash
working-directory: ./docs

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install and Build
run: |
cd docs
npm install react@18 react-dom@18
npm install
npm run build
- name: Setup Pages
uses: actions/configure-pages@v4

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./docs/build

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
63 changes: 63 additions & 0 deletions docs/docs/CLI/coleta_bin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: "📃 Coleta por Bin"
sidebar_label: "Coleta por Bin"
sidebar_position: 2
---
## 🔍 O que é?

  A **coleta por bin** é um método implementado na ```CLI``` para a coleta automatizada de medicamentos em bins específicos. Esse processo permite determinar a quantidade exata de itens a serem coletados de cada bin, garantindo maior controle e precisão na operação.

## 🤔 Como funciona?

  A função recebe como entrada a quantidade de medicamentos que devem ser retirados de cada bin. Esses valores são passados como argumentos e armazenados em um dicionário para facilitar o processamento.

  O código responsável por essa funcionalidade é:

```python
@cli.command()
def collect_bin(
bin_1: Annotated[int, typer.Argument(help="Quantidade de medicamentos do bin 1")] = 0,
bin_2: Annotated[int, typer.Argument(help="Quantidade de medicamentos do bin 2")] = 0,
bin_3: Annotated[int, typer.Argument(help="Quantidade de medicamentos do bin 3")] = 0,
bin_4: Annotated[int, typer.Argument(help="Quantidade de medicamentos do bin 4")] = 0,
bin_5: Annotated[int, typer.Argument(help="Quantidade de medicamentos do bin 5")] = 0,
):
bin_counts = {
1: bin_1,
2: bin_2,
3: bin_3,
4: bin_4,
5: bin_5,
}

for bin_num in range(1, 6):
for _ in range(bin_counts[bin_num]):
take_medicine(f"bin_{bin_num}")
```

  No código acima:
- Os valores de entrada são armazenados no dicionário ```bin_counts```, onde cada chave representa um bin e o valor associado indica a quantidade de medicamentos a serem coletados.
- O loop percorre os bins de 1 a 5 e, para cada um, chama a função ```take_medicine()``` de acordo com a quantidade informada.

## 📋 Testes

  Para verificar a funcionalidade, foi realizado um teste passando os seguintes argumentos:

```shell
python cli.py collect_bin 2 1 3 2 1
```

Neste caso, o sistema coletará:
- **2** medicamento do **bin 1**
- **1** medicamentos do **bin 2**
- **3** medicamento do **bin 3**
- **2** medicamentos do **bin 4**
- **1** medicamentos do **bin 5**

  O vídeo abaixo demonstra o teste realizado:

<iframe width="560" height="315" src="https://www.youtube.com/embed/ITf1zWd6Wp0?si=J0BAWA2ujUIeheMH" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style={{display:"block", marginLeft:"auto", marginRight:"auto"}}></iframe>

## ✅ Conclusão

&emsp; A **coleta por bin** proporciona uma solução eficiente para a retirada automatizada de medicamentos, garantindo precisão e organização no fluxo operacional. Esse método permite que a coleta seja realizada de forma ordenada e controlada, reduzindo erros e aumentando a confiabilidade do processo.
42 changes: 42 additions & 0 deletions docs/docs/CLI/coleta_lista.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: "📃 Coleta por lista"
sidebar_label: "Coleta por lista"
sidebar_position: 3
---

## 🔍 O que é?

&emsp; Dentro da ```CLI``` existem duas principais funções responsáveis por coletar as medicações nos bins que imaginamos que podem ser utilizadas durante o desenvolvimento do projeto. Neste documento, vamos apresentar a ```coleta por lista```.

## 🤔 Como funciona?

&emsp; A ideia principal é que nosso código receba uma lista desordenada contendo apenas os números dos bins que precisam ser coletados. Por exemplo, se houver uma requisição de ```2 remédios do bin 1``` e ```3 remédios do bin 5```, a lista pode chegar de diversas formas dependendo da forma que for processada pelo sistema do hospital. Alguns exemplos são:

- ```[5, 1, 1, 5, 5]```
- ```[1, 5, 1, 5, 5]```
- ```[5, 5, 1, 1, 5]```

&emsp; Pensando nessa possibilidade, desenvolvemos um código que organiza a lista enviada para ele e, em seguida, inicia a coleta de cada bin.

```python
def collect_list(
input_list: Annotated[List[str], typer.Argument(help="List of bins to collect")],
):
ordered_list = sorted(input_list)
for bin_num in ordered_list:
take_medicine(f'bin_{bin_num}')
```

&emsp; O código recebe a lista dos bins que precisam ser coletados, utiliza o método ```sorted()``` do Python para organizá-los em ordem crescente e, em seguida, executa um ```for``` para coletar todos os medicamentos solicitados, enviando os valores da lista para a função ```take_medicine()``` por meio do sistema de ```f-string```, que permite inserirmos valores dentro de uma ```string```.

## 📋 Testes

&emsp; Para comprovar a viabilidade desse código, realizamos um teste enviando a seguinte lista de valores para ele: ```[5, 3, 1, 4, 2, 2, 3]```

&emsp; Vídeo demonstrando o teste:

<iframe width="560" height="315" src="https://www.youtube.com/embed/qNKu9K5KKDU?si=9uVXZ4fdQ_gTb00s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style={{display:"block", marginLeft:"auto", marginRight:"auto"}}></iframe>

## ✅ Conclusão

&emsp; A utilização da CLI em conjunto com o código desenvolvido para organizar e coletar medicamentos a partir de uma lista desordenada demonstra ser uma solução eficiente e adaptável ao fluxo operacional do projeto. Essa abordagem não só comprova a viabilidade técnica da solução proposta, como também reforça sua aplicabilidade para resolver o problema de coleta automatizada em ambientes hospitalares, garantindo maior organização e confiabilidade no processo.
141 changes: 141 additions & 0 deletions docs/docs/CLI/funcoes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
title: "🔧 Funções da CLI"
sidebar_label: "Funções da CLI"
sidebar_position: 1
---

## 🔍 Introdução

&emsp; O código contém diversas funções auxiliares que garantem o funcionamento correto da coleta de medicamentos. Essas funções controlam desde a movimentação do robô até o acionamento da sucção para pegar e entregar os medicamentos corretamente. Neste documento, detalharemos cada uma dessas funções e seu papel no sistema.


## ⚙️ **check_suction()**

### 📌 O que é?
&emsp; Esta função verifica se a sucção deve ser ativada ou desativada com base nos dados da posição.

### 🛠️ Como funciona?
&emsp; A função recebe como argumento um objeto `Position` e verifica se a chave `suction` está ativada. Se estiver ativada, a ferramenta de sucção do robô é ligada; caso contrário, ela é desligada.

### 💻 Código-fonte:
```python
def check_suction(
position: Annotated[Position, typer.Argument(help="Position data to check if suction should be enabled or disabled.")]
):
if (position.get("suction")):
dobot.enable_tool(100)
else:
dobot.disable_tool(100)
```


## ⚙️ **execute_movement()**

### 📌 O que é?
&emsp; A função responsável por mover o robô para uma posição específica.

### 🛠️ Como funciona?
&emsp; A função recebe um objeto `Position` e um valor opcional de altura adicional. Ela carrega os dados da posição, ajusta a coordenada `z` caso necessário e executa o movimento do robô. Dependendo do tipo de movimento indicado na posição (`move_l` ou `move_j`), o robô usa um movimento linear ou de junta.

### 💻 Código-fonte:
```python
def execute_movement(
position: Annotated[Position, typer.Argument(help="Position data to determine and execute the appropriate movement.")],
add_height: Annotated[int, typer.Argument(help="Additional height to be added to Z if it is the last position of the delivery.")] = 0
):
spinner = yaspin(text=f"Moving to {position}...")
current_position = Position()
current_position.load_from_dict(position)

current_position.z += add_height

if position.get("move") == "move_l":
dobot.move_l_to(current_position, wait=True)
else:
dobot.move_j_to(current_position, wait=True)

spinner.stop()
```


## ⚙️ **deliver()**

### 📌 O que é?
&emsp; A função responsável por entregar os medicamentos coletados.

### 🛠️ Como funciona?
&emsp; A entrega segue um ciclo de posições pré-configuradas, identificadas como `delivery_1`, `delivery_2`, etc. A função percorre essas posições, ajustando a altura da entrega a cada seis medicamentos para evitar colisões.

### 💻 Código-fonte:
```python
def deliver():
global deliver_value
global add_height

if deliver_value > 6:
deliver_value = 1
add_height += 20

for index, position in enumerate(data[f"delivery_{deliver_value}"]):
check_suction(position)

if index != 1:
execute_movement(position)
else:
execute_movement(position, add_height)
deliver_value += 1
```


## ⚙️ **take_medicine()**

### 📌 O que é?
&emsp; A função responsável por coletar medicamentos de um bin específico.

### 🛠️ Como funciona?
&emsp; A função recebe o nome do bin como argumento e percorre as posições associadas a ele no arquivo de configuração, ativando a sucção e movendo o robô conforme necessário.

### 💻 Código-fonte:
```python
def take_medicine(
bin: Annotated[str, typer.Argument(help="Name of the bin from which medicine should be taken.")]
):
for position in data[bin]:
check_suction(position)
execute_movement(position)
deliver()
```


## ⚙️ **main()**

### 📌 O que é?
&emsp; A função principal, que inicializa a conexão com o robô e executa a interface de linha de comando (CLI).

### 🛠️ Como funciona?
&emsp; A função:
1. Lista as portas disponíveis para conexão com o robô.
2. Solicita ao usuário que escolha uma porta.
3. Conecta-se ao robô e configura sua velocidade.
4. Executa a interface da CLI para permitir a execução dos comandos.

### 💻 Código-fonte:
```python
def main():
available_ports = list_ports.comports()
print(f'available ports: {[x.device for x in available_ports]} \n')
port_input = input("Desired port number: ")
port = available_ports[int(port_input)].device
spinner = yaspin(text=f"Connecting with port {port}...")
spinner.start()
dobot.connect(port)
dobot.set_speed(150, 150)
spinner.stop()
cli()
```


## ✅ Conclusão

&emsp; As funções auxiliares desempenham um papel essencial no funcionamento do sistema, garantindo a movimentação do robô, ativação da sucção, coleta e entrega dos medicamentos. O design modular do código facilita a manutenção e possíveis melhorias futuras, tornando a automação mais eficiente e confiável.

Loading

0 comments on commit 416b216

Please sign in to comment.