MrStashley / Android-RasPi-WifiP2P-Communication

repo that contains a template/example of setting up a Wifi Direct connection between a Raspberry Pi Zero W and an android phone. Contains config scripts as well as code for setting up a connection, setting up a TCP socket, and exchanging data on both the android and the pi
11 stars 2 forks source link

Trying to setup raspberry pi zero 2 with wifi direct #1

Open shaunaa126 opened 1 year ago

shaunaa126 commented 1 year ago

Hello @MrStashley, first of all thank you so much for sharing with the community your code and how to establish using Bluetooth and WifiDirect connectivity to Android.

I am trouble following the directions to get my setup working, I was hoping you have some time to help. For now I am skipping the Bluetooth initiation, I am just trying to get my Raspberry PI Zero 2 W working with WifiDirect so that the android app you have can connect to it. Here is what I have done so far:

BLE_INIT_FAILED = "0"; BLE_INIT_SUCCESS = "1"; CENTRAL_CONNECTED = "2"; DEVICE_NAME = "3"; START_CONNECT = "4"; CENTRAL_DISCONNECTED = "5"; DISCONNECT_WFD = "7"; START_SOCKET = "8";

P2P_FIND_COMMAND = "wpa_cli -i p2p-dev-wlan0 p2p_find"; GET_P2P_PEERS_COMMAND = "for i in $( wpa_cli -i p2p-dev-wlan0 p2p_peers ); do echo -n \"$i \n\"; wpa_cli -i p2p-dev-wlan0 p2p_peer $i | grep -E \"device_name=\"; done"; P2P_GROUP_REMOVE_COMMAND = "wpa_cli -ip2p-dev-wlan0 p2p_group_remove $(ip -br link | grep -Po 'p2p-wlan0-\d+')" ;

def P2P_CONNECT_COMMAND(macd):

python macro B-). idk if this is a thing that is done in standard python style but idc i'm doin it

return "wpa_cli -i p2p-dev-wlan0 p2p_connect " + macd + " pbc";

class WifiDirectConnector:

def __init__(self):
    self.device_name = "";
    self.connected = False;
    self.main();

def main(self):
    #comPort = "/dev/ttyACM0"; #port that will be used if one is not specified (COM3 on windows)
    #baud = 9600; #default baudrate
    #if(len(sys.argv) > 1): #accept other com port and baudrate if one is given
    #    comPort = sys.argv[1];
    #    if(len(sys.argv) > 2):
    #        baud = sys.argv[2];

    #serialConn = serial.Serial(comPort,baud, timeout=.1); #creates an object that watches the given port at the given baudrate

    #while True:
    data = sys.argv;
        #data = serialConn.readline()[:-2] #reads a line; the last byte is a newline character and we don't need it
        if data:
            command_code = sys.argv[1];
            print("Command registered: " + command_code);
            if(len(sys.argv) > 2):
              value = sys.argv[2];

            if(command_code == DEVICE_NAME):
                self.set_device_name(value);
            if(command_code == CENTRAL_CONNECTED):
                self.central_connected();
            if(command_code == CENTRAL_DISCONNECTED):
                self.central_disconnected();
            if(command_code == START_CONNECT):
                self.start_connect();
            if(command_code == DISCONNECT_WFD):
                self.disconnect();
            if(command_code == START_SOCKET):
                self.wifi_direct_connected();

            print(data);

def disconnect(self):
    self.connected = False;
    print("disconnecting");

    if (not self.p2p_group_remove()):
        print("Disconnect failed");
    else:
        print("Disconnected");

def start_connect(self):
    if(self.device_name == ""):
        return;

    print("Starting connection with " + str(self.device_name));

    if(not self.p2p_find()):
        print("p2p_find failed. stopping");
        return;

    macd = self.get_mac_address();

    print("got macd: " + str(macd));

    if(self.p2p_connect(macd)):
        print("successfully connected to " + str(self.device_name));
        self.connected = True;

    else:
        print("Connection failed. Something went wrong");

