-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
This page will help you get started with collecting WiFi CSI data with python. Before following this guide, make sure you have configured a CSI transmitter and receiver using one of the following guides:
When using Python, it is often best to setup a virtual environment to isolate your dependencies. To do this in a new project directory, run the following command:
python3 -m venv .venvThis will create a python virtual environment in the .venv directory. To use this environment source the activation script. You should do this every time you use the python environment in the terminal, or your IDE may activate this automatically (VS Code with the python extension does):
. ./.venv/bin/activateInstall the csi-py python package to make collecting csi data easier.
pip install csi-pyFirst, create a python file, which can be called anything, but lets use csi_collection.py. In this python file, add the following code.
import sys
from csi_py.csireader import CSIReader
def print_rssi(data):
print(f"RSSI: {data.meta['rssi']}")
def main():
if len(sys.argv) < 2:
print("Usage: python main.py <serial_port>")
sys.exit(1)
port = sys.argv[1]
reader = CSIReader(port, data_callback=print_rssi, rate=20)
try:
reader.run()
except KeyboardInterrupt:
reader.stop()
print("Stopped.")
if __name__ == "__main__":
main()Let's first look at the first couple of lines:
import sys
from csi_py.csireader import CSIReaderFirst, we import python's built-in sys package which will allow us to take in command line arguments. In addition, we will import the CSIReader class from the csi-py package's csireader file.
Then, we define a callback function, called print_rssi, to handle CSI data. In the main function, we process the first command line argument with the following snippet:
if len(sys.argv) < 2:
print("Usage: python main.py <serial_port>")
sys.exit(1)
port = sys.argv[1]To collect the CSI data, we will create an object of the CSIReader class. To do so, we'll define a port, a callback function, and a refresh rate. By calling the run function of the CSIReader class, the callback function will be called passing one object that represents the CSI data.
The data object has the following format:
class CSIData:
def __init__(self, amplitude, phase, raw, meta):
self.amplitude = amplitude # CSI data amplitude array
self.phase = phase # CSI data phase array
self.raw = raw # CSI data raw array
self.meta = meta # CSI data metadataThe meta object is a python dictionary with the following fields:
channel # the WiFi signal channel
bandwidth # WiFi signal bandwidth
noise_floor # WiFi noise floor
rate_index # WiFi physical layer data rate
rssi # Received signal strength indicator
mac # Sending device MAC address.To run this script, after sourcing your virtual environment, run the command:
python3 csi_collection.py <serial_port>Be sure to replace <serial_port> with the serial port of your ESP32 device. To find this on Mac, for example, run the command in terminal: ls /dev/tty.usb*. The port should be listed in the terminal.
Say we want to make a script that adds the values in the CSI raw data array. This would look like the following:
import sys
from csi_py.csireader import CSIReader
def sum_raw(data): # The callback function has been renamed.
raw = data.raw
output = sum(raw) # Not doing anything with this now, but it can be used.
def main():
if len(sys.argv) < 2:
print("Usage: python main.py <serial_port>")
sys.exit(1)
port = sys.argv[1]
reader = CSIReader(port, data_callback=sum_raw, rate=20)
try:
reader.run()
except KeyboardInterrupt:
reader.stop()
print("Stopped.")
if __name__ == "__main__":
main()