Reputation: 1
I am working on a Bluetooth LE mesh network project with various devices distributed in an urban environment. My goal is to determine the minimum node density per square kilometer required for the network to function effectively.
To explore this, I am using MATLAB, specifically the Bluetooth Toolbox library, to simulate a Bluetooth mesh network within a 200x200 meter area. In the simulation:
The script identifies active links between nodes based on the remaining power, which is calculated as the difference between the transmission power and the path loss. If the remaining power exceeds -70 dBm (the detection threshold for most receivers), the link is considered active. These active links are displayed on a figure using color grading.
However, i am encountering two major issues:
CODE:
% Initialize the wireless network simulator
networkSimulator = wirelessNetworkSimulator.init;
% Parameter to enable or disable the maximum distance constraint
maintainDistanceConstraint = true; % Set to false to disable the maximum distance constraint
% Define the area and node parameters
areaSide = 200;
numNodes = 12; % Total number of nodes
minReceivedPower = -70; % Minimum received power threshold in dBm
maxDistance = 70; % Maximum distance between nodes (valid only if maintainDistanceConstraint is true)
maxLinkDistance = 100; % Maximum distance to consider a link active
transmissionPower = 20; % Transmitted power in dBm
% Operating frequency of the Bluetooth LE signal (2.4 GHz)
frequency = 2.4e9;
% Function to calculate free space path loss
calculateFreeSpacePathLoss = @(distance, frequency) ...
20 * log10(distance) + 20 * log10(frequency) - 147.55; % Result in dB
% Initialize the position matrix
nodePositions = zeros(numNodes, 3); % Including z = 0
% Random generation of rectangular obstacles (buildings) without overlap
numBuildings = 5; % Number of buildings
buildings = struct('x', [], 'y', [], 'width', [], 'height', []);
for i = 1:numBuildings
validBuilding = false;
maxAttempts = 1000;
attempts = 0;
while ~validBuilding && attempts < maxAttempts
attempts = attempts + 1;
% Random dimensions for the building (between 20x20 and 80x80 meters)
width = 20 + rand * 60;
height = 20 + rand * 60;
% Random position for the building
x = rand * (areaSide - width);
y = rand * (areaSide - height);
% Check for overlap with existing buildings
overlap = false;
for j = 1:i-1
if ~(x + width < buildings(j).x || buildings(j).x + buildings(j).width < x || ...
y + height < buildings(j).y || buildings(j).y + buildings(j).height < y)
overlap = true;
break;
end
end
if ~overlap
validBuilding = true;
buildings(i).x = x;
buildings(i).y = y;
buildings(i).width = width;
buildings(i).height = height;
end
end
if ~validBuilding
warning("Could not place building %d without overlaps after %d attempts.", i, maxAttempts);
end
end
% Node generation with or without maximum distance constraint
for i = 1:numNodes
validPosition = false;
nodeAttempts = 0;
maxNodeAttempts = 1000;
while ~validPosition && nodeAttempts < maxNodeAttempts
nodeAttempts = nodeAttempts + 1;
newPosition = rand(1, 2) * areaSide;
if maintainDistanceConstraint && i > 1
distances = sqrt(sum((nodePositions(1:i-1, 1:2) - newPosition).^2, 2));
distanceSatisfied = any(distances <= maxDistance);
else
distanceSatisfied = true;
end
insideBuilding = false;
for j = 1:numBuildings
building = buildings(j);
if newPosition(1) > building.x && newPosition(1) < (building.x + building.width) && ...
newPosition(2) > building.y && newPosition(2) < (building.y + building.height)
insideBuilding = true;
break;
end
end
if distanceSatisfied && ~insideBuilding
validPosition = true;
nodePositions(i, 1:2) = newPosition;
end
end
if ~validPosition
warning("Could not position node %d respecting constraints after %d attempts.", i, maxNodeAttempts);
end
end
% Randomly select the transmitter and receiver
randomIndices = randperm(numNodes, 2);
transmitterIndex = randomIndices(1);
receiverIndex = randomIndices(2);
% Create the transmitter node
sourceNode = bluetoothLENode("broadcaster-observer", ...
Name="Source Node", ...
Position=nodePositions(transmitterIndex, :), ...
TransmitterPower=transmissionPower); % Set transmission power
% Create the receiver node
destinationNode = bluetoothLENode("broadcaster-observer", ...
Name="Destination Node", ...
Position=nodePositions(receiverIndex, :), ...
TransmitterPower=transmissionPower); % Set transmission power
% Configure Mesh profile for the transmitter node
cfgMeshSource = bluetoothMeshProfileConfig(ElementAddress="0001");
sourceNode.MeshConfig = cfgMeshSource;
% Configure Mesh profile for the receiver node
cfgMeshDestination = bluetoothMeshProfileConfig(ElementAddress="0002");
destinationNode.MeshConfig = cfgMeshDestination;
% Create relay nodes
relayNodes = cell(1, numNodes - 2); % Initialize the relay nodes array
relayCounter = 1;
for i = 1:numNodes
if i ~= transmitterIndex && i ~= receiverIndex
relayNode = bluetoothLENode("broadcaster-observer", ...
Name=sprintf("Relay Node %d", relayCounter), ...
Position=nodePositions(i, :), ...
TransmitterPower=transmissionPower); % Set transmission power
relayNodes{relayCounter} = relayNode; % Add relay node
relayCounter = relayCounter + 1;
end
end
% Create network traffic
traffic = networkTrafficOnOff(OnTime=inf, DataRate=1, PacketSize=15, GeneratePacket=true);
addTrafficSource(sourceNode, traffic, SourceAddress="0001", DestinationAddress="0002", TTL=10);
% Create the `nodes` array
nodes = [{sourceNode}, relayNodes, {destinationNode}];
addNodes(networkSimulator, [nodes{:}]);
% Calculate active links and received power
linkMatrix = zeros(numNodes); % Adjacency matrix
linkPower = zeros(numNodes, numNodes); % Residual power for links
minResidualPower = inf; % Minimum power value
maxResidualPower = -inf; % Maximum power value
fprintf("\nActive links in the mesh network:\n");
for i = 1:numNodes
%{
- Check the distance between nodes.
- Check for obstacles (buildings) on the link.
- Calculate received power considering path loss.
- Register the link as active if the received power exceeds the threshold.
- Update the minimum and maximum residual power values.
- Print active link information.
%}
for j = 1:numNodes
if i ~= j
distance = pdist2(nodePositions(i, :), nodePositions(j, :));
if distance <= maxLinkDistance
% Check if a building is between the nodes
buildingAttenuation = false;
midX = (nodePositions(i, 1) + nodePositions(j, 1)) / 2;
midY = (nodePositions(i, 2) + nodePositions(j, 2)) / 2;
for k = 1:numBuildings
building = buildings(k);
if midX > building.x && midX < (building.x + building.width) && ...
midY > building.y && midY < (building.y + building.height)
buildingAttenuation = true;
break;
end
end
if ~buildingAttenuation
% Calculate path loss
pathLoss = calculateFreeSpacePathLoss(distance, frequency);
receivedPower = transmissionPower - pathLoss;
if receivedPower >= minReceivedPower
linkMatrix(i, j) = 1; % Active link
linkPower(i, j) = receivedPower;
minResidualPower = min(minResidualPower, receivedPower);
maxResidualPower = max(maxResidualPower, receivedPower);
fprintf("Node %d -> Node %d: Distance = %.2f m, Received Power = %.2f dBm\n", ...
i, j, distance, receivedPower);
end
end
end
end
end
end
% Run the simulation
simulationTime = 10;
run(networkSimulator, simulationTime);
% Retrieve and display statistics
sourceStats = statistics(sourceNode);
destinationStats = statistics(destinationNode);
relayStats = cellfun(@statistics, relayNodes, 'UniformOutput', false);
disp("Transmitter node statistics:");
disp(sourceStats);
disp("Receiver node statistics:");
disp(destinationStats);
% Calculate and display KPIs
latency = kpi(sourceNode, destinationNode, "latency", Layer="App");
plr = kpi(sourceNode, destinationNode, "PLR", Layer="App");
pdr = kpi(sourceNode, destinationNode, "PDR", Layer="App");
fprintf("\nBluetooth Mesh Network KPIs:\n");
fprintf("Latency: %.2f ms\n", latency * 1000); % Converted to milliseconds
fprintf("Packet Loss Ratio (PLR): %.2f\n", plr);
fprintf("Packet Delivery Ratio (PDR): %.2f\n", pdr);
% Visualize the mesh network
figure;
hold on;
% Draw buildings
for i = 1:numBuildings
rectangle('Position', [buildings(i).x, buildings(i).y, buildings(i).width, buildings(i).height], ...
'FaceColor', [0.5 0.5 0.5], 'EdgeColor', 'k');
end
% Draw nodes
for i = 1:numNodes
if i == transmitterIndex
scatter(nodePositions(i, 1), nodePositions(i, 2), 250, 'r', 'filled'); % Transmitter (red)
elseif i == receiverIndex
scatter(nodePositions(i, 1), nodePositions(i, 2), 250, 'g', 'filled'); % Receiver (green)
else
scatter(nodePositions(i, 1), nodePositions(i, 2), 200, 'b', 'filled'); % Other nodes (blue)
end
end
% Draw links
for i = 1:numNodes
for j = 1:numNodes
if linkMatrix(i, j) == 1
powerNorm = (linkPower(i, j) - minResidualPower) / ...
(maxResidualPower - minResidualPower);
linkColor = [1 - powerNorm, powerNorm, 0]; % Gradient from red to green
plot([nodePositions(i, 1), nodePositions(j, 1)], ...
[nodePositions(i, 2), nodePositions(j, 2)], '-', ...
'Color', linkColor, 'LineWidth', 2);
end
end
end
title('Distribution of Nodes, Buildings, and Active Links in the Bluetooth Mesh Network');
xlabel('X Position (meters)');
ylabel('Y Position (meters)');
xlim([0 areaSide]);
ylim([0 areaSide]);
grid on;
axis equal;
hold off;
Currently, my approach is as follows:
I am trying to adjust the simulation to only process data and compute metrics using the active links, but i am unsure how to implement this next step. I also know from the official MATLAB documentation that there is a way to account for attenuation directly using built-in library functions, but i am struggling to integrate this feature into the programming logic.
What i expect is for the script to compute and return realistic, non-zero values for Latency, Packet Loss Ratio (PLR), and Packet Delivery Ratio (PDR) when the transmitter and receiver are actively linked.
Upvotes: 0
Views: 27