Skip to content

pedroreis2468/ASM

Repository files navigation

🏛️ SmartStudyRoom — Gestão Inteligente de Bibliotecas Universitárias

Python SPADE FIPA-ACL XMPP Tests Coverage Lint Grade License

Agentes e Sistemas Multiagente | Mestrado em Inteligência Artificial | Universidade do Minho | 2025/26

Sistema multiagente distribuído para gestão inteligente de bibliotecas e salas de estudo universitárias, implementado com SPADE sobre XMPP, com comunicação FIPA-ACL e negociação via protocolo Contract Net.

O projeto divide-se em duas fases:

  • Trabalho de Investigação — revisão sistemática (PRISMA) e proposta de arquitetura multiagente (artigo LNCS)
  • Trabalho Prático — implementação do SMA em SPADE com simulação de salas, sensores virtuais e dashboard em tempo real

🎯 Objetivos

  • Monitorizar condições ambientais (temperatura, humidade, CO₂, ruído, iluminância) com sensores virtuais
  • Gerir a ocupação com granularidade ao nível da mesa e cadeira, com indicadores LED (🟢🟡🔴)
  • Redistribuir estudantes automaticamente via FIPA Contract Net quando uma sala atinge lotação
  • Recomendar espaços de forma personalizada com base em preferências declaradas pelo utilizador
  • Integrar pesquisa de livros com disponibilidade de lugares em múltiplas bibliotecas

🏗️ Arquitetura

┌──────────────────── Coordenação Global ─────────────────────┐
│                  Ag. Coordenador Global                      │
└──────────────────────────┬──────────────────────────────────┘
                      FIPA-ACL
┌──────────────── Coordenação Local (por biblioteca) ─────────┐
│   Ag. Coordenador  ←→  Ag. Biblioteca  ←→  Ag. Interface    │
└───────┬──────────────────────────────────────────┬──────────┘
        │                                          │
┌───────┴───── Execução (por sala/piso) ──────┐    │ REST/HTTP
│  Ag. Sala ←→ Ag. Conforto ←→ Ag. Energia   │    │
└─────────────────────────────────────────────┘    │
        ↑ MQTT (simulado)                          ↓
    Sensores IoT (virtuais)                  Dashboard Web
                                             Ag. Utilizador

Agentes e Arquiteturas Internas

Agente Arquivo Arquitetura Função
RoomAgent room_agent.py BDI (FAA) Gere ocupação granular, responde a CFP, pede redistribuição
ComfortAgent comfort_agent.py Reativa Monitoriza sensores, emite alertas condição-ação
CoordinatorAgent coordinator_agent.py Dispatcher–worker Orquestra Contract Net para redistribuição entre salas
GlobalCoordinatorAgent global_coordinator_agent.py Dispatcher–worker Medeia negociação multicampus entre coordenadores locais
EnergyAgent energy_agent.py Utilidade Otimiza U = we·E + wc·(1−C) + wq·(1−Q)
UserAgent user_agent.py BDI Preferências declarativas, recomendação proativa
LibraryAgent library_agent.py Procedimental Pesquisa de livros, participação em negociação multicampus
InterfaceAgent interface_agent.py Reativa Agrega estado, REST API, dashboard web

Protocolos FIPA-ACL

Protocolo Performativas Cenário
Contract Net CFPPROPOSE / REFUSEACCEPT-PROPOSAL / REJECT-PROPOSAL Redistribuição de estudantes
Request REQUESTINFORM Consulta de estado, pesquisa de livros
Inform INFORM Alertas de conforto, atualizações de sensores

Objectos de Mensagem (não strings)

Todas as mensagens transportam objectos serializados em JSON com to_json() / from_json():

Classe Utilização
ComfortAlert Alerta de parâmetro fora de limiar
RedistributionRequest Pedido de redistribuição (sala lotada)
RoomProposal Proposta de acolhimento (Contract Net)
RoomState Estado completo de uma sala
BookSearchRequest Pesquisa de livro
SpaceRecommendation Recomendação de espaço ao utilizador
EnergyAdjustment Sugestão de ajuste energético
UserPreferences Perfil declarado pelo estudante

🔄 Fluxos Principais

1. Redistribuição (Contract Net)

