Skip to content

Restructure the code #22

@lbedogni

Description

@lbedogni

Problem
The current codebase is not modular enough to support multiple client types (Raspberry Pi, ESP32, mobile, etc.). Code is tightly coupled, making it difficult to extend with new platforms without significant duplication.

Impact

  • Cannot easily add new client types
  • Code duplication across platforms
  • Difficult to maintain shared logic
  • Testing is platform-specific and fragmented

Current State
"Code should be modular. Clients may differ depending on the client, so common functions and data structures should be kept together, and specific implementations for given hardware may inherit from that."

Proposed Architecture

Module Organization

src/
├── clients/           # Platform-specific implementations
│   ├── base/         # Abstract base classes
│   │   ├── client.py
│   │   ├── camera.py
│   │   ├── inference.py
│   │   └── communication.py
│   ├── raspberry_pi/
│   │   ├── client.py
│   │   ├── camera.py
│   │   └── inference.py
│   ├── esp32/
│   │   ├── client.c
│   │   ├── camera.c
│   │   └── inference.c
│   └── mobile/
│       ├── ios/
│       └── android/
├── common/           # Shared utilities
│   ├── config.py
│   ├── models.py
│   ├── messages.py
│   ├── logging.py
│   └── exceptions.py
└── server/          # Server components

Base Classes (Abstract Interfaces)

Client Base

class SCIoTClient(ABC):
    @abstractmethod
    async def initialize(self) -> None: pass
    
    @abstractmethod
    async def acquire_data(self) -> ImageData: pass
    
    @abstractmethod
    async def run_inference(self, data: ImageData) -> InferenceResult: pass
    
    @abstractmethod
    async def offload_if_needed(self, result: InferenceResult) -> OffloadResult: pass
    
    @abstractmethod
    async def shutdown(self) -> None: pass

Camera Base

class CameraModule(ABC):
    @abstractmethod
    def start_capture(self, config: CameraConfig) -> None: pass
    
    @abstractmethod
    def get_frame(self) -> Frame: pass
    
    @abstractmethod
    def stop_capture(self) -> None: pass
    
    @property
    @abstractmethod
    def supported_resolutions(self) -> List[Tuple[int, int]]: pass

Inference Base

class InferenceEngine(ABC):
    @abstractmethod
    def load_model(self, model_path: str, config: ModelConfig) -> None: pass
    
    @abstractmethod
    def run(self, input_data: Array) -> Array: pass
    
    @abstractmethod
    def get_layer_info(self, layer_idx: int) -> LayerInfo: pass
    
    @property
    @abstractmethod
    def max_input_size(self) -> int: pass

Platform-Specific Implementations

Raspberry Pi Client

  • Inherits from SCIoTClient
  • Uses PiCameraModule (CSI camera)
  • Uses TensorFlowLiteInference (with optimizations)
  • Uses HTTP/MQTT communication

ESP32 Client

  • Implements SCIoTClient in C/C++
  • Uses OV Camera module (limited frames)
  • Uses TensorFlow Lite Micro (constrained)
  • Uses HTTP communication (minimal)

Mobile Client

  • Implements SCIoTClient per platform
  • Uses platform camera APIs (AVFoundation, CameraX)
  • Uses platform ML frameworks (Core ML, TFLite)
  • Uses HTTP/REST communication

Configuration System

Testing Strategy

Unit Tests

  • Abstract interface compliance tests (protocol)
  • Platform-specific implementation tests
  • Integration tests per platform

Common Test Fixtures

  • Mock camera (pre-recorded frames)
  • Mock inference engine (synthetic results)
  • Mock server (fake offloading endpoint)

Deliverables

Dependencies

Estimated Effort: Large (6-8 weeks)
Priority: High (blocks other features)

Files: src/clients/base/, src/common/, refactored platform directories
Labels: architecture, "refactoring", "enhancement"`

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions