Unity3D UnityWebRequest.Put Method Slow Response - python

Let me preface this by saying I have seen similar posts like this on this site as well as other sites, but have not seen a clear solution to the problem yet. I have created a simple python server with do_GET and do_PUT methods, and corresponding Unity C# code with GetRequest() and PutRequest() methods. I have already tested the Get methods and they run smoothly. On the other hand, the client-side (Unity C#) PutRequest() method only yields once every second or so (which seems unreasonably slow). My frame rate is sitting around 150-160 fps. I thought it would be considerably faster considering I copied the very simple Upload() method from the Unity documentation at https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.Put.html
Below is the client-side Unity C# code I am currently using:
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class WebRequest0 : MonoBehaviour
{
public Transform client;
private string[] pos;
void Start()
{
StartCoroutine(GetRequest());
StartCoroutine(PutRequest());
}
private IEnumerator GetRequest()
{
while (true)
{
UnityWebRequest www = UnityWebRequest.Get("http://localhost");
yield return www.SendWebRequest();
string coordinates = www.downloadHandler.text;
pos = coordinates.Split(',');
if (client && pos.Length > 0)
{
client.position = new Vector3(client.position.x, float.Parse(pos[0]), client.position.z);
}
Debug.Log("Get Request happening");
}
}
private IEnumerator PutRequest()
{
while (true)
{
//What data is being sent
byte[] data = System.Text.Encoding.UTF8.GetBytes("This data is being sent to the server");
using (UnityWebRequest www = UnityWebRequest.Put("http://localhost", data))
{
yield return www.SendWebRequest();
//yield return new WaitForSeconds(0);
if (www.result != UnityWebRequest.Result.Success)
{
Debug.Log("Error sending data to server --- " + www.error);
}
else
{
Debug.Log("Information was successfully sent to server");
}
}
Debug.Log("Put Request happening");
}
}
}
And below is my python server code:
from http.server import BaseHTTPRequestHandler, HTTPServer
hostName = "localhost"
serverPort = 80
positionY = 0.0
deltaPosition = 0.1
class MyServer(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def do_GET(self):
self._set_headers()
global positionY
global deltaPosition
positionYStr = str(positionY)
self.wfile.write(bytes(positionYStr, "utf-8"))
print("sending " + positionYStr + "\n")
positionY += deltaPosition
if positionY > 4 or positionY < -4:
deltaPosition *= -1.0
def do_PUT(self):
self._set_headers()
content_len = int(self.headers.get('content-length'))
put_body = self.rfile.read(content_len)
print(put_body.decode(encoding="ascii", errors="ignore"))
self.wfile.write(bytes("received post request:<br>{}".format(put_body), "utf-8"))
if __name__ == "__main__":
webServer = HTTPServer((hostName, serverPort), MyServer)
print("Server started http://%s:%s" % (hostName, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")
To be clear, I am currently not receiving any errors. However, whenever I use yield return new WaitForSeconds(0); instead of yield return www.SendWebRequest(); in the PutRequest() method, the program runs smoothly, making me believe there is something wrong with the yield return www.SendWebRequest();
Hopefully I have clarified my problem well enough. I appreciate any and all help!

Related

python serial readline() vs C# serial ReadLine()

I'm trying to read serial input from my device, and have gotten it to work in Python using pyserial, e.g.
import serial
port = serial.Serial(port='COM1', baudrate=19200, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
while 1:
N = port.in_waiting
if N>4:
msg = port.readline(N)
print(list(msg))
I'm trying to implement this same code in C#, but it does not quite seem to work, e.g.
port = new SerialPort(COM1);
port.BaudRate = baudRate;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.ReadTimeout = SerialPort.InfiniteTimeout;
port.Handshake = Handshake.None;
port.RtsEnable = false;
port.DtrEnable = false;
port.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
and
void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int N = port.BytesToRead;
if (N > 4)
{
string line = port.ReadLine();
}
}
I'm able to read stuff properly using port.Read() in C#, however it seems like ReadLine doesn't quite work properly--it doesn't seem to be able to find the end-of-line character ("\n")? And the program just freezes. Yet I am not sure why it works with pyserial.ReadLine() which also seeks the same character (and works without timeout). As far as I can tell, the rest of the port settings are identical.
Thanks!
Because the DataReceived event indicates that data has been received through a port, the data is already read and you should call SerialPort.ReadExisting to get it.
void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var data = port.ReadExisting();
}
This event does not guarantee that its data is a single line, if you want a similar way to pySerial, you should not use the event and use ReadLine directly:
port.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
while(true)
{
int N = port.BytesToRead;
if (N > 4)
{
string line = port.ReadLine();
}
}

Apple Watch stops transmitting gyroscope/accelometer data after a few minutes for unknown reason

I have created a watchOS app that fetches data from the accelerometer and gyroscope and sends it to a socket server. The server just prints the data on the console. The socket server is made in python. My app works fine for a few minutes but then stops working.
I tested by creating an iPhone app and it's working fine. The problem is with the apple watch app.
Can someone help me with this? I don't understand what's going on.
server.py
import socket
localIP = ""
localPort = 20001
bufferSize = 10240
msgFromServer = "Hello UDP Client"
bytesToSend = str.encode(msgFromServer)
# Create a datagram socket
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# Bind to address and ip
UDPServerSocket.bind((localIP, localPort))
print("UDP server up and listening")
# Listen for incoming datagrams
while(True):
bytesAddressPair = UDPServerSocket.recvfrom(bufferSize)
message = bytesAddressPair[0]
address = bytesAddressPair[1]
clientMsg = "Message from Client:{}".format(message)
clientIP = "Client IP Address:{}".format(address)
print(clientMsg)
print(clientIP)
# Sending a reply to client
UDPServerSocket.sendto(bytesToSend, address)
InterfaceController.swift
#IBOutlet weak var stopButton: WKInterfaceButton!
#IBOutlet weak var startButton: WKInterfaceButton!
var session = WKExtendedRuntimeSession()
private var host: NWEndpoint.Host = "172.16.105.162"
private var port: NWEndpoint.Port = 20001
private var updateTimeInterval: Double = 1/60
override func awake(withContext context: Any?) {
// Configure interface objects here.
// startButton.setHidden(false)
startButton.setEnabled(true) // // stopButton.setHidden(true)
stopButton.setEnabled(false)
setUPSession()
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
print("ACTIVATE")
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
print("DEACTIVATE")
}
#IBAction func actionStop() { // startButton.setHidden(false)
startButton.setEnabled(true) // // stopButton.setHidden(true)
stopButton.setEnabled(false)
self.stopSession()
// MotionDatafetcher.shared.startSession() //stopWorkoutSEssion() //stopFetch()
}
#IBAction func actionStart() { // startButton.setHidden(true)
startButton.setEnabled(false) // // stopButton.setHidden(false)
stopButton.setEnabled(true)
self.startSession()
// MotionDatafetcher.shared.startFetch()
//MotionDatafetcher.shared.stopSession() //startWorkoutSession() //startDeviceMotionFetch()
}
}
extension InterfaceController : WKExtendedRuntimeSessionDelegate{
func setUPSession() {
// Create the session object.
session = WKExtendedRuntimeSession()
// Assign the delegate.
session.delegate = self
MySocketManager.shared.setUpConn()
}
func startSession() {
session.start()
MySocketManager.shared.connectToUDP(host, port)
MotionDatafetcher.shared.startDeviceMotionFetch(updateTimeInterval)
}
func stopSession() {
session.invalidate()
MotionDatafetcher.shared.stopFetch()
MySocketManager.shared.cancelConnToUDP()
}
func extendedRuntimeSession(_ extendedRuntimeSession: WKExtendedRuntimeSession, didInvalidateWith reason: WKExtendedRuntimeSessionInvalidationReason, error: Error?) {
}
func extendedRuntimeSessionDidStart(_ extendedRuntimeSession: WKExtendedRuntimeSession) {
}
func extendedRuntimeSessionWillExpire(_ extendedRuntimeSession: WKExtendedRuntimeSession) {
self.stopSession()
}
}

