Skip to content

Refactor codebase structure #5

Merged
iGrec-a2n merged 7 commits into
developmentfrom
feat/robot-monitoring
May 19, 2026
Merged

Refactor codebase structure #5
iGrec-a2n merged 7 commits into
developmentfrom
feat/robot-monitoring

Conversation

@damnthonyy

Copy link
Copy Markdown
Member

TroubleShooting

refactoring initiative

( no linked issue )

Summary

Full codebase refactor: removed ~65 stub files, flattened folder structure, renamed adapters to a consistent convention, simplified the state model to only what's actually implemented, added .env support, and documented every module.

Description

The codebase had accumulated ~400 lines of pure TODO placeholders across 65+ files (empty modules for mission, mode, safety, ROS nodes, schemas, utils, tests). None of these were wired up or called anywhere. Alongside the dead weight, several structural issues made the code hard to navigate:

  • Adapters buried under infrastructure/adapters/ with inconsistent naming (mock_robot_adapter.py, adapter_factory.py)
  • m3pro and sim listed as separate adapters despite both communicating through rosbridge
  • RobotState had 7 fields (position_x, position_y, linear_velocity, angular_velocity, mode…) with no ROS topic feeding them
  • No .env file — environment selection was done by manually exporting shell variables
  • backend.params.yaml existed but was never loaded by Config.load()
  • No documentation on how to add a new topic or extend the system

This PR cleans all of that up to match the actual current scope: battery monitoring via /battery → WebSocket push to dashboard.

What's Changed

Deleted (~65 files removed)

  • app/auth.py, app/rate_limiter.py, app/message_router.py — stubs, never called
  • infrastructure/ — entire folder removed (adapters promoted, ROS nodes and schemas deleted)
  • modules/mission/, modules/mode/, modules/safety/ — unimplemented modules
  • modules/robot/domain/, modules/audit/domain/ — unnecessary subdirectory nesting
  • utils/logger.py, utils/enums.py, utils/ids.py, utils/time.py, utils/thread_safe_lock.py — empty stubs
  • tests/ — all stub test files (no actual assertions)
  • Root: list_ros_topics.py, test_ros_bridge_direct.py, test_ros_bridge_integration.py, TESTING_PHASE3.md

Adapters — restructured

  • infrastructure/adapters/adapters/ (top-level, no infrastructure wrapper)
  • Files renamed to *_adapter.py convention: mock_adapter.py, rosbridge_adapter.py, base_adapter.py
  • AdapterFactory class → create_adapter() function in factory.py
  • m3pro_adapter and sim_adapter removed — both communicate via rosbridge, not direct
  • base_adapter.py stripped to one abstract method: is_connected() (removed premature send_velocity, navigate_to, etc.)
  • robot_state_store param removed from adapter — telemetry_service owns state updates

modules/robot — simplified

  • robot_state_store.py renamed to state_store.py, RobotState converted to dataclass
  • RobotState reduced to 3 fields: is_connected, battery_level, last_updated (only what /battery feeds)
  • audit_event.py moved from audit/domain/audit_event.pyaudit/audit_event.py (flat)

Configuration

  • Config.load() now auto-loads .env via stdlib (no external dependency)
  • .env and .env.example created at project root
  • backend.params.yaml merged into common.params.yaml (it was never loaded)
  • m3pro_topics.yaml, security.params.yaml, sim.params.yaml deleted (stubs)

app/ — contracts + constants

  • contracts.py added: full WebSocket API documentation + message type constants
  • websocket_handler.py updated to use constants from contracts.py instead of raw strings

Docs

  • README.md rewritten with current structure, setup, running instructions, roadmap
  • adapters/README.md — how to subscribe/publish to a ROS topic, step by step
  • modules/robot/README.md — state model, telemetry pipeline, how to add a field
  • modules/audit/README.md — event types, how to record an event, how to add a sink
  • app/README.md — startup sequence, message routing table, contracts usage rules
  • src/robocoop_bringup/config/README.md — YAML loading order, how to add an environment

Key files to review:
adapters/rosbridge_adapter.py, adapters/factory.py, modules/robot/state_store.py, app/contracts.py, app/backend_context.py

How to Test

# Setup
cp .env.example .env
pip install -e src/robocoop_backend

# Smoke test — mock mode (no robot needed)
ROBOCOOP_ENV=mock python -m robocoop_backend.app.server

# Connect with any WebSocket client to ws://localhost:8765 and send:
{"type": "ping"}
# Expected: {"type": "pong"}

# On connection you should automatically receive:
# - {"type": "initial_state", "data": {"is_connected": false, "battery_level": 0.0, ...}}
# - {"type": "activity_history", "data": []}

damnthonyy and others added 2 commits May 18, 2026 13:53
* feat(sim): add Docker environment for ROS2 Humble + Gazebo Fortress with GUI access

* docs(README): update launch instructions for lunch Docker

Co-authored-by: Antoine <damnthonyy@users.noreply.github.com>

* init(backend): initialize backend architecture

* feat(init): Add backend's TODO

* feat(init): update readme

* feat(docs): adding structure diagram

* fix(docs): update diagram's alt 👀

* feat(websockets): Create websocket server with Ping/Pong handler

* feat(readme): update readme to explain websocket server

* fix: guard asyncio.run behind __main__ to prevent server start on import

* feat(archi): refactor into multi modules

* refactor(readme): refactor repository structure

Co-authored-by Antoine Mahassadi <dmantoinepro@gmail.com>

* feat(back): create packages for ROS2 exec

* fix(back): resolve threads

* resolve threads

---------

Co-authored-by: Kelian <kelianhalleray@gmail.com>
Co-authored-by: Antoine <damnthonyy@users.noreply.github.com>
- Add unit tests for event formatting, sinks, state store, and telemetry service

- Implemented unit tests for EventFormatter to ensure required fields, action, actor, ID, timestamp, and payload flattening.

- Added tests for ConsoleSink and FileSink to verify logging behavior and file writing.

- Created tests for RobotState and RobotStateStore to validate state management and updates.

- Developed tests for TelemetryService to check state updates and connection event emissions.

- Removed outdated test files for MessageRouter, MissionStateMachine, ModeManager, RobotStateStore, Schema Validation, TeleopService, and WatchdogService.

- Introduced configuration loading tests to validate YAML parameter handling and environment overrides.

- Implemented Config class to manage configuration loading and access with typed getters.

- Updated setup.py to include testing dependencies.

- Added configuration files for backend, common, mock, and real environments.

Assisted-by : Claude :)
@damnthonyy damnthonyy added enhancement New feature or request Refactor labels May 18, 2026
@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Refactor codebase structure: remove stubs, flatten architecture, implement battery monitoring pipeline

