File size: 4,509 Bytes
eeb730c
 
 
 
4f9e349
eeb730c
 
bcf306a
eeb730c
 
4f9e349
eeb730c
 
 
 
bcf306a
eeb730c
 
 
 
 
 
 
 
 
 
 
 
bcf306a
eeb730c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bcf306a
eeb730c
 
 
 
 
bcf306a
eeb730c
 
 
 
bcf306a
eeb730c
 
 
 
 
 
 
bcf306a
eeb730c
 
 
 
bcf306a
eeb730c
 
 
 
 
bcf306a
eeb730c
 
 
 
bcf306a
eeb730c
 
 
 
 
 
4f9e349
eeb730c
 
bcf306a
eeb730c
 
bcf306a
eeb730c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import pywifi
from pywifi import const
import pygame
import threading
import time
import numpy as np
from scipy.optimize import least_squares

# Initialize pygame
pygame.init()

# Set up display
WIDTH, HEIGHT = 800, 600
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Real-Time Wi-Fi Signal Mapping")

# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
AP_COLOR = (0, 255, 0)
DEVICE_COLOR = (255, 0, 0)
TEXT_COLOR = (255, 255, 255)

# Initialize font
FONT = pygame.font.SysFont('Arial', 16)

# Wi-Fi scanner class
class WiFiScanner(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.daemon = True  # Allow thread to exit when main program exits
        self.wifi = pywifi.PyWiFi()
        self.iface = self.wifi.interfaces()[0]
        self.scan_results = []
        self.running = True

    def run(self):
        while self.running:
            self.iface.scan()
            time.sleep(1.5)  # Wait for scan to complete
            self.scan_results = self.iface.scan_results()
            time.sleep(1)

    def stop(self):
        self.running = False

# Function to estimate distance from RSSI
def rssi_to_distance(rssi, tx_power=-40, n=2):
    """
    Estimate distance based on RSSI.
    :param rssi: Received signal strength (dBm)
    :param tx_power: Transmit power (dBm)
    :param n: Path-loss exponent (environmental factor)
    :return: Estimated distance in meters
    """
    return 10 ** ((tx_power - rssi) / (10 * n))

# Function to perform trilateration
def trilaterate(positions, distances):
    """
    Estimate position based on distances to known points.
    :param positions: List of tuples [(x1,y1), (x2,y2), (x3,y3)]
    :param distances: List of distances [d1, d2, d3]
    :return: Estimated position (x, y)
    """
    def residuals(point, positions, distances):
        return [np.linalg.norm(np.array(point) - np.array(pos)) - d for pos, d in zip(positions, distances)]

    # Initial guess
    x0 = np.mean(positions, axis=0)
    res = least_squares(residuals, x0, args=(positions, distances))
    return res.x

# Main function
def main():
    scanner = WiFiScanner()
    scanner.start()

    running = True
    clock = pygame.time.Clock()

    # Simulated positions of known Wi-Fi APs (for demonstration purposes)
    wifi_aps = {}

    # Main loop
    while running:
        WINDOW.fill(BLACK)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # Draw device at center
        device_pos = (WIDTH // 2, HEIGHT // 2)
        pygame.draw.circle(WINDOW, DEVICE_COLOR, device_pos, 5)
        device_text = FONT.render('Your Device (0,0)', True, TEXT_COLOR)
        WINDOW.blit(device_text, (device_pos[0] + 10, device_pos[1]))

        # Process scan results
        aps = scanner.scan_results
        positions = []
        distances = []

        for ap in aps:
            ssid = ap.ssid
            bssid = ap.bssid
            rssi = ap.signal  # RSSI value
            # For this demo, assign random positions to APs if not already assigned
            if bssid not in wifi_aps:
                wifi_aps[bssid] = (np.random.randint(50, WIDTH - 50), np.random.randint(50, HEIGHT - 50))

            # Estimate distance
            distance = rssi_to_distance(rssi)
            positions.append(wifi_aps[bssid])
            distances.append(distance)

            # Draw AP
            ap_pos = wifi_aps[bssid]
            pygame.draw.circle(WINDOW, AP_COLOR, ap_pos, 5)
            ap_text = FONT.render(f'{ssid} ({rssi}dBm)', True, TEXT_COLOR)
            WINDOW.blit(ap_text, (ap_pos[0] + 10, ap_pos[1]))

            # Draw line representing distance
            pygame.draw.line(WINDOW, WHITE, device_pos, ap_pos, 1)
            # Draw circle representing estimated distance
            pygame.draw.circle(WINDOW, WHITE, ap_pos, int(distance), 1)

        # If we have at least 3 APs, perform trilateration
        if len(positions) >= 3:
            estimated_pos = trilaterate(positions[:3], distances[:3])
            pygame.draw.circle(WINDOW, (0, 0, 255), (int(estimated_pos[0]), int(estimated_pos[1])), 5)
            est_text = FONT.render('Estimated Position', True, TEXT_COLOR)
            WINDOW.blit(est_text, (int(estimated_pos[0]) + 10, int(estimated_pos[1])))

        pygame.display.flip()
        clock.tick(30)  # Limit to 30 FPS

    scanner.stop()
    pygame.quit()

if __name__ == "__main__":
    main()