Continuously Send Data from Android Client to Python Server Socket

I am currently trying to send ble data from the app to my PC using sockets. As of now, I am able to send data to the server, but the server only receives one data and then stops receiving. I am suspecting that there is something wrong with my client side code. Any help would be appreciated
My SocketClass code:
inner class SocketClass{
fun doInBackground(message: String): String {
try {
socket = Socket(SERVER_IP, SERVERPORT)
val outputStream = OutputStreamWriter(socket?.getOutputStream())
val printwriter = BufferedWriter(outputStream)
printwriter.write(message)
printwriter.flush()
printwriter.close()
socket?.close()
} catch (e: Exception) {
e.printStackTrace()
}catch (e: UnknownHostException){
}
return ""
}
}
and in the blereadcharacteristic I call the class in a thread like this:
private fun readDeviceCharacteristic(characteristic: BluetoothGattCharacteristic) {
var hashval:MutableMap<String, String> = mutableMapOf()
var mainThreadList :MutableList<String> = mutableListOf()
var currentTime: String = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(
ZoneId.of("Asia/Seoul")).format(Instant.now()) // Get current Timestamp
if(idlist.size != 0) {
readval = characteristic.getStringValue(0)
valdata = readval.subSequence(3, readval.length).toString()
idNo = readval.subSequence(0, 2).toString()
parseList.add(readval)
mainThreadList = parseList.toMutableList().distinctBy{it.subSequence(0, 2)} as MutableList<String>
if(mainThreadList.size == maxConnLimit) {
bleDataList = mainThreadList
bleDataList.forEach{
hashval[it.subSequence(0, 2).toString()] = it.subSequence(3, it.length).toString()
}
loghash = hashval.toSortedMap()
txtRead = bleDataList.toString()
parseList.clear()
if(isChecked) {
savehash["Time"]?.add("$sec.$millis")
bleDataList.forEach {
savehash[it.subSequence(0, 2).toString()]?.add(
it.subSequence(
3,
it.length
).toString()
)
}
}else{
time = 0
sec = 0
millis = ""
}
if(isInsert){
Thread{
SocketClass().doInBackground("$loghash\r\n\r\n")
}.start()
}
}
}
isTxtRead = true
bleDataList.clear()
}
My server socket python code:
import socket
import sys
host = '19.201.12.12'
port = 30001
address = (host, port)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(address)
server_socket.listen(5)
print("Listening for client . . .")
conn, address = server_socket.accept()
print("Connected to client at ", address)
while True:
output = conn.recv(2048);
if output.strip() == "disconnect":
conn.close()
sys.exit("Received disconnect message. Shutting down.")
elif output:
print("Message received from client:")
print(output)
I am able to get the first data sent, but do not receive anything after. Any help would be greatly appreciated thankyou!
Your server code only accepts one client connection. So, here's the timelime.
Python waits at accept.
Kotlin connects
Python moves into while True loop.
Kotlin writes, then closes the socket.
At that point, nothing further will be received by the Python code, but because you never call accept again, you can't accept another connection.
You need to have the accept in a loop. You handle that connection until it closes, then you loop to another accept.
You might consider using the socketserver module, which automates some of this.