✨ Enhancement 🧪 Tests 📝 Documentation

Grey Divider

Walkthroughs

Description
  **Major codebase refactor and cleanup:**
• Removed ~65 stub files (empty modules, unused utilities, dead test placeholders) totaling ~400
  lines of TODO code
• Flattened folder structure: promoted adapters/ to top-level, removed infrastructure/ wrapper
• Simplified RobotState from 7 fields to 3 (is_connected, battery_level, last_updated)
  matching actual scope
• Renamed adapters to consistent *_adapter.py convention; removed unused m3pro and sim
  adapters
• Converted AdapterFactory class to create_adapter() function for cleaner instantiation
  **Core implementation:**
• Added .env support with stdlib dotenv loading and Config.load() YAML+environment merging
• Implemented RosbridgeClient WebSocket transport layer with primary/secondary URL fallback and
  exponential backoff
• Built RosbridgeAdapter with battery topic subscription, voltage-to-percentage conversion (9V→0%,
  12.6V→100%), and watchdog timeout detection
• Created TelemetryService to receive adapter data, update state store, emit connection events,
  and broadcast to WebSocket clients
• Implemented AuditService with in-memory event history, sink dispatch, and newest-first retrieval
• Added WebSocketHandler with client lifecycle management, message routing, and broadcast
  capabilities
• Created BackendContext singleton for dependency injection and service wiring
  **Testing and documentation:**
• Comprehensive unit test coverage for adapters, services, configuration, and WebSocket handling
• Integration tests wiring real objects end-to-end (adapter → telemetry → audit → state store)
• Real integration tests for live rosbridge server (marked @pytest.mark.real, skipped in CI)
• Complete module documentation (adapters, app, audit, robot, configuration) with extension guides
• Project README with architecture diagram, setup instructions, and roadmap
• GitHub PR template for consistent contribution workflow
  **Configuration and deployment:**
• Created common.params.yaml with WebSocket, battery thresholds, and watchdog settings
• Added environment-specific configs (mock.params.yaml, real.params.yaml)
• Docker setup for ROS 2 Humble + Gazebo simulation environment with VNC/noVNC access
• Bash launch scripts for backend server with environment selection
• ROS 2 launch file placeholders for mock, simulation, real hardware, and debug modes
Diagram
flowchart LR
  ROS["ROS Topics<br/>/battery"]
  RC["RosbridgeClient<br/>WebSocket"]
  RA["RosbridgeAdapter<br/>Voltage→%<br/>Watchdog"]
  TS["TelemetryService<br/>State Updates<br/>Events"]
  SS["StateStore<br/>3-field Model"]
  AS["AuditService<br/>Event History"]
  WS["WebSocketHandler<br/>Client Broadcast"]
  
  ROS -->|subscribe| RC
  RC -->|battery msg| RA
  RA -->|telemetry| TS
  TS -->|update| SS
  TS -->|emit| AS
  TS -->|broadcast| WS
  AS -->|history| WS
Loading

Grey Divider

File Changes

1. src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_rosbridge_adapter.py 🧪 Tests +169/-0

Unit tests for rosbridge adapter battery handling and watchdog

• Comprehensive unit tests for RosbridgeRobotAdapter covering voltage-to-percentage conversion
 (9V→0%, 12.6V→100%)
• Tests for battery watchdog timeout mechanism and disconnection notifications
• Tests for bridge reconnection/disconnection callbacks and connection state delegation

src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_rosbridge_adapter.py


2. src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_rosbridge_client.py 🧪 Tests +198/-0

Unit tests for rosbridge WebSocket client protocol

• Unit tests for RosbridgeClient WebSocket connection lifecycle (connect, disconnect,
 is_connected)
• Tests for topic subscription with correct JSON message format and callback storage
• Tests for message dispatch to subscribers and reconnection logic with exponential backoff

src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_rosbridge_client.py


3. src/robocoop_backend/robocoop_backend/tests/unit/app/test_websocket_handler.py 🧪 Tests +142/-0

Unit tests for WebSocket message handler and client lifecycle

• Tests for WebSocket client registration, initial state/history broadcast, and unregistration
• Tests for message handling (ping/pong, get_state, get_activity, teleop.move, emergency_stop)
• Tests for broadcast to all clients with graceful disconnection handling

src/robocoop_backend/robocoop_backend/tests/unit/app/test_websocket_handler.py


View more (85)
4. src/robocoop_backend/robocoop_backend/tests/unit/utils/test_config.py 🧪 Tests +130/-0

Unit tests for configuration loader and environment variables

• Tests for Config.load() with YAML file merging (common + environment-specific)
• Tests for typed getters (get_str, get_int, get_float, get_bool) with type conversion
• Tests for .env file loading with comment skipping and environment variable precedence

src/robocoop_backend/robocoop_backend/tests/unit/utils/test_config.py


5. src/robocoop_backend/robocoop_backend/adapters/rosbridge_client.py ✨ Enhancement +125/-0

Rosbridge WebSocket client protocol implementation

• Pure WebSocket transport layer for rosbridge protocol (no business logic)
• Implements connection with primary/secondary URL fallback and exponential backoff reconnection
• Handles topic subscription and message dispatch to registered callbacks

src/robocoop_backend/robocoop_backend/adapters/rosbridge_client.py


6. src/robocoop_backend/robocoop_backend/tests/unit/modules/test_telemetry_service.py 🧪 Tests +92/-0

Unit tests for telemetry service and state updates

• Tests for telemetry state updates and connection event emission (robot.connected/disconnected)
• Tests for battery threshold monitoring with one-time alert and recovery reset
• Tests for WebSocket broadcast integration and error handling

src/robocoop_backend/robocoop_backend/tests/unit/modules/test_telemetry_service.py


7. src/robocoop_backend/robocoop_backend/adapters/rosbridge_adapter.py ✨ Enhancement +107/-0

Rosbridge adapter with battery monitoring and watchdog

• Domain-level adapter wrapping RosbridgeClient with battery topic subscription and voltage
 conversion
• Implements battery watchdog timeout to detect disconnection after N seconds without messages
• Handles bridge reconnection callbacks and notifies telemetry service of state changes

src/robocoop_backend/robocoop_backend/adapters/rosbridge_adapter.py


8. src/robocoop_backend/robocoop_backend/app/websocket_handler.py ✨ Enhancement +99/-0

WebSocket message handler with client lifecycle management

• Handles WebSocket client registration, message routing, and broadcast to all connected clients
• Implements message type dispatch using constants from contracts.py (ping, get_state,
 teleop.move, emergency_stop)
