"""AccessPoint base class for VLC access points."""
import numpy as np
from enum import Enum
from typing import Optional, Any
[docs]
class AccessPoint:
"""Base class for all communication access points in VLC simulation.
AccessPoint provides the foundational structure for both VLC (VLed) and RF communication
access points. It manages spatial positioning, operational state, and time-division
multiplexing (TDM) parameters.
The class implements a state machine where access points can be either IDLE or BUSY,
and supports TDM frame slicing for resource allocation.
Attributes:
stateap (Enum): Enumeration defining AP states (IDLE, BUSY)
Properties:
x (float): X-coordinate position in meters
y (float): Y-coordinate position in meters
z (float): Z-coordinate position in meters (typically height)
position (ndarray): 3D position vector [x, y, z]
state (stateap): Current operational state
ID (int): Unique identifier for the access point
B (float): Bandwidth in Hz
sliceTime (float): Duration of each time slice in seconds
slicesInFrame (int): Number of slices per TDM frame
Example:
AccessPoint is typically not instantiated directly, but through subclasses ::
# Create VLed access point
vled = VLed(x=5.0, y=5.0, z=3.0, nLedsX=2, nLedsY=2,
ledPower=20, theta=60)
vled.sliceTime = 0.1 # 100ms slices
vled.slicesInFrame = 10 # 10 slices per frame
# Create RF access point
rf = RF(x=5.0, y=5.0, z=1.0)
rf.B = 5e6 # 5 MHz bandwidth
Note:
- Position coordinates use a standard 3D Cartesian coordinate system
- Z-coordinate typically represents height (e.g., ceiling height for LEDs)
- Bandwidth B is used in capacity calculations
- TDM parameters control resource allocation granularity
"""
stateap = Enum("state", "IDLE BUSY")
[docs]
def __init__(
self,
x: float,
y: float,
z: float,
) -> None:
"""Initialize an AccessPoint at a given 3D position.
Creates a new access point with specified coordinates and default configuration.
The access point is initialized in IDLE state with default TDM parameters.
Args:
x: X-coordinate position in meters
y: Y-coordinate position in meters
z: Z-coordinate position in meters (typically height from ground)
Example:
Typically called from subclass constructors::
class MyAccessPoint(AccessPoint):
def __init__(self, x, y, z):
super().__init__(x, y, z)
# Add subclass-specific initialization
Note:
- Default bandwidth is set to 1 MHz
- Default slice time is 0.1 seconds (100ms)
- Default frame has 10 slices
- Initial state is IDLE
"""
self._x: float = x
self._y: float = y
self._z: float = z
self._state = AccessPoint.stateap.IDLE
self._sliceTime: float = 0.1
self._slicesInFrame: int = 10
self._ID: Optional[int] = None
self._position: np.ndarray[Any, np.dtype[np.float64]] = np.array([x, y, z])
self._B: float = 1e6
@property
def B(self) -> float:
"""Get the bandwidth of this access point.
Returns:
float: Bandwidth in Hz (default: 1 MHz)
"""
return self._B
@B.setter
def B(self, value: float) -> None:
"""Set the bandwidth of this access point.
Args:
value: Bandwidth in Hz
"""
self._B = value
@property
def ID(self) -> Optional[int]:
"""Get the unique identifier of this access point.
Returns:
int or None: Access point ID, None if not yet assigned
"""
return self._ID
@ID.setter
def ID(self, value: int) -> None:
"""Set the unique identifier of this access point.
Args:
value: ID number to assign
"""
self._ID = value
@property
def x(self) -> float:
"""Get the X-coordinate of this access point.
Returns:
float: X-coordinate in meters
"""
return self._x
@x.setter
def x(self, value: float) -> None:
"""Set the X-coordinate of this access point.
Updates both the individual coordinate and the position vector.
Args:
value: X-coordinate in meters
"""
self._x = value
self._position = np.array([self._x, self.y, self.z])
@property
def y(self) -> float:
"""Get the Y-coordinate of this access point.
Returns:
float: Y-coordinate in meters
"""
return self._y
@y.setter
def y(self, value: float) -> None:
"""Set the Y-coordinate of this access point.
Updates both the individual coordinate and the position vector.
Args:
value: Y-coordinate in meters
"""
self._y = value
self._position = np.array([self.x, self._y, self.z])
@property
def z(self) -> float:
"""Get the Z-coordinate of this access point.
Returns:
float: Z-coordinate in meters (typically height)
"""
return self._z
@z.setter
def z(self, value: float) -> None:
"""Set the Z-coordinate of this access point.
Updates both the individual coordinate and the position vector.
Args:
value: Z-coordinate in meters
"""
self._z = value
self._position = np.array([self.x, self.y, self._z])
@property
def position(self) -> np.ndarray[Any, np.dtype[np.float64]]:
"""Get the 3D position vector of this access point.
Returns:
ndarray: Position vector [x, y, z] in meters
"""
return self._position
@property
def state(self) -> stateap:
"""Get the current operational state of this access point.
Returns:
stateap: Current state, either IDLE or BUSY
"""
return self._state
[docs]
def setIDLE(self) -> None:
"""Set this access point to IDLE state.
Transitions the access point to IDLE, indicating it is ready to accept
new connections.
"""
self._state = AccessPoint.stateap.IDLE
[docs]
def setBUSY(self) -> None:
"""Set this access point to BUSY state.
Transitions the access point to BUSY, indicating it is actively
serving connections.
"""
self._state = AccessPoint.stateap.BUSY
@property
def sliceTime(self) -> float:
"""Get the time duration of each TDM slice.
The slice time determines how long each connection can use the access point
in a single time slice.
Returns:
float: Slice time duration in seconds (default: 0.1s)
"""
return self._sliceTime
@sliceTime.setter
def sliceTime(self, value: float) -> None:
"""Set the time duration of each TDM slice.
Args:
value: Slice time duration in seconds
"""
self._sliceTime = value
@property
def slicesInFrame(self) -> int:
"""Get the number of time slices in each TDM frame.
This determines the frame structure for time-division multiplexing.
Total frame duration equals sliceTime * slicesInFrame.
Returns:
int: Number of slices per frame (default: 10)
"""
return self._slicesInFrame
@slicesInFrame.setter
def slicesInFrame(self, value: int) -> None:
"""Set the number of time slices in each TDM frame.
Args:
value: Number of slices per frame
"""
self._slicesInFrame = value