So yesterday I had all this working on a Raspberry Pi talking to Unity (Python 2.7 on Pi, Unity 2017) then the memory card failed and I had to build a new one. The new install is Python 3.5 and same Unity as before. The code I wrote I think is roughly the same though with troubleshooting it's gotten changed a bit (print statements changed etc for 3.5). Either way I'm getting an error on the Unity side saying the connected party did not properly respond after a period of time. I've pinged the IP and the socket from the PC and also other computers and it's accessible but just the Unity application won't talk to the Pi Server. Can someone see where I've messed up in my code? Firewall is disabled on the PC and the IP/Port addresses for the Pi are correct.
Python on Raspberry Pi
import socket
import sys
backlog = 1
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.3.232', 12345))
s.listen(1)
while True:
print ('waiting for a connection')
connection, client_address = s.accept()
try:
print ('connection from', client_address)
while True:
data = connection.recv(16)
print ('received "%s"' % data)
if data:
print ('sending data back to the client')
connection.sendall(data)
else:
print ('no more data from', client_address)
break
finally:
print("closing socket")
cient.close()
s.close()
C# on Unity
using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Net.Sockets;
public class ClientSocket : MonoBehaviour {
bool socketReady = false;
TcpClient mySocket;
public NetworkStream theStream;
StreamWriter theWriter;
StreamReader theReader;
public String Host = "192.168.3.232";
public Int32 Port = 12345;
void Start() {
setupSocket ();
}
public void setupSocket() { // Socket setup here
try {
mySocket = new TcpClient(Host, Port);
theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
theReader = new StreamReader(theStream);
socketReady = true;
}
catch (Exception e) {
Debug.Log("Socket error:" + e); // catch any exceptions
}
}
Error from Unity console:
Socket error:System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
Possibly the firewall on the Raspberry Pi is still on. Check your iptables.
You can test that if you make a small sockettest application in python on your Raspberry Pi.
# Colin. I copied and pasted your Python code into Python 2.7.9 running on my Raspberry Pi and also your Client Socket in Unity running on my PC and it works fine. Simply changed the IP address and all worked fine. I know this is a late response but it may help someone else.
Related
So I have two machines, a laptop and a raspberry pi 4. I am trying to send UDP packets to the pi from my laptop.
C# code running on laptop:
public static void SendMessage(string msg, IPEndPoint endPoint)
{
using (UdpClient client = new())
{
var message = Encoding.ASCII.GetBytes(msg);
client.Send(message, message.Length, endPoint);
}
}
which I am calling in Main():
static void Main(string[] args)
{
new Thread(()=>
{
while (true)
{
for (int i = 0; i < 256; i++)
Networking.UDP.SendMessage("Hello World!", new IPEndPoint(IPAddress.Parse($"192.168.1.{i}"), 11000));
Console.WriteLine("Message sent");
Thread.Sleep(1000);
}
}).Start();
}
On the raspberry pi I am running this simple python script:
import socket
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
local_port = 11000
UDPsocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPsocket.bind((local_ip, local_port))
print("Now listening on port "+str(local_port))
while (True):
bytesAddressPair = UDPsocket.recvfrom(1024)
message = bytesAddressPair[0]
address = bytesAddressPair[1]
print(str(address)+" : "+str(message))
However, the raspberry pi program does not seem to receive any messages. What am I doing wrong?
(Edit: First comment on this answer explains the reason)
Figured it out.
On the pi, in order to get the local IP I was using
socket.gethostbyname(socket.gethostname())
which apparently was not the correct way to get the local IP. Someone might be able to further explain why that was not producing the correct outcome.
To solve the issue I just ran hostname -I on the pi to find the correct local IP and used that in the code, with the final receiving code being:
import socket
local_ip = "192.168.1.10" #Your local IP here obtained from terminal
local_port = 11000
UDPsocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPsocket.bind((local_ip, local_port))
print("Now listening on port "+str(local_port))
while (True):
bytesAddressPair = UDPsocket.recvfrom(1024)
message = bytesAddressPair[0]
address = bytesAddressPair[1]
print(str(address)+" : "+str(message))
im trying to talk between my java app and python client. But it cant seem to connect.
I am not sure if it is because of a wrong IP-adress. Because i read somewhere that you can use the IP of the PC to connect to the virtual device, but i also used the 10.0.x.x address of the virtual device which also doesnt seem to work. In IntelliJ my code does seem to work, only not with the app.
my python client code:
import socket
HOST = "172.20.10.12"
PORT = 8080
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
print('connected')
sock.sendall(b'Hello!')
data = sock.recv(1024)
print("1", data, '\n')
sock.sendall(b'Bye\n')
data = sock.recv(1024)
print("2", data, '\n')
print("Socket closed")
sock.close()
And this is the receiving side of my app: StartReceive.java:
package com.example.test;
import java.io.IOException;
class StartReceive implements Runnable {
#Override
public void run() {
try {
Receive.startReceive();
} catch (IOException e) {
e.printStackTrace();
}
}
}
My receive.java:
public class Receive {
static String fromClient;
static String toClient;
public static void startReceive() throws IOException {
ServerSocket server = new ServerSocket(8080);
System.out.println("wait for connection on port 8080");
boolean run = true;
while (run) {
Socket client = server.accept();
System.out.println("got connection on port 8080");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
fromClient = in.readLine();
System.out.println("received: " + fromClient);
if (fromClient != null) {
toClient = "message is received on server";
System.out.println("send: message is received");
out.println(toClient);
fromClient = in.readLine();
System.out.println("received: " + fromClient);
if (fromClient.equals("Bye")) {
toClient = "bye received on server";
System.out.println("send: bye received on server");
out.println(toClient);
client.close();
run = false;
System.out.println("socket closed");
}
}
}
}
}
And then i call it in my mainactivity like this:
To debug the connection issue, first try and set the IP to "localhost" on the client.
You might also usefully print server.getInetAddress() on the server side. It's possible you're not listening on the specific address that your client wanted to connect to.
I would debug this as follows:
Run the server
On the server PC, type the command 'netstat -a -p tcp' (this is Windows, right) and look for something you recognize as the server. The "virtual android device" must show up on the physical PC, since the physical PC is the thing that is physically connected to the physical network.
Try and connect to that server using some utility or other; I prefer telnet. 'telnet '. You should at least see your server's "connected" message on the server console output.
If this all goes well, you now know the server is basically functional.
Once your client is connected, you have a further bug:
You are sending 6 bytes, no newline.
sock.sendall(b'Hello!')
You are expecting to receive data terminated by a newline.
fromClient = in.readLine();
Your receiver is still waiting for the end of the line.
I am trying to connect my Arduino Nano Connect RP2040 with my machine using Python (3.8.8). I want to use WiFi communication protocol and I am currently working on a client-server socket.
Since I am not so familiar with this communication protocol I am following this thread which looks to perform good results. Of course, this thread talks about Ethernet and I am readapting using WiFiNina library which has been developed by Arduino in order to use the module.
Here the code I am running on Arduino:
#include <SPI.h>
#include <WiFiNINA.h>
#include <ArduinoJson.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0x08, 0x3A, 0xF2, 0xB1, 0x9D, 0xE0 };
IPAddress ip(192,168,43,98);
// Enter the IP address of the server you're connecting to:
IPAddress server(192,168,0,4);
// Initialize the WiFi client library
// with the IP address and port of the server
WiFiClient client;
char ssid[] = "xxxxx"; // the name of your network
char username[] = "xxxxxxx";
char pass[] = "xxxxxxx";
void setup() {
// start the Wifi connection:
WiFi.beginEnterprise(ssid, username, pass);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 13380)) {
Serial.println("connected");
}
else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
}
void loop()
{
//JSON stuff
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["sensor"] = "gps";
root["time"] = 42;
JsonArray& data = root.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
char json[100];
root.printTo(json);
Serial.print(json);
// if there are incoming bytes available
// from the server, read them and print them:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// as long as there are bytes in the serial queue,
// read them and send them out the socket if it's open:
if (client.connected()) {
client.print(json);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing:
while(true);
}
}
I have used some functions from WiFiNina (for example .beginEnterprise() in order to connect Arduino to the network).
For what server concerns, here the code in Python:
import socket
import sys
import json
# host = '127.0.0.1'
host = '192.168.0.4'
port = 13380
address = (host, port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(address)
server_socket.listen(5)
# server_socket.connect(address)
print ("waiting for a connection . . .")
conn, address = server_socket.accept()
print ("Connection established: "), address
while True:
output = conn.recv(84048);
if output.strip() == "disconnect":
conn.close()
sys.exit("Disconnect message received - terminate the connection")
conn.send("dack")
elif output:
print(output)
data = json.load(output)
print(data)
I am not interested in sending JSON data, like I have already mentioned I am just readapt the code in thread. I actually need to send data in real-time, but step-by-step :-)
The problem is that I cannot establish the connection between Arduino (client) and Python (server).
From server part, I actually got this error:
Traceback (most recent call last):
File "server_arduino.py", line 18, in <module>
server_socket.bind(address)
OSError: [WinError 10049] The requested address is not valid in its context
For some reasons which I actually did not understand yet, if I would change host in 127.0.0.1 (following suggestions here) the server part starts to work, and it stucks in waiting for a connection . . . printed in my console, because it needs a client to connect.
At this stage, running my Arduino code I got this:
connecting...
connection failed
{"sensor":"gps","time":42,"data":[48.75608,2.302038]}
disconnecting.
So, it does mean to me that I was able to connect to WiFi, but not to server.
Does anyone give me any suggestions?
I know I am really beginner and any suggestions would be really appreciated.
So I am trying to send data from the raspberry pi to unity.
I trying to create socket server to do so.
I can get the socket server running on the raspberry pi and can also look at the port with netstat -tulpn | grep :5005 in the terminal on the machine where the python script is running.
I also tried it on my mac and it also showed up as a TCP-server.
However when I try to connect to the same port and ip via Unity or on another machine it doesn't work. I also can't seem to find the port when listing all of the ports with netstat.
Unity spits out a "Connection refused" error.
Here is the code in Unity in C#
using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Net.Sockets;
public class ClientSocket : MonoBehaviour
{
bool socketReady = false;
TcpClient mySocket;
public NetworkStream theStream;
StreamWriter theWriter;
StreamReader theReader;
public String Host = "192.168.8.137";
public Int32 Port = 5005;
void Start()
{
setupSocket();
TextMessage("SocketTest");
}
public void setupSocket()
{ // Socket setup here
try
{
mySocket = new TcpClient(Host, Port);
theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
theReader = new StreamReader(theStream);
socketReady = true;
}
catch (Exception e)
{
Debug.Log("Socket error:" + e); // catch any exceptions
}
}
public void TextMessage(string message)
{
if (socketReady == true)
{
theWriter.Write(message);
theWriter.Flush();
}
}
}
here is the code in python, which should be running on the raspberry pi.
import socket
import sys
backlog = 1
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.8.137', 5005))
s.listen(1)
try:
print ("is waiting")
client, address = s.accept()
while 1:
data = client.recv(size)
if data:
print (data)
finally:
print("closing socket")
cient.close()
s.close()
I'm new to socket servers, but I really trying to accomplish a connection here.
Thanks for reading!
am pretty sure you need to encode the data that you about to send in c# TcpClient
adding an example from my final project:
string data = "Hello Server!"; //the message in string (important it will be string)
byte[] msg = Encoding.Unicode.GetBytes(data); //encoded the message using unicode (utf-16)
NetworkStream stream = client.GetStream(); //get the tcp client stream
stream.Write(msg, 0, msg.Length); //write the message to the stream
and in the server you suppose to have something like that:
msg = clnt.recv(1024) #reciving the data
msg = msg.decode("utf-16") #decoding the data
print(msg) #printing the data
and i think thats it
and i would recommend using port above 10000 because most of the ports can be used
I'm putting a drone together and I have a Python script running on a Raspberry Pi taking Xbox controller inputs and turning them into a Python output I can use like:
if (event.code == 'ABS_Y'):
if event.state in range(25001,32768):
print("Full Throttle Reverse Left")
kit.motor1.throttle = -1
The controller however needs to be connected to the Raspberry Pi and that limits my range. Can I connect the controller to a laptop and send those outputs to the Raspberry Pi over a router to execute Python commands?
I'm new to programming as a whole and I'm certain there are smarter ways of doing this so any assistance or alternate suggestions are welcome.
I recommend using a socket for your application.
The client (running on the laptop) could take the xbox controller inputs and send it to the server (running on raspberry pi).
Here is a simple socket application:
Client:
import socket
ip = "192.168.xxx.yyy" # IP of Raspberry Pi
# connect to server
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((ip, 8080))
print("CLIENT: connected")
# send a message
msg = "I am CLIENT"
client.send(msg.encode())
# recive a message and print it
from_server = client.recv(4096).decode()
print("Recieved: " + from_server)
# exit
client.close()
Server:
import socket
ip = "192.168.xxx.yyy" # IP of Raspberry Pi
# start server
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv.bind((ip, 8080))
serv.listen(5)
print("SERVER: started")
while True:
# establish connection
conn, addr = serv.accept()
from_client = ''
print("SERVER: connection to Client established")
while True:
# receive data and print
data = conn.recv(4096).decode()
if not data: break
from_client += data
print("Recieved: " + from_client)
# send message back to client
msg = "I am SERVER"
conn.send(msg.encode())
# close connection and exit
conn.close()
break
More information can be found here.
Here's how to do it:
In the Raspberry Pi, make sure you have OpenSSH (you probably do, try running apt install openssh-server if you cannot connect), and you also need the OpenSSH client on your computer(the 'ssh' command).
First, let's look at your script. On your Python Script, you can write something like this to output JSON:
print(json.dumps(your message here....))
On your Raspberry Pi, find out your private IP. You can do something like:ifconfig | grep 192
On your computer, type:
ssh pi#<your private IP> 'python <your script path, example: /home/pi/Desktop/script.py>'
You may need to change pi to the username that you use on your Raspberry Pi.
The script will run on your Raspberry Pi, and you will get the JSON output on your computer! You can easily automate this using subprocess and json.loads . This way is also secure, because SSH uses encryption.