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() |