def central_connected(self):
    self.connected = False;
    if(not self.p2p_find()):
        print("p2p_find failed. stopping");
        return;

def central_disconnected(self):
    self.device_name = "";

def set_device_name(self, pdevice_name):
    pdevice_name = str(pdevice_name)[2:-1];
    print("Setting device name: " + str(pdevice_name));
    self.device_name = pdevice_name;

def p2p_find(self):
    to_return = False;
    p2p_find_file = os.popen(P2P_FIND_COMMAND, 'r');
    cmd_output = p2p_find_file.readline();

    if(cmd_output == "OK\n"):
        to_return = True;

    p2p_find_file.close();

    return to_return;

def get_mac_address(self):
    to_return = "";

    get_peers_file = os.popen(GET_P2P_PEERS_COMMAND, 'r');
    while(True):
        macd = get_peers_file.readline()[:-1];
        device_name = get_peers_file.readline()[12:-1];

        if(macd == "" or device_name == ""):
            break;

        if(device_name == self.device_name):
            to_return  = macd;
            break;

    get_peers_file.close();

    return to_return;

def p2p_connect(self, macd):
    to_return = False;

    p2p_connect_file = os.popen(P2P_CONNECT_COMMAND(macd), 'r');
    cmd_output = p2p_connect_file.readline();

    if(cmd_output == "OK\n"):
        to_return = True;

    return to_return;

def p2p_group_remove(self):
    to_return = False;

    p2p_group_remove_file = os.popen(P2P_GROUP_REMOVE_COMMAND, "r");
    cmd_output = p2p_group_remove_file.readline();

    if(cmd_output == "OK\n"):
        to_return = True;

    return to_return;

def wifi_direct_connected(self):
    self.socket = WifiDirectSocket();
    self.socket.create_socket();
    self.socket.accept();

if name == "main": wifi_direct_conn = WifiDirectConnector();

MrStashley commented 1 year ago

Hey! Nice to hear that you are taking interest in my code

So something about the way I did this that I'm realizing I did not make super clear except in the second readme, is that I am actually using the ble to get the wifi direct connection. Something about the wifi direct protocol is that it is designed specifically to have some kind of user input involved in the connection. I was looking for an automated solution where I wouldn't have to require any user input on the raspberry pi side. What I do is I use the ble connection to tell the pi to start connecting to the android phone

So what I am doing is I have an Arduino Nano 33 BLE sense connected to my raspberry pi zero via usb. Then I have arduino code included in this repo that connects with the android phone and listens for the android to tell it to connect. Then it tells the pi over serial.

So unfortunately my code won't work for you as is unless you include the arduino portion, but I can maybe give you some help/ direction to help you do what you want to do. Do you care if the user has to interact with the pi in order to make the connection work? If not you can tweak my code and have it working pretty easily. Another thing you can do that would require a little bit more work is implement the ble service on the raspberry pi and hook it up to my code. But if your project allows, grabbing a cheap ble enabled arduino would be the easiest solution.

You can also experiment with other ways to create a second communication channel, like perhaps nfc or sound or something like that, and you could also attempt to do some wifi direct research and try and take this farther than I was able to. I wasn't able to get the connection to work without a second channel, but it could be possible.

Hope this is helpful, and feel free to hit me up with follow up questions I am always happy to help!

elioscordo commented 11 months ago

Hey, thank you for the code. It would be great if you could have an interactive version, for my use case (https://github.com/elioscordo/hoverdroid) I would like to get images from android cameras and send back serial commands. and I don't mind the interaction.

thebrrt commented 1 month ago

@MrStashley

Thank you so much for uploading your bash script. That alone is going to save me HOURS of yelling at ChatGPT and looking up documentation.

I'm trying to implement WiFi Direct in a project of mine involving a Pi Zero 2 W (without need for the BLE features). I don't want to make any promises, but I'll be working on modifying the Python script to just take an argument for the device name, no BLE business

EDIT: Finished updating it. Haven't had a chance to test it yet though. Will create PR when tested and validated