• Sends initial state and audit history on client connection

src/robocoop_backend/robocoop_backend/app/websocket_handler.py


9. src/robocoop_backend/robocoop_backend/utils/config.py ✨ Enhancement +91/-0

Configuration loader with YAML and dotenv support

• Configuration loader supporting YAML files and .env environment variables
• Deep merge of common and environment-specific YAML configs with dot-notation access
• Typed getters for string, int, float, and boolean values with defaults

src/robocoop_backend/robocoop_backend/utils/config.py


10. src/robocoop_backend/robocoop_backend/app/contracts.py 📝 Documentation +97/-0

WebSocket API contracts and message type constants

• Comprehensive WebSocket API documentation with message types and payload schemas
• Defines constants for all message types (ping, pong, get_state, teleop.move, emergency_stop, etc.)
• Documents audit actions (robot.connected, battery.low, emergency_stop)

src/robocoop_backend/robocoop_backend/app/contracts.py


11. src/robocoop_backend/robocoop_backend/tests/integration/test_telemetry_pipeline.py 🧪 Tests +74/-0

Integration tests for telemetry pipeline

• Integration tests wiring real objects (adapter → telemetry → audit → state store) end-to-end
• Tests battery voltage flow through conversion, state update, and audit event creation
• Tests connection state transitions and recovery scenarios

src/robocoop_backend/robocoop_backend/tests/integration/test_telemetry_pipeline.py


12. src/robocoop_backend/robocoop_backend/app/server.py ✨ Enhancement +93/-0

Main server entry point with lifecycle and signal handling

• Main server entry point with lifecycle management (initialize, start, shutdown)
• Loads configuration from YAML and environment, creates WebSocket server on configurable host/port
• Handles SIGTERM/SIGINT signals for graceful shutdown

src/robocoop_backend/robocoop_backend/app/server.py


13. src/robocoop_backend/robocoop_backend/modules/robot/telemetry_service.py ✨ Enhancement +83/-0

Telemetry service with state updates and event emission

• Receives telemetry data from adapter and updates robot state store
• Emits connection events (robot.connected/disconnected) and battery low alerts
• Broadcasts state updates to WebSocket clients via async fire-and-forget

src/robocoop_backend/robocoop_backend/modules/robot/telemetry_service.py


14. src/robocoop_backend/robocoop_backend/tests/unit/modules/test_state_store.py 🧪 Tests +75/-0

Unit tests for robot state store

• Tests for RobotState dataclass with three fields (is_connected, battery_level, last_updated)
• Tests for RobotStateStore update/get/reset operations and JSON serialization
• Tests for last_updated timestamp refresh on each update

src/robocoop_backend/robocoop_backend/tests/unit/modules/test_state_store.py


15. src/robocoop_backend/robocoop_backend/modules/audit/audit_service.py ✨ Enhancement +85/-0

Audit service with event recording and history query

• High-level service for recording audit events in-memory with configurable max history
• Dispatches events to audit logger sinks and broadcasts via WebSocket (fire-and-forget)
• Provides get_history() with limit parameter, returns newest-first

src/robocoop_backend/robocoop_backend/modules/audit/audit_service.py


16. src/robocoop_backend/robocoop_backend/tests/unit/modules/test_audit_service.py 🧪 Tests +70/-0

Unit tests for audit service

• Tests for event recording, history retrieval (newest-first), and limit enforcement
• Tests for audit logger dispatch and error swallowing
• Tests for max_history deque size enforcement

src/robocoop_backend/robocoop_backend/tests/unit/modules/test_audit_service.py


17. src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_factory.py 🧪 Tests +65/-0

Unit tests for adapter factory

• Tests for create_adapter() factory function with mock and rosbridge adapter types
• Tests for case-insensitive adapter type matching and config parameter extraction
• Tests for default values and error handling for unknown adapter types

src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_factory.py


18. src/robocoop_backend/robocoop_backend/tests/unit/app/test_backend_context.py 🧪 Tests +76/-0

Unit tests for backend dependency injection context

• Tests for BackendContext singleton pattern (initialize, get_instance, reset)
• Tests for service wiring (state store, audit, telemetry, adapter)
• Tests for lifecycle methods (connect, disconnect) and WebSocket handler propagation

src/robocoop_backend/robocoop_backend/tests/unit/app/test_backend_context.py


19. src/robocoop_backend/robocoop_backend/tests/unit/modules/test_sinks.py 🧪 Tests +61/-0

Unit tests for audit output sinks

• Tests for ConsoleSink logging audit events via logger.info
• Tests for FileSink appending JSON lines to file with parent directory creation
• Tests for multiple writes and JSON validity

src/robocoop_backend/robocoop_backend/tests/unit/modules/test_sinks.py


20. src/robocoop_backend/robocoop_backend/app/backend_context.py ✨ Enhancement +65/-0

Dependency injection context for service initialization

• Dependency injection container initializing all services (state store, audit, telemetry, adapter)
• Singleton pattern with initialize/get_instance/reset for global access
• Wires WebSocket handler to telemetry and audit services for broadcasting

src/robocoop_backend/robocoop_backend/app/backend_context.py


21. src/robocoop_backend/robocoop_backend/tests/real/test_rosbridge_live.py 🧪 Tests +64/-0

Real rosbridge integration tests with live server

• Real integration tests requiring live rosbridge server (skipped in CI)
• Tests connection, subscription, and battery message reception from actual ROS topics
• Marked with @pytest.mark.real and gated by ROSBRIDGE_URL environment variable

src/robocoop_backend/robocoop_backend/tests/real/test_rosbridge_live.py


22. src/robocoop_backend/robocoop_backend/modules/audit/sinks.py ✨ Enhancement +52/-0

Audit sink implementations for console and file output

• Abstract AuditSink base class for audit output destinations
• ConsoleSink logs events to stdout via logger
• FileSink appends JSON lines to file in background thread (non-blocking)

src/robocoop_backend/robocoop_backend/modules/audit/sinks.py


23. src/robocoop_backend/robocoop_backend/tests/conftest.py 🧪 Tests +68/-0

Pytest fixtures and test configuration

• Pytest fixtures for state store, audit service, telemetry service, and WebSocket mocks
• Auto-reset BackendContext singleton before/after each test
• Patches websockets.connect for unit tests

src/robocoop_backend/robocoop_backend/tests/conftest.py


24. src/robocoop_backend/robocoop_backend/tests/unit/modules/test_event_formatter.py 🧪 Tests +48/-0

Unit tests for audit event serialization

• Tests for EventFormatter.format() serializing AuditEvent to JSON-serializable dict
• Tests for payload field flattening at top level
• Tests for ISO timestamp formatting