RoomAgent (lotado) ──REQUEST──→ CoordinatorAgent
CoordinatorAgent   ──CFP──────→ RoomAgent A, B, C...
RoomAgent A        ──PROPOSE──→ CoordinatorAgent
RoomAgent B        ──REFUSE───→ CoordinatorAgent
CoordinatorAgent   ──ACCEPT───→ RoomAgent A (melhor utilidade)
CoordinatorAgent   ──REJECT───→ RoomAgent C

2. Alerta de Conforto

ComfortAgent ──INFORM (ComfortAlert)──→ RoomAgent
RoomAgent    ──REQUEST──→ EnergyAgent (ajuste HVAC)
RoomAgent    ──INFORM──→  InterfaceAgent (alerta visual)

3. Pesquisa Livro + Sala

UserAgent    ──REQUEST (BookSearchRequest)──→ LibraryAgent
LibraryAgent ──INFORM (resultados)──────────→ UserAgent
UserAgent avalia salas conhecidas → SpaceRecommendation

🖥️ Dashboard

O dashboard web mostra em tempo real:

  • Estatísticas globais — bibliotecas, salas, lugares livres/ocupados
  • Cards por sala — indicador LED (verde/amarelo/vermelho), sensores, ocupação
  • Detalhe de sala — clique para ver sensores ambientais e dados de ocupação
  • Eventos — redistribuições (Contract Net), alertas de conforto

Atualização automática a cada 3 segundos via polling HTTP.


📂 Estrutura do Repositório

ASM/
├── main.py                            # Entry point — instancia campus e agentes
├── register_agents.py                 # Regista contas XMPP em massa no Prosody
├── config.py                          # Configuração (XMPP, campus, limiares, MQTT)
├── env.yml                            # Ambiente Conda
├── pyproject.toml                     # Config pytest, coverage e ruff
├── docker-compose.yml                 # Prosody + Mosquitto + Prometheus + Grafana
├── prosody.cfg.lua                    # Configuração Prosody (XMPP)
├── mosquitto.conf                     # Configuração Mosquitto (MQTT)
├── setup_xmpp.sh                      # Setup Prosody nativo (alternativa ao Docker)
│
├── core/                              # Ontologia e protocolos
│   ├── ontology.py                    #   SmartStudyRoom-Ontology (objectos serializáveis)
│   ├── fipa.py                        #   Helpers FIPA-ACL para SPADE
│   ├── metrics.py                     #   Instrumentação Prometheus
│   └── logging_config.py              #   Logging estruturado (structlog)
│
├── agents/                            # Agentes SPADE
│   ├── room_agent.py                  #   Agente Sala (BDI real via spade_bdi)
│   ├── comfort_agent.py               #   Agente Conforto (Reativo + MQTT)
│   ├── coordinator_agent.py           #   Agente Coordenador (BDI + Contract Net)
│   ├── global_coordinator_agent.py    #   Coordenador Global (escalação multicampus)
│   ├── energy_agent.py                #   Agente Energia (Utilidade multiobjetivo)
│   ├── user_agent.py                  #   Agente Utilizador (BDI + preferências)
│   ├── library_agent.py               #   Agente Biblioteca (pesquisa livros)
│   ├── interface_agent.py             #   Agente Interface (REST + /metrics + Dashboard)
│   └── bdi/                           #   Programas AgentSpeak (.asl) para BDI real
│       ├── room_agent.asl
│       └── user_agent.asl
│
├── simulation/                        # Simulação de sensores virtuais
│   ├── __init__.py                    #   SensorSimulator + OccupancySimulator
│   └── mqtt_bus.py                    #   Publisher/Subscriber MQTT (paho-mqtt)
│
├── scenarios/                         # 13 cenários de validação reproduzíveis
│   ├── live.py                        #   Cenários "vivos" (injeção no sistema em execução)
│   ├── exam_week.py                   #   Semana de exames (saturação global)
│   ├── sensor_failure.py              #   Sensor degradado → alertas de conforto
│   ├── massive_negotiation.py         #   Contract Net massivo (throughput)
│   ├── multi_campus_cfp.py            #   Escalação multicampus via GlobalCoord.
│   └── …                              #   + comfort_cascade, peak_hour, library_rush,
│                                      #     user_recommendations, book_search_burst, etc.
│
├── tests/                             # 223 testes pytest (unit + integração)
│   ├── test_ontology.py, test_fipa.py, test_config.py, …
│   └── test_contract_net.py implícito em test_coordinator_async.py
│
├── web/                               # Dashboard (HTML/CSS/JS)
│   ├── dashboard.html
│   ├── dashboard.css
│   └── dashboard.js
│
├── prometheus/prometheus.yml          # Scrape config (alvo host.docker.internal:9100)
├── grafana/
│   ├── provisioning/                  # Datasource Prometheus + provider de dashboards
│   └── dashboards/smartstudyroom.json # Dashboard pré-configurado
│
├── .github/workflows/ci.yml           # CI: ruff + pytest + coverage (fail < 60%)
└── docs/                              # Documentação
    ├── paper.pdf                      #   Artigo LNCS (Trabalho de Investigação)
    └── report.pdf                     #   Relatório (Trabalho Prático)