gRPC Node Js client: "Method not found"

I have a gRPC server implemented in python and I am calling an RPC from NodeJS but it gives an error "Method not found". When I call using the python client, the request is successful.
stream_csv.proto
syntax = "proto3";
package csv;
service Stream {
rpc csvToObject(CSVDataRequest) returns (stream CSVDataResponse) {};
rpc sayHello(HelloRequest) returns (HelloReply);
}
message CSVDataRequest{
string url = 1;
enum Protocol {
HTTP = 0;
HTTPS = 1;
FTP = 2;
SFTP = 3;
}
Protocol protocol = 2;
}
message CSVDataResponse{
repeated string row = 1;
}
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
client.js
var PROTO_PATH = '../stream_csv.proto';
var grpc = require('grpc');
var protoLoader = require('#grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var proto = grpc.loadPackageDefinition(packageDefinition).csv;
function main() {
var client = new proto.Stream('localhost:5000',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
console.log(user);
client.sayHello({name: user}, function(err, response) {
console.log(err);
});
}
main();
server.py
import grpc
import stream_csv_pb2
import urllib.request
from urllib.error import HTTPError, URLError
from concurrent import futures
class DataService:
def csv_to_object(self, request, context):
url = request.url
protocol = stream_csv_pb2.CSVDataRequest.Protocol.Name(
request.protocol)
fetch_url = protocol.lower() + "://"+url
try:
with urllib.request.urlopen(fetch_url) as data:
for line in data:
decoded_line = line.decode()
val = decoded_line.split(',')
print(val)
print("Data send")
yield stream_csv_pb2.CSVDataResponse(row=val)
print("Sending finished!")
except URLError as e:
context.abort(grpc.StatusCode.UNKNOWN,
'Randomly injected failure.')
# return stream_csv_pb2.CSVDataResponse(row=[], error=e.reason)
def SayHello(self, request, context):
name = request.name
print(name)
return stream_csv_pb2.HelloReply(message='Hello %s' % (name))
def add_DataServicer_to_server(servicer, server):
rpc_method_handlers = {
'CSVToObject': grpc.unary_stream_rpc_method_handler(
servicer.csv_to_object,
request_deserializer=stream_csv_pb2.CSVDataRequest.FromString,
response_serializer=stream_csv_pb2.CSVDataResponse.SerializeToString,
),
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=stream_csv_pb2.HelloRequest.FromString,
response_serializer=stream_csv_pb2.HelloReply.SerializeToString,
)
}
generic_handler = grpc.method_handlers_generic_handler(
'stream_csv.Stream', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
add_DataServicer_to_server(DataService(), server)
server.add_insecure_port('[::]:5000')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
Error
Error: 12 UNIMPLEMENTED: Method not found!
at Object.exports.createStatusError (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:1209:28)
at InterceptingListener._callNext (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:618:8)
at callback (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:847:24) {
code: 12,
metadata: Metadata { _internal_repr: {}, flags: 0 },
details: 'Method not found!'
}
I wrote a simpler variant of your Python (and Golang) server implementations.
Both work with your Node.JS client as-is.
I think perhaps your issue is as simple as needing to name the rpc sayHello (rather than SayHello).
from concurrent import futures
import logging
import grpc
import stream_csv_pb2
import stream_csv_pb2_grpc
class Stream(stream_csv_pb2_grpc.StreamServicer):
def sayHello(self, request, context):
logging.info("[sayHello]")
return stream_csv_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
logging.info("[serve]")
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
stream_csv_pb2_grpc.add_StreamServicer_to_server(Stream(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
And:
node client.js
Greeting: Hello, Freddie!
null
Conventionally (!) gRPC follows Protobufs style guide of CamelCasing service, rpc and message names and using underscores elsewhere see Style Guide. When protoc compiles, the results don't always match perfectly (e.g. Python's CamelCased functions rather than lowercased with underscores).
Conventionally, your proto would be:
service Stream {
rpc CsvToObject(CSVDataRequest) returns (stream CSVDataResponse) {};
rpc SayHello(HelloRequest) returns (HelloReply);
}
...and then the Python generated function would be (!) SayHello too.

Streaming camera from Python to C# over sockets?

I need to stream video from a Raspberry Pi's camera (Python server), to a C# script client (Unity, in fact).
I have successfully done this, using a Python to Python workflow, but I can't manage to make It work on C# client side.
This is my python server, where I'm sending the Stream over sockets:
Server.py:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 24000))
s.listen(1)
connection = s.accept()[0].makefile('wb')
print ('Client connected')
while True:
stream = io.BytesIO()
for foo in camera.capture_continuous(stream, 'jpeg'):
connection.write(struct.pack('<L', stream.tell()))
connection.flush()
stream.seek(0)
connection.write(stream.read())
stream.seek(0)
stream.truncate()
And this is my Python client side, which is actually working:
Client.py:
def threadLoop(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.ip, self.port))
connection = self.socket.makefile('rb')
print('Recibiendo fotos')
while not self.haltSignal():
image_len, image_width, image_height = struct.unpack('<LLL', connection.read(struct.calcsize('<LLL')))
print ("L: " + str(image_len) + " W: " + str(image_width) + " H: " + str(image_height))
if not image_len:
break
image_stream = io.BytesIO()
image_stream.write(connection.read(image_len))
image_stream.seek(0)
self.callback(image_stream.getvalue(), image_width, image_height)
self.socket.close()
self.socket = None
self.thread = None
So, the question is... having this Server.py, how can I make a C# client that receives the stream and show the pictures?
I've tried to capture the received data in C#, over the socket, store It in a Byte array and convert It to a readable image, which sometimes, when It's a (very)small sized picture, works fine. I guess there must be a better way to achieve this.
Thanks!
Edit: This is what I've been trying in C#. Thanks again!
public int Connect()
{
if (_clientSocket.Connected == false)
{
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
mutexToSend = new Mutex();
mutexReceived = new Mutex();
ThreadStart ts = new ThreadStart(SendReceiveData);
threadSend = new Thread(ts);
threadSend.Start();
return 1;
}
else
return 0; //There is a socket already connected.
}
//----------------------------------------------------------
private void SendReceiveData()
{
try
{
_clientSocket.SendTimeout = 1000;
_clientSocket.ReceiveTimeout = 1000;
System.Net.IPAddress ipaddress = this.serverIP;
_clientSocket.Connect(new IPEndPoint(ipaddress, this.serverPort));
}
catch (SocketException ex)
{
//turn ex.Message;
}
_clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
//----------------------------------------------------------
private void ReceiveCallback(IAsyncResult AR)
{
//Check how much bytes are recieved and call EndRecieve to finalize handshake
int recieved = _clientSocket.EndReceive(AR);
if (recieved <= 0)
{
GestorCamaraSala.imgReceived = _recieveBuffer; //I copy the received data to the image texture
return;
}
//Start receiving again
_clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}// end ReceivedCallback

Categories