src/robocoop_backend/robocoop_backend/tests/unit/modules/test_event_formatter.py


25. src/robocoop_backend/robocoop_backend/tests/integration/test_context_lifecycle.py 🧪 Tests +44/-0

Integration tests for backend context and service wiring

• Integration tests verifying service wiring and lifecycle (connect/disconnect)
• Tests state updates visible in store and audit events visible in history
• Tests WebSocket handler propagation to telemetry and audit services

src/robocoop_backend/robocoop_backend/tests/integration/test_context_lifecycle.py


26. src/robocoop_backend/robocoop_backend/tests/unit/modules/test_audit_logger.py 🧪 Tests +43/-0

Unit tests for audit logger and sink dispatch

• Tests for AuditLogger dispatching events to multiple sinks
• Tests for error isolation (failing sink doesn't block others)
• Tests for event formatting before sink dispatch

src/robocoop_backend/robocoop_backend/tests/unit/modules/test_audit_logger.py


27. src/robocoop_backend/robocoop_backend/adapters/factory.py ✨ Enhancement +36/-0

Adapter factory with configuration-driven instantiation

• Factory function create_adapter() instantiating mock or rosbridge adapters based on config
• Extracts rosbridge parameters (URLs, timeouts, topics) from config dict
• Raises ValueError for unknown adapter types

src/robocoop_backend/robocoop_backend/adapters/factory.py


28. src/robocoop_backend/robocoop_backend/tests/unit/modules/test_audit_event.py 🧪 Tests +38/-0

Unit tests for audit event dataclass

• Tests for AuditEvent dataclass auto-generating UUID and timestamp
• Tests for custom payload storage and action/actor fields
• Tests for default empty payload

src/robocoop_backend/robocoop_backend/tests/unit/modules/test_audit_event.py


29. src/robocoop_backend/robocoop_backend/modules/robot/state_store.py ✨ Enhancement +42/-0

Robot state store with simplified three-field model

RobotState dataclass with three fields: is_connected, battery_level, last_updatedRobotStateStore wrapper with get/update/reset/to_dict methods
• Updates refresh last_updated timestamp automatically

src/robocoop_backend/robocoop_backend/modules/robot/state_store.py


30. src/robocoop_backend/robocoop_backend/modules/audit/audit_logger.py ✨ Enhancement +32/-0

Audit logger with sink dispatch and error isolation

• Dispatches AuditEvent objects to registered sinks after formatting
• Swallows sink errors so audit never blocks critical operations
• Supports zero or more sinks

src/robocoop_backend/robocoop_backend/modules/audit/audit_logger.py


31. src/robocoop_backend/robocoop_backend/modules/audit/event_formatter.py ✨ Enhancement +28/-0

Audit event serialization to JSON-compatible format

• Serializes AuditEvent to JSON-serializable dict with id, action, actor, timestamp
• Flattens payload fields at top level for WebSocket transmission
• Converts timestamp to ISO format string

src/robocoop_backend/robocoop_backend/modules/audit/event_formatter.py


32. src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_mock_adapter.py 🧪 Tests +23/-0

Unit tests for mock robot adapter

• Tests for MockRobotAdapter always returning is_connected() == True
• Tests for subclass relationship and instance independence

src/robocoop_backend/robocoop_backend/tests/unit/adapters/test_mock_adapter.py


33. src/robocoop_backend/setup.py ⚙️ Configuration changes +22/-0

Python package setup and dependencies

• Package metadata and dependencies (websockets, pyyaml)
• Test extras with pytest, pytest-asyncio, pytest-mock
• Optional ROS dependency

src/robocoop_backend/setup.py


34. src/robocoop_backend/robocoop_backend/modules/audit/audit_event.py ✨ Enhancement +13/-0

Audit event dataclass definition

AuditEvent dataclass with action, actor, payload, auto-generated id and timestamp
• Represents critical system events (robot.connected, battery.low, emergency_stop)

src/robocoop_backend/robocoop_backend/modules/audit/audit_event.py


35. src/robocoop_bringup/launch/backend_real.launch.py 📝 Documentation +11/-0

TODO placeholder for real hardware launch

• TODO placeholder for real hardware launch configuration
• Outlines steps: load config, include robot runtime, bridges, monitoring, start server

src/robocoop_bringup/launch/backend_real.launch.py


36. src/robocoop_bringup/launch/backend_sim.launch.py 📝 Documentation +11/-0

TODO placeholder for simulation launch

• TODO placeholder for Gazebo simulation launch configuration
• Outlines steps: load config, bridges, server, watchdog, telemetry/teleop bridges

src/robocoop_bringup/launch/backend_sim.launch.py


37. src/robocoop_bringup/launch/backend_mock.launch.py 📝 Documentation +8/-0

TODO placeholder for mock launch

• TODO placeholder for mock adapter launch (no ROS, no hardware)
• Outlines steps: load config, start server and watchdog

src/robocoop_bringup/launch/backend_mock.launch.py


38. src/robocoop_backend/robocoop_backend/adapters/mock_adapter.py ✨ Enhancement +9/-0

Mock robot adapter for development

• Minimal mock adapter implementing RobotAdapter interface
• Always returns is_connected() == True for development/testing

src/robocoop_backend/robocoop_backend/adapters/mock_adapter.py


39. src/robocoop_bringup/launch/backend_debug.launch.py 📝 Documentation +8/-0

TODO placeholder for debug launch

• TODO placeholder for debug mode launch (mock with DEBUG logging)
• Notes security warning about dev-only usage

src/robocoop_bringup/launch/backend_debug.launch.py


40. src/robocoop_bringup/launch/includes/robot_runtime.launch.py 📝 Documentation +7/-0

TODO placeholder for robot runtime nodes

• TODO placeholder for core robot runtime nodes (real hardware only)
• Outlines robot_state_node and emergency_stop_node with respawn configuration

src/robocoop_bringup/launch/includes/robot_runtime.launch.py


41. src/robocoop_bringup/launch/includes/monitoring.launch.py 📝 Documentation +7/-0

TODO placeholder for monitoring nodes

• TODO placeholder for monitoring/observability nodes
• Outlines watchdog_node and optional ROS2 topic logger

src/robocoop_bringup/launch/includes/monitoring.launch.py


42. src/robocoop_bringup/launch/includes/websocket.launch.py 📝 Documentation +5/-0

TODO placeholder for WebSocket server launch

• TODO placeholder for WebSocket server node launch
• References host, port, and auth token parameters

src/robocoop_bringup/launch/includes/websocket.launch.py


43. src/robocoop_backend/robocoop_backend/adapters/base_adapter.py ✨ Enhancement +6/-0

Abstract base adapter interface

• Abstract base class RobotAdapter with single abstract method is_connected()
• Minimal interface for all adapter implementations

src/robocoop_backend/robocoop_backend/adapters/base_adapter.py


44. src/robocoop_bringup/launch/includes/ros_bridges.launch.py 📝 Documentation +6/-0

TODO placeholder for ROS bridge nodes

• TODO placeholder for ROS2 bridge nodes launch
• Outlines teleop_bridge_node, telemetry_bridge_node, mode_bridge_node

src/robocoop_bringup/launch/includes/ros_bridges.launch.py


45. sim_env/docker-container-ros2/ros2/entrypoint.sh ⚙️ Configuration changes +65/-0

Docker entrypoint for ROS2 simulation environment

• Docker entrypoint script for ROS2 Humble + Gazebo Fortress environment
• Sets up Xvfb, XFCE4 desktop, VNC server, and noVNC web interface
• Configurable display resolution, VNC port, and password

sim_env/docker-container-ros2/ros2/entrypoint.sh


46. run_backend.sh ⚙️ Configuration changes +51/-0

Bash launch script for backend server

• Bash launch script for backend server with environment selection (mock/sim/real)
• Sets PYTHONPATH and exports environment variables
• Validates environment and provides usage instructions

run_backend.sh


47. src/robocoop_bringup/scripts/run_real.sh 📝 Documentation +8/-0

TODO placeholder for real hardware launch script

• TODO placeholder for real hardware launch convenience script
• Outlines environment setup and ROS2 launch command

src/robocoop_bringup/scripts/run_real.sh


48. src/robocoop_bringup/scripts/run_mock.sh 📝 Documentation +7/-0

TODO placeholder for mock launch script

• TODO placeholder for mock backend launch convenience script
• Outlines environment setup and ROS2 launch command

src/robocoop_bringup/scripts/run_mock.sh


49. src/robocoop_bringup/scripts/run_sim.sh 📝 Documentation +7/-0

TODO placeholder for simulation launch script

• TODO placeholder for simulation backend launch convenience script
• Outlines environment setup and ROS2 launch command

src/robocoop_bringup/scripts/run_sim.sh


50. src/robocoop_backend/robocoop_backend/adapters/README.md 📝 Documentation +183/-0

Adapter architecture documentation and extension guide

• Comprehensive guide to adapter architecture and two-layer design (client + adapter)
• Step-by-step instructions for subscribing to new ROS topics and publishing messages
• Examples for adding new adapter types and extending the system

src/robocoop_backend/robocoop_backend/adapters/README.md


51. README.md 📝 Documentation +159/-1

Comprehensive project README with setup and architecture

• Complete project overview with architecture diagram and file structure
• Setup instructions, running commands, and quick connection test
• Configuration reference, testing guide, and roadmap

README.md


52. .github/PR_TEMPLATE.md 📝 Documentation +36/-0

GitHub pull request template

• Pull request template with sections for troubleshooting, summary, description, changes, testing
• Guidance on grouping changes by domain and highlighting key files
• Optional sections for screenshots and related issues

.github/PR_TEMPLATE.md


53. src/robocoop_backend/robocoop_backend/modules/robot/README.md 📝 Documentation +107/-0

Robot state and telemetry module documentation

• Documents the robot state management layer with state_store.py and telemetry_service.py
• Explains the simplified RobotState dataclass with only 3 fields: is_connected,
 battery_level, last_updated
• Provides step-by-step guide for adding new ROS topics to the state model
• Details the telemetry pipeline flow and edge-triggered battery alert mechanism

src/robocoop_backend/robocoop_backend/modules/robot/README.md


54. src/robocoop_backend/robocoop_backend/app/README.md 📝 Documentation +93/-0

Application layer and WebSocket API documentation

• Documents the application layer with server lifecycle, WebSocket connections, and dependency
 wiring
• Explains BackendContext singleton pattern for service graph initialization
• Details message routing in websocket_handler.py with inbound/outbound message types
• Describes contracts.py as single source of truth for WebSocket API with constants and examples

src/robocoop_backend/robocoop_backend/app/README.md


55. src/robocoop_backend/robocoop_backend/modules/audit/README.md 📝 Documentation +96/-0

Audit logging and event recording module documentation

• Documents audit event recording system with AuditEvent dataclass and AuditService API
• Explains event serialization with flattened payload structure
• Lists current event types: robot.connected, robot.disconnected, battery.low,
 emergency_stop
• Provides guidance on recording new events and adding custom audit sinks

src/robocoop_backend/robocoop_backend/modules/audit/README.md


56. src/robocoop_bringup/config/README.md 📝 Documentation +108/-0

Configuration system and YAML parameters documentation

• Documents YAML configuration loading order: common.params.yaml + environment-specific overrides
• Explains key configuration values for WebSocket, battery thresholds, and audit logging
• Provides instructions for adding new environments and ROS topics to configuration
• Shows how to access config values in code using dot notation via Config.get()

src/robocoop_bringup/config/README.md


57. sim_env/docker-container-ros2/ros2/Dockerfile ⚙️ Configuration changes +67/-0

Docker image for ROS 2 simulation environment

• Creates Docker image with Ubuntu 22.04, Gazebo Fortress, and ROS 2 Humble
• Installs GUI components (XFCE), VNC, and noVNC for remote access
• Sets up virtual display environment with configurable resolution and VNC/noVNC ports
• Includes entrypoint script for container initialization

sim_env/docker-container-ros2/ros2/Dockerfile


58. sim_env/docker-container-ros2/README.md 📝 Documentation +60/-0

Docker simulation environment setup guide

• Provides French-language setup instructions for Docker-based Ubuntu + Gazebo + ROS 2 environment
• Documents prerequisites, launch commands, and GUI access via noVNC at localhost:6080
• Includes troubleshooting tips for display issues

sim_env/docker-container-ros2/README.md


59. src/robocoop_backend/robocoop_backend.egg-info/SOURCES.txt ⚙️ Configuration changes +28/-0

Package source file manifest

• Lists all source files in the refactored backend package structure
• Includes adapters, app layer, audit module, and robot module files
• Generated metadata file for package distribution

src/robocoop_backend/robocoop_backend.egg-info/SOURCES.txt


60. .github/workflows/ci.yml ⚙️ Configuration changes +34/-0

Continuous integration workflow configuration

• Defines GitHub Actions CI pipeline for unit and integration tests
• Tests against Python versions 3.11, 3.12, 3.13, 3.14
• Installs package with test dependencies and runs pytest excluding real robot tests

.github/workflows/ci.yml


61. src/robocoop_bringup/package.xml ⚙️ Configuration changes +18/-0

ROS 2 package manifest for bringup

• ROS 2 package manifest for robocoop_bringup launch and configuration package
• Declares dependencies on ROS 2 Humble core packages and launch utilities
• Specifies Apache-2.0 license and version 0.1.0

src/robocoop_bringup/package.xml


62. src/robocoop_backend/robocoop_backend.egg-info/PKG-INFO ⚙️ Configuration changes +19/-0

Python package metadata and dependencies

• Package metadata including version 0.1.0, Python requirement >=3.10
• Declares core dependencies: websockets, pyyaml
• Defines optional extras: ros (rclpy) and test (pytest, pytest-asyncio, pytest-mock)

src/robocoop_backend/robocoop_backend.egg-info/PKG-INFO


63. src/robocoop_bringup/config/common.params.yaml ⚙️ Configuration changes +12/-0

Common configuration parameters for all environments

• Shared configuration for WebSocket server (host 0.0.0.0, port 8765)
• Battery safety thresholds: warning at 20%, critical at 10%
• Battery watchdog timeout set to 15 seconds for disconnection detection
• Audit log output path for JSON lines format

src/robocoop_bringup/config/common.params.yaml


64. sim_env/docker-container-ros2/docker-compose.yml ⚙️ Configuration changes +13/-0

Docker Compose configuration for simulation

• Docker Compose service definition for ROS 2 Humble container
• Exposes VNC (5900) and noVNC (6080) ports for remote GUI access
• Allocates 1GB shared memory and sets ROS_DOMAIN_ID environment variable

sim_env/docker-container-ros2/docker-compose.yml


65. src/robocoop_bringup/config/real.params.yaml ⚙️ Configuration changes +10/-0

Real robot environment configuration

• Configuration for real robot deployment with rosbridge adapter
• Specifies primary and secondary rosbridge URLs (10.10.220.79)
• Sets connection timeout (8s), reconnect interval (2s), and max attempts (10)
• Maps /battery ROS topic for telemetry

src/robocoop_bringup/config/real.params.yaml


66. .env.example ⚙️ Configuration changes +10/-0

Environment variables template file

• Template environment file for local development setup
• Defines ROBOCOOP_ENV selector (mock or real)
• Optional overrides for config directory and rosbridge URL

.env.example


67. pyproject.toml ⚙️ Configuration changes +8/-0

Pytest configuration for test organization

• Pytest configuration with test path and asyncio mode settings
• Defines test markers: unit, integration, real for test categorization

pyproject.toml


68. src/robocoop_bringup/CMakeLists.txt ⚙️ Configuration changes +11/-0

ROS 2 CMake build configuration

• CMake build configuration for ROS 2 robocoop_bringup package
• Installs launch files, config, and scripts directories to package share

src/robocoop_bringup/CMakeLists.txt


69. src/robocoop_backend/robocoop_backend.egg-info/requires.txt Dependencies +10/-0

Package dependency specification

• Specifies core dependencies: websockets, pyyaml
• Optional ros extra with rclpy for ROS integration
• Optional test extra with pytest and async testing utilities

src/robocoop_backend/robocoop_backend.egg-info/requires.txt


70. src/robocoop_backend/requirements.txt Dependencies +0/-0

Backend Python requirements update

• Updated to specify websockets==16.0 as core dependency

src/robocoop_backend/requirements.txt


71. src/robocoop_backend/robocoop_backend.egg-info/top_level.txt ⚙️ Configuration changes +1/-0

Package top-level module declaration

• Declares robocoop_backend as top-level package name

src/robocoop_backend/robocoop_backend.egg-info/top_level.txt


72. src/robocoop_backend/robocoop_backend.egg-info/dependency_links.txt ⚙️ Configuration changes +1/-0

Package dependency links metadata

• Empty dependency links file (standard egg-info metadata)

src/robocoop_backend/robocoop_backend.egg-info/dependency_links.txt


73. src/robocoop_bringup/config/mock.params.yaml ⚙️ Configuration changes +1/-0

Mock environment configuration

• Minimal mock environment configuration setting adapter_type: "mock"
• Used for local development without real robot connection

src/robocoop_bringup/config/mock.params.yaml


74. src/robocoop_backend/robocoop_backend/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/init.py


75. src/robocoop_backend/robocoop_backend/adapters/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/adapters/init.py


76. src/robocoop_backend/robocoop_backend/app/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/app/init.py


77. src/robocoop_backend/robocoop_backend/modules/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/modules/init.py


78. src/robocoop_backend/robocoop_backend/modules/audit/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/modules/audit/init.py


79. src/robocoop_backend/robocoop_backend/modules/robot/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/modules/robot/init.py


80. src/robocoop_backend/robocoop_backend/services/.gitkeep Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/services/.gitkeep


81. src/robocoop_backend/robocoop_backend/tests/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/init.py


82. src/robocoop_backend/robocoop_backend/tests/integration/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/integration/init.py


83. src/robocoop_backend/robocoop_backend/tests/real/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/real/init.py


84. src/robocoop_backend/robocoop_backend/tests/unit/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/unit/init.py


85. src/robocoop_backend/robocoop_backend/tests/unit/adapters/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/unit/adapters/init.py


86. src/robocoop_backend/robocoop_backend/tests/unit/app/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/unit/app/init.py


87. src/robocoop_backend/robocoop_backend/tests/unit/modules/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/unit/modules/init.py


88. src/robocoop_backend/robocoop_backend/tests/unit/utils/__init__.py Additional files +0/-0

...

src/robocoop_backend/robocoop_backend/tests/unit/utils/init.py


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented May 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (5) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Missing adapter command methods 🐞 Bug ≡ Correctness
Description
WebSocketHandler.handle_message() calls adapter.send_velocity() and adapter.emergency_stop(), but
RobotAdapter/MockRobotAdapter/RosbridgeRobotAdapter do not define these methods, so those message
types will trigger AttributeError and the command/audit won’t execute.
Code

src/robocoop_backend/robocoop_backend/app/websocket_handler.py[R66-73]

+            elif msg_type == MSG_TELEOP_MOVE:
+                self.context.adapter.send_velocity(message.get("data"))
+            elif msg_type == MSG_EMERGENCY_STOP:
+                logger.warning("Emergency stop via WebSocket")
+                self.context.adapter.emergency_stop()
+                self.context.audit_service.record(
+                    AuditEvent(action=MSG_EMERGENCY_STOP, actor="dashboard", payload={})
+                )
Evidence
The WebSocket handler directly calls send_velocity/emergency_stop, but the adapter base class
and both adapter implementations in the PR only expose is_connected() (and battery/connectivity
helpers for rosbridge), so these calls cannot succeed at runtime.

src/robocoop_backend/robocoop_backend/app/websocket_handler.py[55-73]
src/robocoop_backend/robocoop_backend/adapters/base_adapter.py[1-6]
src/robocoop_backend/robocoop_backend/adapters/mock_adapter.py[1-9]
src/robocoop_backend/robocoop_backend/adapters/rosbridge_adapter.py[12-107]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`WebSocketHandler.handle_message()` routes `teleop.move` and `emergency_stop` to `context.adapter.send_velocity(...)` and `context.adapter.emergency_stop()`, but the adapter interface/implementations don’t provide these methods. This causes runtime failures (caught/logged) and prevents emergency stop from being recorded after the exception.
## Issue Context
- The adapter abstraction currently only defines `is_connected()`.
- Both concrete adapters shown in this PR only implement `is_connected()` (+ connect/disconnect for rosbridge).
## Fix Focus Areas
- src/robocoop_backend/robocoop_backend/adapters/base_adapter.py[1-6]
- src/robocoop_backend/robocoop_backend/adapters/mock_adapter.py[1-9]
- src/robocoop_backend/robocoop_backend/adapters/rosbridge_adapter.py[12-107]
- src/robocoop_backend/robocoop_backend/app/websocket_handler.py[55-73]
## Suggested fix
1. Extend `RobotAdapter` with the command methods actually used by the WebSocket API (at minimum `send_velocity(...)` and `emergency_stop()`), ideally with clear typing (sync vs async).
2. Implement them in `MockRobotAdapter` as safe no-ops.
3. Implement them in `RosbridgeRobotAdapter` (even if initially no-op with logged warning) or remove/disable the message routes until implemented.
4. Update `WebSocketHandler` to `await` these methods if you make them async.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Sim env falls back silently 🐞 Bug ≡ Correctness
Description
run_backend.sh accepts sim and exports ROBOCOOP_ENV=sim, but the repo documents only
mock.params.yaml and real.params.yaml, so sim loads no env YAML and BackendContext defaults
adapter_type to mock, silently running mock mode.
Code

run_backend.sh[R27-36]

+# Validate environment
+case "$ENVIRONMENT" in
+    mock|sim|real)
+        echo "✓ Valid environment: $ENVIRONMENT"
+        ;;
+    *)
+        echo "❌ Invalid environment: $ENVIRONMENT"
+        echo "Supported: mock, sim, real"
+        exit 1
+        ;;
Evidence
The run script explicitly validates sim, but the configuration documentation shows only mock and
real env files; when an env YAML is missing, Config.load logs a warning and proceeds, and
BackendContext defaults adapter_type to mock when absent.