🚀 Reprodução

Pré-requisitos

  • Python 3.11+ (via Anaconda/Miniconda)
  • Docker (recomendado — lança Prosody + Mosquitto + Prometheus + Grafana) ou Prosody + Mosquitto instalados localmente

Passos

  1. Clonar o repositório:

    git clone https://github.com/pedroreis2468/ASM.git
    cd SmartStudyRoom
  2. Criar e ativar o ambiente:

    conda env create -f env.yml
    conda activate ASM
  3. Arrancar os serviços (XMPP + MQTT + Prometheus + Grafana):

    Opção A — Docker (recomendado):

    docker-compose up -d

    Traz 4 serviços:

    Opção B — Prosody nativo:

    sudo bash setup_xmpp.sh
  4. Registar contas XMPP dos agentes (primeira execução apenas):

    python register_agents.py
  5. Executar o SMA:

    python main.py
  6. Abrir:

Parar

Ctrl+C no terminal (para os agentes)
docker-compose down   (para os serviços)

⚙️ Configuração

Editar config.py ou definir variáveis de ambiente:

Parâmetro Descrição Default
XMPP_SERVER Servidor XMPP localhost
XMPP_PASSWORD Password partilhada dos agentes password
CAMPUS_CONFIG Bibliotecas, salas, mesas 2 bibliotecas, 6 salas, 22 mesas, 104 lugares
COMFORT_THRESHOLDS Limiares de conforto temp 18–26 °C, CO₂ < 1000 ppm, ruído < 60 dB
SENSOR_UPDATE_INTERVAL Intervalo de leitura de sensores 5 s
OCCUPANCY_CHANGE_INTERVAL Intervalo de simulação de ocupação 8 s
DASHBOARD_PORT Porta do dashboard + /metrics 8080
HTTP_BIND Interface do dashboard (0.0.0.0 para expor) 127.0.0.1
MQTT_ENABLED / MQTT_BROKER_HOST Ativar sensores via broker MQTT true / localhost
PROMETHEUS_PORT Porta do exportador Prometheus dedicado 9100
SIM_SEED Seed determinística para reprodutibilidade (unset)
CONTRACT_NET_WEIGHTS Pesos availability / comfort / proximity do CN 0.4 / 0.3 / 0.3
ENERGY_UTILITY_WEIGHTS Pesos we / wc / wq da função U do EnergyAgent 0.3 / 0.4 / 0.3

🧪 Testes

Suite de 223 testes (unit + assíncronos) com configuração em pyproject.toml:

# Correr todos os testes
python -m pytest tests/ -v

# Coverage com relatório no terminal
python -m coverage run -m pytest tests/
python -m coverage report

# Coverage HTML interativo
python -m coverage html && open htmlcov/index.html

Cobertura atual:

Módulo Cobertura
core/ontology.py 99%
core/metrics.py 100%
core/fipa.py 95%
config.py 100%
agents/library_agent.py 94%
agents/energy_agent.py 81%
Total 60%

Cobertura dos agentes é propositadamente mais baixa porque a camada XMPP/SPADE é mockada em testes puros; os comportamentos assíncronos têm testes dedicados em test_*_async.py.


📊 Métricas (Prometheus + Grafana)

Todas as métricas relevantes do SMA são exportadas em formato Prometheus, disponíveis em duas URLs:

