【发布时间】:2018-04-23 10:45:45
【问题描述】:
我正在 Unity3d 中创建一个与 python 的 websockets 库通信的应用程序。我的python脚本如下:
from __future__ import division
import asyncio
import websockets
import time
import os
from threading import Thread
from random import randint
from read import CustOPCLib
import socket
from jsonsocket import Client,Server
class SubHandler(object):
def data_change(self, handle, node, val, attr):
print("Python: New data change event", handle, node, val, attr)
def datachange_notification(self, node, val, data):
print("Data received: ",val)
def event(self, handle, event):
print("Python: New event", handle, event)
p = CustOPCLib()
async def hello(websocket, path):
p.connect() #my own custom library
while True:
datastring = p.opcjson() #this is a jsonstring
await websocket.send(datastring)
#print("> {}".format(datastring))
time.sleep(1)
if __name__ == '__main__':
start_server = websockets.serve(hello, '127.0.0.1', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
我的json字符串如下:
{
"Index": 709953575,
"Moto": true,
"Start": false,
"StartWINCC": false,
"Stop": false,
"StopWINCC": false,
"Tag1": true,
"Tag2": false
}
这是我要发送给 Unity 的字符串。在 Unity3d 中,我制作了以下使用单声道并发队列的脚本。该脚本相应地工作,但是我遇到的问题是我从 websocket 获得了很多空值。 我的 Unity3d 脚本:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Threading;
public class ConcurrentQueue<T> : IEnumerable<T>, ICollection, ISerializable, IDeserializationCallback
{
class Node
{
public T Value;
public Node Next;
}
Node _head = new Node();
Node _tail;
int _count;
/// <summary>
/// </summary>
public ConcurrentQueue()
{
_tail = _head;
}
public ConcurrentQueue(IEnumerable<T> enumerable)
: this()
{
foreach (T item in enumerable)
Enqueue(item);
}
public void Enqueue(T item)
{
var node = new Node { Value = item };
Node oldTail = null;
bool update = false;
while (!update)
{
oldTail = _tail;
var oldNext = oldTail.Next;
// Did tail was already updated ?
if (_tail == oldTail)
{
if (oldNext == null)
{
// The place is for us
update = Interlocked.CompareExchange(ref _tail.Next, node, null) == null;
}
else
{
// another Thread already used the place so give him a hand by putting tail where it should be
Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
}
}
}
// At this point we added correctly our node, now we have to update tail. If it fails then it will be done by another thread
Interlocked.CompareExchange(ref _tail, node, oldTail);
Interlocked.Increment(ref _count);
}
/// <summary>
/// </summary>
/// <returns></returns>
public bool TryDequeue(out T value)
{
value = default(T);
bool advanced = false;
while (!advanced)
{
Node oldHead = _head;
Node oldTail = _tail;
Node oldNext = oldHead.Next;
if (oldHead == _head)
{
// Empty case ?
if (oldHead == oldTail)
{
// This should be false then
if (oldNext != null)
{
// If not then the linked list is mal formed, update tail
Interlocked.CompareExchange(ref _tail, oldNext, oldTail);
}
value = default(T);
return false;
}
else
{
value = oldNext.Value;
advanced = Interlocked.CompareExchange(ref _head, oldNext, oldHead) == oldHead;
}
}
}
Interlocked.Decrement(ref _count);
return true;
}
/// <summary>
/// </summary>
/// <returns></returns>
public bool TryPeek(out T value)
{
if (IsEmpty)
{
value = default(T);
return false;
}
Node first = _head.Next;
value = first.Value;
return true;
}
public void Clear()
{
_count = 0;
_tail = _head = new Node();
}
IEnumerator IEnumerable.GetEnumerator()
{
return InternalGetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return InternalGetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return InternalGetEnumerator();
}
IEnumerator<T> InternalGetEnumerator()
{
Node myHead = _head;
while ((myHead = myHead.Next) != null)
{
yield return myHead.Value;
}
}
void ICollection.CopyTo(Array array, int index)
{
T[] dest = array as T[];
if (dest == null)
return;
CopyTo(dest, index);
}
public void CopyTo(T[] dest, int index)
{
IEnumerator<T> e = InternalGetEnumerator();
int i = index;
while (e.MoveNext())
{
dest[i++] = e.Current;
}
}
public T[] ToArray()
{
T[] dest = new T[_count];
CopyTo(dest, 0);
return dest;
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new NotImplementedException();
}
bool ICollection.IsSynchronized
{
get { return true; }
}
public void OnDeserialization(object sender)
{
throw new NotImplementedException();
}
readonly object _syncRoot = new object();
object ICollection.SyncRoot
{
get { return _syncRoot; }
}
public int Count
{
get
{
return _count;
}
}
public bool IsEmpty
{
get
{
return _count == 0;
}
}
}
public class test : MonoBehaviour
{
class OpcJson
{
public int Index { get; set; }
public bool Moto { get; set; }
public bool Start { get; set; }
public bool StartWINCC { get; set; }
public bool Stop { get; set; }
public bool StopWINCC { get; set; }
public bool Tag1 { get; set; }
public bool Tag2 { get; set; }
}
//variables
static readonly ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
public string receivedFromServer;
WebSocket w = new WebSocket(new Uri("ws://127.0.0.1:8765"));
public Text testert;
public Image moto;
public Image start;
public Image startwincc;
public Image stop;
public Image stopwincc;
public Image tag1;
public Image tag2;
// Use this for initialization
IEnumerator StartWebsocket()
{
yield return StartCoroutine(w.Connect());
//w.SendString("Hi there");
//int i = 0;
while (true)
{
string reply = w.RecvString();
if (reply != null)
{
//Debug.Log(reply);
queue.Enqueue(reply);
//receivedFromServer = reply;
//Debug.Log("Received: " + reply);
//w.SendString("Hi there" + i++);
}
if (w.error != null)
{
Debug.LogError("Error: " + w.error);
break;
}
yield return 0;
}
w.Close();
}
private void OnApplicationQuit()
{
StopAllCoroutines();
w.Close();
}
IEnumerator JsonObjectSetter(float waitforsecods)
{
while (true)
{
queue.TryDequeue(out receivedFromServer);
//string s = receivedFromServer;
//Debug.Log(s);
if(receivedFromServer == null)
{
Debug.Log("I'm null");
}
else
{
var results = JsonConvert.DeserializeObject<OpcJson>(receivedFromServer);
testert.text = results.Index.ToString();
if (results.Moto == true)
{
moto.GetComponent<Image>().color = Color.green;
}
else
{
moto.GetComponent<Image>().color = Color.red;
}
if (results.Start == true)
{
start.GetComponent<Image>().color = Color.green;
}
else
{
start.GetComponent<Image>().color = Color.red;
}
if (results.StartWINCC == true)
{
startwincc.GetComponent<Image>().color = Color.green;
}
else
{
startwincc.GetComponent<Image>().color = Color.red;
}
if (results.Stop == true)
{
stop.GetComponent<Image>().color = Color.green;
}
else
{
stop.GetComponent<Image>().color = Color.red;
}
if (results.StopWINCC == true)
{
stopwincc.GetComponent<Image>().color = Color.green;
}
else
{
stopwincc.GetComponent<Image>().color = Color.red;
}
if (results.Tag1 == true)
{
tag1.GetComponent<Image>().color = Color.green;
}
else
{
tag1.GetComponent<Image>().color = Color.red;
}
if (results.Tag2 == true)
{
tag2.GetComponent<Image>().color = Color.green;
}
else
{
tag2.GetComponent<Image>().color = Color.red;
}
}
yield return new WaitForSeconds(waitforsecods);
}
}
private void Start()
{
StartCoroutine(StartWebsocket());
StartCoroutine(JsonObjectSetter(1));
}
}
如您所见,我在 JsonObjectSetter 方法中创建了 if/else 语句。每次出队后字符串为空时,它都会打印出“I'm null”,如果它不为空,它会根据值将图像设置为颜色。 我怎样才能做到这样我就不会再得到任何空值了?
编辑 1:在 7 分钟的测试中,我计算了 49 个空值。老实说,这是一个相当大的问题......
【问题讨论】:
标签: c# python unity3d websocket