run_backend.sh[27-51]
src/robocoop_bringup/config/README.md[18-25]
src/robocoop_backend/robocoop_backend/utils/config.py[25-43]
src/robocoop_backend/robocoop_backend/app/backend_context.py[15-29]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`run_backend.sh` claims `sim` is a supported environment, but there is no `sim.params.yaml` and the config loader will warn and proceed with common-only config. Since `adapter_type` is then absent, `BackendContext` defaults to `mock`, so users who choose `sim` won’t actually run a distinct sim configuration.
## Issue Context
The config README explicitly lists only `common`, `mock`, and `real` config files.
## Fix Focus Areas
- run_backend.sh[27-51]
- src/robocoop_bringup/config/README.md[18-25]
- src/robocoop_backend/robocoop_backend/utils/config.py[25-43]
- src/robocoop_backend/robocoop_backend/app/backend_context.py[15-29]
## Suggested fix
Choose one:
1) If `sim` is intentionally not implemented yet: remove `sim` from the launch script validation and from any docs claiming it is supported.
2) If `sim` should be supported: add `src/robocoop_bringup/config/sim.params.yaml` (even if it initially sets `adapter_type: mock` plus sim-specific overrides) and/or update docs accordingly.
3) Optionally: make `Config.load()` fail-fast (or at least exit non-zero) for non-`mock` envs when `{env}.params.yaml` is missing.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Watchdog timeout config ignored 🐞 Bug ≡ Correctness
Description
AdapterFactory reads battery_watchdog_timeout_seconds from the rosbridge subsection, but
common.params.yaml (and its docs) define it as a top-level key, so changing the documented value
won’t affect the watchdog behavior.
Code