Métrica Tipo Labels Significado
asm_cfp_sent_total Counter library, scope CFPs emitidas
asm_proposals_received_total Counter library, scope PROPOSEs recebidos
asm_refusals_received_total Counter library, scope REFUSEs recebidos
asm_redistributions_total Counter library, scope Redistribuições concluídas
asm_escalations_total Counter library Escalações ao Coord. Global
asm_comfort_alerts_total Counter room, parameter Alertas de conforto
asm_energy_adjustments_total Counter library, action Ajustes energéticos aplicados
asm_recommendations_total Counter user Recomendações emitidas
asm_room_occupancy_ratio Gauge room, library Ocupação por sala ∈ [0,1]
asm_room_led_status Gauge room, library 0=vermelho, 1=amarelo, 2=verde
asm_active_negotiations Gauge library Negociações CN em curso
asm_cfp_round_seconds Histogram library, scope Latência de uma ronda CN
asm_redistribution_utility Histogram library, scope Utilidade da proposta vencedora
asm_energy_utility Histogram library Função U do EnergyAgent

O Grafana (localhost:3000) vem com o dashboard SmartStudyRoom pré-provisionado em grafana/dashboards/smartstudyroom.json, com painéis para negociações ativas, totais de CFPs/redistribuições, estado LED por sala e rácio de ocupação.


🎬 Cenários de Validação

Cenários reproduzíveis (sem XMPP/MQTT — exercitam as funções de utilidade e regras de decisão puras):

python -m scenarios.exam_week          # Semana de exames (todas as salas ≥90%)
python -m scenarios.sensor_failure     # Sensores degradados + alertas de conforto
python -m scenarios.massive_negotiation  # Contract Net massivo (throughput)
python -m scenarios.multi_campus_cfp   # Escalação multicampus BG → BA

Cada cenário imprime um relatório no terminal mostrando candidatas, utilidade calculada, sala vencedora e (quando aplicável) ações HVAC resolvidas.

Cenários ao vivo (sistema em execução)

Com o sistema a correr (python main.py), é possível disparar cenários no sistema vivo e vê-los acontecer no dashboard — útil para demonstrações. A injeção mexe nos objetos Room partilhados pelos agentes, pelo que o RoomAgent/ComfortAgent reagem de imediato (Contract Net, alertas, escalamento). Funciona com o Modo Demo desligado (estado estável, sem ruído aleatório a sobrepor a injeção).

O catálogo ao vivo (definido em scenarios/live.py) cobre todos os cenários determinísticos, agrupados por categoria no dropdown do dashboard: Redistribuição (saturate, exam_week, massive_negotiation…), Conforto/Energia (comfort_spike, sensor_failure, comfort_cascade…), Multicampus (multicampus, multi_campus_cfp, unbalanced_campuses), Recomendação (recommendation_conflict, user_recommendations, peak_hour), Livros (book_search_burst, book_no_match), Combinado (library_rush, perfect_storm) e Reset.

Três formas de disparar:

# 1) CLI
python toggle_demo.py scenarios            # lista os cenários ao vivo
python toggle_demo.py scenario saturate    # satura uma sala -> redistribuição
python toggle_demo.py scenario multicampus # satura uma biblioteca -> escala ao global
python toggle_demo.py scenario comfort_spike  # picos de CO2/temp/ruído -> alertas
python toggle_demo.py scenario book_search_burst  # pesquisa de livros multi-biblioteca
python toggle_demo.py scenario reset       # repõe as salas (re-arma os cenários)

# 2) REST
curl "http://localhost:8080/api/demo/scenario?name=saturate"

# 3) Dashboard: dropdown "Cenário" + botão "Correr" (junto ao Modo Demo)

Nota (comfort_spike): os alertas de conforto disparam de forma fiável no modo fallback (sem broker MQTT, em que o ComfortAgent reavalia o ambiente em cada ciclo). Com um broker MQTT ativo a avaliação é orientada por eventos, pelo que o comfort_spike ao vivo é mais fiável sem o broker. Os cenários de ocupação (saturate, multicampus) disparam o Contract Net em qualquer modo. Dica: subir a velocidade (ex.: 5x) acelera a reação.


👥 Grupo

Nome Email
Luís Miguel Pereira Silva PG60390 pg60390@alunos.uminho.pt
Pedro Miguel S. A. Urbano dos Reis PG59908 pg59908@alunos.uminho.pt
Guilherme Lobo Pinto PG60225 pg60225@alunos.uminho.pt
Pedro Alexandre Silva Gomes PG60289 pg60289@alunos.uminho.pt

📜 Licença

Este trabalho é de cariz estritamente académico. Universidade do Minho, Escola de Engenharia, Departamento de Informática.

About

🏛️ Distributed multi-agent system for smart university library management using SPADE/XMPP, FIPA-ACL protocols, and Contract Net negotiation, with real-time dashboard.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors