feat(rcf):ground work on propertystreaming

This commit is contained in:
Swann
2019-02-13 18:53:22 +01:00
parent 77b8221026
commit c3e935081e
4 changed files with 53 additions and 39 deletions

View File

@ -27,14 +27,11 @@ from . import net_ui
import bpy import bpy
def register(): def register():
bpy.types.Scene.message = bpy.props.StringProperty(default="Hi")
bsyncio.register() bsyncio.register()
net_operators.register() net_operators.register()
net_ui.register() net_ui.register()
def unregister(): def unregister():
del bpy.types.Scene.message
bsyncio.unregister() bsyncio.unregister()
net_operators.unregister() net_operators.unregister()
net_ui.unregister() net_ui.unregister()

View File

@ -9,9 +9,8 @@ import struct
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
# TODO: Add message time and author stamp for reliabilty # TODO: Add message time and author stamp for reliabilty
class RCFMessage(object): class RCFMessage(object):
""" """
Message is formatted on wire as 2 frames: Message is formatted on wire as 2 frames:
@ -35,16 +34,17 @@ class RCFMessage(object):
def send(self, socket): def send(self, socket):
"""Send key-value message to socket; any empty frames are sent as such.""" """Send key-value message to socket; any empty frames are sent as such."""
key = '' if self.key is None else self.key key = '' if self.key is None else self.key.encode()
body = '' if self.body is None else self.body body = '' if self.body is None else umsgpack.packb(self.body)
socket.send_multipart([key, body]) socket.send_multipart([key, body])
@classmethod @classmethod
def recv(cls, socket): def recv(cls, socket):
"""Reads key-value message from socket, returns new kvmsg instance.""" """Reads key-value message from socket, returns new kvmsg instance."""
key, body = socket.recv_multipart() key, body = socket.recv_multipart(zmq.NOBLOCK)
key = key if key else None key = key.decode() if key else None
body = body if body else None body = umsgpack.unpackb(body) if body else None
return cls(key=key, body=body) return cls(key=key, body=body)
def dump(self): def dump(self):
@ -75,7 +75,7 @@ class Client():
self.task = asyncio.ensure_future(self.main()) self.task = asyncio.ensure_future(self.main())
self.property_map = {} self.property_map = {}
self.message_store = []
logger.info("{} client initialized".format(id)) logger.info("{} client initialized".format(id))
def bind_ports(self): def bind_ports(self):
@ -114,27 +114,18 @@ class Client():
break break
if self.pull_sock in socks: if self.pull_sock in socks:
update = self.pull_sock.recv_multipart(zmq.NOBLOCK) rcfmsg = RCFMessage.recv(self.pull_sock)
print(update) rcfmsg.store(self.property_map)
rcfmsg.dump()
# TODO: Proper routing throught different socket / sub ? for f in self.recv_callback:
if update[1].decode() == 'chat': f(rcfmsg)
# Store message
self.message_store.append(
[update[0].decode('ascii'), umsgpack.unpackb(update[2])])
if update[1].decode() == 'chat':
pass
if self.recv_callback: def push_update(self, key, body):
self.recv_callback() rcfmsg = RCFMessage(key,body)
rcfmsg.send(self.push_sock)
def send_msg(self, msg): # self.push_sock.send_multipart()
self.req_sock.send_multipart([b"chat",umsgpack.packb(msg)])
def send_update(self, msg):
self.push_sock.send_multipart()
def stop(self): def stop(self):
logger.info("Stopping client") logger.info("Stopping client")
@ -199,7 +190,10 @@ class Server():
self.pub_sock.send_multipart(msg) self.pub_sock.send_multipart(msg)
if self.collector_sock in socks: if self.collector_sock in socks:
pass msg = self.collector_sock.recv_multipart(zmq.NOBLOCK)
# Update all clients
self.pub_sock.send_multipart(msg)
def stop(self): def stop(self):
logger.info("Stopping server") logger.info("Stopping server")

View File

@ -2,6 +2,7 @@ import bpy
from . import net_components from . import net_components
import time import time
import logging import logging
import mathutils
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -9,12 +10,28 @@ client = None
server = None server = None
context = None context = None
# CLIENT-SERVER # CLIENT-SERVER
def refresh_window(): def refresh_window(msg):
import bpy import bpy
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
def patch_scene(msg):
path = msg.key.split('/')
attribute = getattr(getattr(bpy.data,path[0])[path[1]],path[2])
print(type(attribute))
if type(attribute) == mathutils.Vector:
attribute = array2vector(msg.body)
def vector2array(v):
return [v.x,v.y,v.z]
def array2vector(a):
print(mathutils.Vector((a[0],a[1],a[2])))
return mathutils.Vector((a[0],a[1],a[2]))
class session_join(bpy.types.Operator): class session_join(bpy.types.Operator):
bl_idname = "session.join" bl_idname = "session.join"
bl_label = "join" bl_label = "join"
@ -29,7 +46,9 @@ class session_join(bpy.types.Operator):
global client global client
username = str(context.scene.session_settings.username) username = str(context.scene.session_settings.username)
client = net_components.Client(id=username ,recv_callback=refresh_window) callbacks=[refresh_window,patch_scene]
client = net_components.Client(id=username ,recv_callback=callbacks)
time.sleep(1) time.sleep(1)
bpy.ops.asyncio.loop() bpy.ops.asyncio.loop()
@ -52,7 +71,10 @@ class session_send(bpy.types.Operator):
def execute(self, context): def execute(self, context):
global client global client
client.send_msg(self.message) key = "objects/Cube/location"
value = vector2array(bpy.data.objects['Cube'].location)
client.push_update(key,value)
return {"FINISHED"} return {"FINISHED"}
@ -71,9 +93,10 @@ class session_create(bpy.types.Operator):
global client global client
username = str(context.scene.session_settings.username) username = str(context.scene.session_settings.username)
callbacks=[refresh_window,patch_scene]
server = net_components.Server() server = net_components.Server()
client = net_components.Client(id=username,recv_callback=refresh_window) client = net_components.Client(id=username,recv_callback=callbacks)
time.sleep(1) time.sleep(1)

View File

@ -25,16 +25,16 @@ class SessionPanel(bpy.types.Panel):
row = layout.row() row = layout.row()
row = layout.row(align=True) row = layout.row(align=True)
row.prop(scene,"message",text="")
row.operator("session.send").message = scene.message row.operator("session.send")
row = layout.row() row = layout.row()
# Debug area # Debug area
row = layout.row() row = layout.row()
area_msg = row.box() area_msg = row.box()
if len(net_operators.client.message_store) > 0: if len(net_operators.client.property_map) > 0:
for (id,msg) in net_operators.client.message_store: for key,value in net_operators.client.property_map.items():
area_msg.label(text="{}:{}".format(id,msg)) area_msg.label(text="{}:{}".format(key,value))
else: else:
area_msg.label(text="Empty") area_msg.label(text="Empty")