src/robocoop_backend/robocoop_backend/adapters/factory.py[R22-33]

+    if adapter_type == "rosbridge":
+        rb = config.get("rosbridge", {})
+        topics = rb.get("topics", {})
+        return RosbridgeRobotAdapter(
+            url_primary=rb.get("url_primary", "ws://localhost:9090"),
+            url_secondary=rb.get("url_secondary"),
+            connection_timeout=rb.get("connection_timeout_seconds", 5.0),
+            reconnect_interval=rb.get("reconnect_interval_seconds", 2.0),
+            max_reconnect_attempts=rb.get("max_reconnect_attempts", 5),
+            battery_topic=topics.get("battery", "/battery"),
+            battery_watchdog_timeout=rb.get("battery_watchdog_timeout_seconds", 15.0),
+            telemetry_service=telemetry_service,
Evidence
The YAML config and documentation define battery_watchdog_timeout_seconds at the top level, but
adapter construction only looks for it under rosbridge, so the documented configuration path is
not honored.

src/robocoop_backend/robocoop_backend/adapters/factory.py[22-34]
src/robocoop_bringup/config/common.params.yaml[6-10]
src/robocoop_bringup/config/README.md[35-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`create_adapter()` pulls `battery_watchdog_timeout_seconds` from `config['rosbridge']`, but the configuration files/documentation place this value at the top level. This makes the setting effectively non-functional unless duplicated under `rosbridge`.
## Issue Context
The config README shows `battery_watchdog_timeout_seconds` as a top-level key in `common.params.yaml`.
## Fix Focus Areas
- src/robocoop_backend/robocoop_backend/adapters/factory.py[22-34]
- src/robocoop_bringup/config/common.params.yaml[6-10]
- src/robocoop_bringup/config/README.md[35-40]
## Suggested fix
Either:
- Update `factory.py` to read `battery_watchdog_timeout_seconds` from the top-level config first (e.g. `config.get(...)`), then fall back to `rb.get(...)`; or
- Move the key under `rosbridge:` in YAML and update documentation to match.
Add/adjust a unit test to prove the configured value is applied.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Battery threshold config ignored 🐞 Bug ≡ Correctness
Description
BackendContext constructs TelemetryService without passing battery_warning_threshold from config,
so battery_warning_threshold in YAML does not affect when battery.low audit events fire.
Code

src/robocoop_backend/robocoop_backend/app/backend_context.py[R18-23]

+        self.robot_state_store = RobotStateStore()
+        self.audit_service = AuditService(AuditLogger(sinks=[ConsoleSink()]))
+        self.telemetry_service = TelemetryService(
+            robot_state_store=self.robot_state_store,
+            audit_service=self.audit_service,
+        )
Evidence
TelemetryService exposes battery_warning_threshold, and the YAML config defines it, but
BackendContext does not pass any value from config so the default is always used.

src/robocoop_backend/robocoop_backend/app/backend_context.py[15-29]
src/robocoop_backend/robocoop_backend/modules/robot/telemetry_service.py[10-23]
src/robocoop_bringup/config/common.params.yaml[6-9]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`TelemetryService` supports a configurable `battery_warning_threshold`, and the YAML config defines it, but `BackendContext` always uses the default constructor value. This makes the YAML setting ineffective.
## Issue Context
Current YAML sets the same default (20.0), so behavior happens to match today, but future config changes will be ignored.
## Fix Focus Areas
- src/robocoop_backend/robocoop_backend/app/backend_context.py[15-29]
- src/robocoop_backend/robocoop_backend/modules/robot/telemetry_service.py[10-23]
- src/robocoop_bringup/config/common.params.yaml[6-9]
## Suggested fix
- In `BackendContext.__init__`, read `battery_warning_threshold` from `self.config` and pass it into `TelemetryService(..., battery_warning_threshold=...)`.
- Add a unit test asserting that a non-default config value changes `TelemetryService.battery_warning_threshold`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
5. .env path depends on CWD 🐞 Bug ☼ Reliability
Description
Config.load() only attempts to load .env from the current working directory, but run_backend.sh
changes directory to src/robocoop_backend while the README indicates .env lives at the project
root, so .env variables won’t be applied when starting via the script.
Code

src/robocoop_backend/robocoop_backend/utils/config.py[R14-27]

+    def _load_dotenv(path: str = ".env") -> None:
+        if not os.path.exists(path):
+            return
+        with open(path) as f:
+            for line in f:
+                line = line.strip()
+                if line and not line.startswith("#") and "=" in line:
+                    key, _, value = line.partition("=")
+                    os.environ.setdefault(key.strip(), value.strip())
+
+    @staticmethod
+    def load(config_dir: str = "./config", env: Optional[str] = None) -> "Config":
+        Config._load_dotenv()
+        env = env or os.environ.get("ROBOCOOP_ENV", "mock").lower()
Evidence
Config._load_dotenv defaults to a relative .env, while the launch script changes into
src/robocoop_backend before starting the server and the README describes .env at repo root,
making dotenv loading dependent on how the server is started.

src/robocoop_backend/robocoop_backend/utils/config.py[14-27]
run_backend.sh[49-51]
README.md[46-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Dotenv loading uses a relative path (`.env`) which depends on the process working directory. The provided `run_backend.sh` changes CWD to `src/robocoop_backend`, while documentation places `.env` at the repo root, so dotenv-based configuration won’t be loaded in common startup flows.
## Issue Context
`run_backend.sh` does export `ROBOCOOP_ENV` explicitly, but any other settings placed in `.env` (e.g., overrides) won’t be loaded.
## Fix Focus Areas
- src/robocoop_backend/robocoop_backend/utils/config.py[14-27]
- run_backend.sh[49-51]
- README.md[49-54]
## Suggested fix
- Make `Config.load()` accept a `dotenv_path` (or search upwards from `config_dir`/module location), and pass an absolute `.env` path from `server.py`.
- Alternatively, update `run_backend.sh` to source/load the root `.env` before `cd`, or avoid changing CWD.
- Add a unit test demonstrating dotenv loading works regardless of working directory.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +66 to +73
elif msg_type == MSG_TELEOP_MOVE:
self.context.adapter.send_velocity(message.get("data"))
elif msg_type == MSG_EMERGENCY_STOP:
logger.warning("Emergency stop via WebSocket")
self.context.adapter.emergency_stop()
self.context.audit_service.record(
AuditEvent(action=MSG_EMERGENCY_STOP, actor="dashboard", payload={})
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Missing adapter command methods 🐞 Bug ≡ Correctness

WebSocketHandler.handle_message() calls adapter.send_velocity() and adapter.emergency_stop(), but
RobotAdapter/MockRobotAdapter/RosbridgeRobotAdapter do not define these methods, so those message
types will trigger AttributeError and the command/audit won’t execute.
Agent Prompt
## Issue description
`WebSocketHandler.handle_message()` routes `teleop.move` and `emergency_stop` to `context.adapter.send_velocity(...)` and `context.adapter.emergency_stop()`, but the adapter interface/implementations don’t provide these methods. This causes runtime failures (caught/logged) and prevents emergency stop from being recorded after the exception.

## Issue Context
- The adapter abstraction currently only defines `is_connected()`.
- Both concrete adapters shown in this PR only implement `is_connected()` (+ connect/disconnect for rosbridge).

## Fix Focus Areas
- src/robocoop_backend/robocoop_backend/adapters/base_adapter.py[1-6]
- src/robocoop_backend/robocoop_backend/adapters/mock_adapter.py[1-9]
- src/robocoop_backend/robocoop_backend/adapters/rosbridge_adapter.py[12-107]
- src/robocoop_backend/robocoop_backend/app/websocket_handler.py[55-73]

## Suggested fix
1. Extend `RobotAdapter` with the command methods actually used by the WebSocket API (at minimum `send_velocity(...)` and `emergency_stop()`), ideally with clear typing (sync vs async).
2. Implement them in `MockRobotAdapter` as safe no-ops.
3. Implement them in `RosbridgeRobotAdapter` (even if initially no-op with logged warning) or remove/disable the message routes until implemented.
4. Update `WebSocketHandler` to `await` these methods if you make them async.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

damnthonyy and others added 2 commits May 18, 2026 21:52
This reverts commit dd388fc, reversing
changes made to 351d7b6.
- enhance battery level calcul
- update tests
- update readme

Co-authored-by: Kelian <kelianhalleray@gmail.com>
Comment thread src/robocoop_backend/robocoop_backend/app/backend_context.py Outdated
damnthonyy and others added 2 commits May 19, 2026 10:21
…er, update BackendContext for dependency injection

Co-authored-by: Kelian <kelianhalleray@gmail.com>
@iGrec-a2n iGrec-a2n merged commit 1ad1897 into development May 19, 2026
4 checks passed
@damnthonyy damnthonyy mentioned this pull request May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants