add request

This commit is contained in:
remilia 2025-02-26 21:41:15 +08:00
parent e4d54c6176
commit f51d244466
9 changed files with 199 additions and 143 deletions

View File

@ -1,26 +1,20 @@
import logging import logging
import struct
import time import time
from pathlib import Path
import cupy as cp import cupy as cp
import cv2 import cv2
import numpy as np
import zmq
from config import PLAYBACK_SOCKET, VIDEO_WIDTH, VIDEO_HEIGHT, LIVE_SOCKET, IMAGING_CONFIG from config import VIDEO_WIDTH, VIDEO_HEIGHT
from nodes.Node import Node from nodes.Node import Node
from utils.Msg import BMMsg, ImageArgMsg, KillMsg, SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, SetRecordMsg, \ from utils.Msg import BMMsg, ImageArgMsg, SetSeqMetaMsg, Msg, RfFrameWithMetaMsg, BeamformerMsg, RequestRfFrameMsg
RecordFrameMsg, ImagingConfigNameListMsg, Msg, RfFrameMsg from utils.RfFile import RfSequenceMeta
from utils.RfFile import RfFrame, RfSequenceMeta
from utils.RfMat import RfMat from utils.RfMat import RfMat
from utils.RfMeta import RfFrameMeta
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Beamformer(Node): class Beamformer(Node):
topics = [RfFrameMsg] topics = [BeamformerMsg]
def __init__(self, level=logging.INFO): def __init__(self, level=logging.INFO):
super(Beamformer, self).__init__(level=level) super(Beamformer, self).__init__(level=level)
@ -40,24 +34,28 @@ class Beamformer(Node):
self.send(BMMsg(0, d2.__bytes__())) self.send(BMMsg(0, d2.__bytes__()))
def loop(self): def loop(self):
req_socket = self.context.socket(zmq.REQ)
req_socket.connect('tcp://127.0.0.1:5559')
time.sleep(1) time.sleep(1)
while True: while True:
req_socket.send(b'') self.send(RequestRfFrameMsg())
r = req_socket.recv() r = dict(self.c.poller.poll(1000))
if r.__len__() > 0: if self.c.sub in r:
id2 = r.index(Msg.magic(), 1) msg = self.recv()
id3 = r.index(Msg.magic(), id2 + 1) if isinstance(msg, BeamformerMsg):
print(id2, id3) if msg.value == b'init':
seq_msg: SetSeqMetaMsg = Msg.decode_msg(r[:id2]) time.sleep(1)
arg_msg: ImageArgMsg = Msg.decode_msg(r[id2:id3]) continue
b_msg: RfFrameMsg = Msg.decode_msg(r[id3:]) if msg.value == b'nop':
s = b_msg.data continue
fb1 = cp.frombuffer(s, dtype=cp.int16) r = msg.value
seq_meta = RfSequenceMeta.from_name(seq_msg.name) id2 = r.index(Msg.magic(), 1)
mat = RfMat(fb1.reshape(seq_meta.shape), RfFrameMeta( id3 = r.index(Msg.magic(), id2 + 1)
encoder=b_msg.encoder, seq_msg: SetSeqMetaMsg = Msg.decode_msg(r[:id2])
sequence_id=b_msg.sequence_id, arg_msg: ImageArgMsg = Msg.decode_msg(r[id2:id3])
), seq_meta) b_msg: RfFrameWithMetaMsg = Msg.decode_msg(r[id3:])
self.process(mat, arg_msg) s = b_msg.data
fb1 = cp.frombuffer(s, dtype=cp.int16)
seq_meta = RfSequenceMeta.from_name(seq_msg.name)
mat = RfMat(fb1.reshape(seq_meta.shape), b_msg.meta, seq_meta)
self.process(mat, arg_msg)
else:
logger.debug('package lose')

View File

@ -1,4 +1,5 @@
import logging import logging
import struct
import subprocess import subprocess
import time import time
@ -7,13 +8,15 @@ import zmq
from config import LIVE_REP_SOCKET, CONFIG, DEVICE_CONFIG from config import LIVE_REP_SOCKET, CONFIG, DEVICE_CONFIG
from nodes.Node import Node from nodes.Node import Node
from utils.Msg import ImageArgMsg, KillMsg, SetDeviceConnectedMsg, SetDeviceEnabledMsg, DeviceEnabledMsg, \ from utils.Msg import ImageArgMsg, KillMsg, SetDeviceConnectedMsg, SetDeviceEnabledMsg, DeviceEnabledMsg, \
DeviceConnectedMsg, SetDeviceConfigMsg, DeviceOnlineMsg, DeviceConfigListMsg DeviceConnectedMsg, SetDeviceConfigMsg, DeviceOnlineMsg, DeviceConfigListMsg, RequestRfFrameMsg, RfFrameMsg, \
RfFrameWithMetaMsg
from utils.RfMeta import RfFrameMeta
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Device(Node): class Device(Node):
topics = [SetDeviceConnectedMsg, SetDeviceEnabledMsg, SetDeviceConfigMsg] topics = [SetDeviceConnectedMsg, SetDeviceEnabledMsg, SetDeviceConfigMsg, RequestRfFrameMsg]
def __init__(self, level=logging.INFO): def __init__(self, level=logging.INFO):
super(Device, self).__init__(level=level) super(Device, self).__init__(level=level)
@ -137,7 +140,6 @@ class Device(Node):
logger.debug(f'device start loop') logger.debug(f'device start loop')
while True: while True:
msg = self.recv() msg = self.recv()
logger.debug(f'{msg}')
if isinstance(msg, KillMsg): if isinstance(msg, KillMsg):
if msg.name == '': if msg.name == '':
return return
@ -153,3 +155,12 @@ class Device(Node):
self.disconnect() self.disconnect()
elif isinstance(msg, SetDeviceConfigMsg): elif isinstance(msg, SetDeviceConfigMsg):
self.setfile(msg.value) self.setfile(msg.value)
elif isinstance(msg, RequestRfFrameMsg):
braw = self.data()
if braw == b'':
continue
_, sequence_id, encoder = struct.unpack_from('=iqi', braw)
buffer = braw[4 + 8 + 4:]
self.send(RfFrameWithMetaMsg(0, RfFrameMeta(
encoder=encoder, sequence_id=sequence_id
), buffer))

View File

@ -27,31 +27,42 @@ class ImageFFMPEG(Node):
'-f', 'rawvideo', '-f', 'rawvideo',
'-pixel_format', 'rgb24', '-pixel_format', 'rgb24',
'-video_size', '1080x1920', '-video_size', '1080x1920',
'-framerate', '60', '-framerate', '24',
'-hwaccel', 'nvdec', '-hwaccel', 'nvdec',
'-i', '-', '-i', '-',
'-vcodec', 'h264_nvenc', '-vcodec', 'h264_nvenc',
'-preset', 'faster', '-preset', 'fast',
'-gpu', '1',
# '-profile:v', 'high',
'-zerolatency', '1',
# '-tune', 'ull',
# '-level', '42',
'-pix_fmt', 'yuv420p', '-pix_fmt', 'yuv420p',
# '-vcodec', 'libx264', # '-vcodec', 'libx264',
'-b:v', '40M', # '-b:v', '40M',
'-f', 'flv', '-f', 'flv',
'rtmp://localhost/live/livestream' 'rtmp://q1hyb.as/live/bscan'
# '-f', 'mpegts', # '-f', 'mpegts',
# 'srt://localhost:10080?streamid=#!::r=live/livestream,m=publish' # 'srt://localhost:10080?streamid=#!::r=live/livestream,m=publish'
], ],
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
) )
lasttime = time.time()
while True: while True:
# socks = dict(self.c.poller.poll(1 / 30)) # socks = dict(self.c.poller.poll(1 / 30))
events = self.c.poller.poll(1) events = self.c.poller.poll(1000 / 24)
if events: if events:
msg: BMMsg = Msg.decode_msg(events[0][0].recv()) msg: BMMsg = Msg.decode_msg(events[0][0].recv())
b = np.frombuffer(msg.data, dtype=np.uint8) b = np.frombuffer(msg.data, dtype=np.uint8)
b = np.reshape(b, (VIDEO_HEIGHT, VIDEO_WIDTH, 4))[:, :, :3] b = np.reshape(b, (VIDEO_HEIGHT, VIDEO_WIDTH, 4))[:, :, :3]
self.buffer = b.tobytes() self.buffer = b.tobytes()
p.stdin.write(self.buffer) p.stdin.write(self.buffer)
time.sleep(1 / 60) # time.sleep(1 / 60)
currenttime = time.time()
logger.debug(f'{currenttime - lasttime}')
lasttime = currenttime
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -8,7 +8,7 @@ import zmq
from config import PLAYBACK_SOCKET_PORT, SOFTWARE_CONFIG from config import PLAYBACK_SOCKET_PORT, SOFTWARE_CONFIG
from nodes.Node import Node from nodes.Node import Node
from utils.Msg import MoveAxisMsg, KillMsg, SetSeqMetaMsg, SeqIdMinMax, SetBaseMsg, SeqListMsg, SeqIdList, \ from utils.Msg import MoveAxisMsg, KillMsg, SetSeqMetaMsg, SeqIdMinMax, SetBaseMsg, SeqListMsg, SeqIdList, \
SetSidMsg SetSidMsg, RfFrameWithMetaMsg
from utils.RfFile import RfSequence from utils.RfFile import RfSequence
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -33,10 +33,11 @@ class Loader(Node):
pass pass
elif isinstance(msg, SetSidMsg): elif isinstance(msg, SetSidMsg):
frame = rff.frames[msg.value] frame = rff.frames[msg.value]
buffer = io.BytesIO() # buffer = io.BytesIO()
buffer.write(struct.pack('=iqi', 114514, frame.meta.sequence_id, frame.meta.encoder)) # buffer.write(struct.pack('=iqi', 114514, frame.meta.sequence_id, frame.meta.encoder))
buffer.write(frame.bytes) # buffer.write(frame.bytes)
playback_socket.send(buffer.getvalue()) # playback_socket.send(buffer.getvalue())
self.send(RfFrameWithMetaMsg(1, frame.meta, frame.bytes))
elif isinstance(msg, SetSeqMetaMsg): elif isinstance(msg, SetSeqMetaMsg):
if base is None: if base is None:
continue continue

View File

@ -1,26 +1,22 @@
import logging import logging
import struct
import time import time
from pathlib import Path from pathlib import Path
import cupy as cp
import cv2
import numpy as np import numpy as np
import zmq import zmq
from config import PLAYBACK_SOCKET, VIDEO_WIDTH, VIDEO_HEIGHT, LIVE_SOCKET, IMAGING_CONFIG from config import IMAGING_CONFIG
from nodes.Node import Node from nodes.Node import Node
from utils.Msg import BMMsg, ImageArgMsg, KillMsg, SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, SetRecordMsg, \ from utils.Msg import ImageArgMsg, KillMsg, SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, SetRecordMsg, \
RecordFrameMsg, ImagingConfigNameListMsg, RfFrameMsg ImagingConfigNameListMsg, RfFrameWithMetaMsg, BeamformerMsg, RequestRfFrameMsg
from utils.RfFile import RfFrame, RfSequenceMeta from utils.RfFile import RfSequenceMeta
from utils.RfMat import RfMat
from utils.RfMeta import RfFrameMeta
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Muxer(Node): class Muxer(Node):
topics = [SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, SetRecordMsg] topics = [SetSeqMetaMsg, SetPlayMode, SetDeviceConfigMsg, SetRecordMsg, RfFrameWithMetaMsg, RequestRfFrameMsg,
ImageArgMsg]
def __init__(self, level=logging.INFO): def __init__(self, level=logging.INFO):
super(Muxer, self).__init__(level=level) super(Muxer, self).__init__(level=level)
@ -33,94 +29,70 @@ class Muxer(Node):
self.play_mode = None self.play_mode = None
@property @property
def current_seq_meta(self): def current_meta(self):
seq_meta = None seq_meta: RfSequenceMeta | None = {
match self.play_mode: "live": self.seq_meta_live,
case 'live': "playback": self.seq_meta_playback,
seq_meta = self.seq_meta_live }.get(self.play_mode, None)
case 'playback':
seq_meta = self.seq_meta_playback
return seq_meta return seq_meta
def loop(self): def loop(self):
device_socket = self.context.socket(zmq.PULL) device_socket = self.context.socket(zmq.PULL)
device_socket.setsockopt(zmq.CONFLATE, 1) self.sf = None
rep_socket = self.context.socket(zmq.REP)
rep_socket.bind('tcp://*:5559')
self.arg = ImageArgMsg('', t_start=0, t_end=1499) self.arg = ImageArgMsg('', t_start=0, t_end=1499)
self.c.poller.register(device_socket, zmq.POLLIN) self.c.poller.register(device_socket, zmq.POLLIN)
self.c.poller.register(rep_socket, zmq.POLLIN)
rfframemsg: RfFrameMsg | None = None
time.sleep(1) time.sleep(1)
self.send(ImagingConfigNameListMsg([path.stem for path in IMAGING_CONFIG.glob('*.json')])) self.send(ImagingConfigNameListMsg([path.stem for path in IMAGING_CONFIG.glob('*.json')]))
while True: while True:
socks = dict(self.c.poller.poll()) socks = dict(self.c.poller.poll())
if device_socket in socks and socks[device_socket] == zmq.POLLIN: for k in socks:
buffer = device_socket.recv() if k == device_socket:
device_socket.disconnect(f"tcp://{LIVE_SOCKET}") pass
device_socket.connect(f"tcp://{LIVE_SOCKET}") if k == self.c.sub:
logger.debug(f'device receive {buffer.__len__()}') msg = self.recv()
_, sequence_id, encoder = struct.unpack_from('=iqi', buffer) if isinstance(msg, RfFrameWithMetaMsg):
buf = buffer[4 + 8 + 4:] if msg.sender == 0 and self.play_mode == 'live':
logger.debug(f'live meta {self.seq_meta_live}, playback meta {self.seq_meta_playback}') self.send(BeamformerMsg(
seq_meta: RfSequenceMeta | None = { SetSeqMetaMsg('any', self.seq_meta_live.name).encode_msg() +
"live": self.seq_meta_live, self.arg.encode_msg() +
"playback": self.seq_meta_playback, msg.encode_msg()
}.get(self.play_mode, None) ))
if seq_meta is not None: elif msg.sender == 1:
if (buf.__len__() // 2) == np.prod(seq_meta.shape): self.sf = msg
self.seq_meta = seq_meta elif isinstance(msg, RequestRfFrameMsg):
rfframemsg = RfFrameMsg(sequence_id, encoder, buf) if self.play_mode is None:
fm = RfFrameMeta( self.send(BeamformerMsg(b'init'))
encoder=encoder, elif self.play_mode == 'playback':
sequence_id=sequence_id, if self.sf is None:
) self.send(BeamformerMsg(b'nop'))
if self.record_enable: elif (self.sf.data.__len__() // 2) != np.prod(self.seq_meta_playback.shape):
(self.record_path / fm.filename).write_bytes(buf) self.send(BeamformerMsg(b'nop'))
self.send(RecordFrameMsg(buf.__len__(), sequence_id)) else:
if rep_socket in socks and socks[rep_socket] == zmq.POLLIN: self.send(BeamformerMsg(
rep_socket.recv() SetSeqMetaMsg('any', self.seq_meta_playback.name).encode_msg() +
if rfframemsg is None or self.seq_meta is None:
rep_socket.send(b'')
else:
rep_socket.send(SetSeqMetaMsg('any', self.seq_meta.name).encode_msg() +
self.arg.encode_msg() + self.arg.encode_msg() +
rfframemsg.encode_msg()) self.sf.encode_msg()
if self.c.sub in socks and socks[self.c.sub] == zmq.POLLIN: ))
msg = self.recv() elif isinstance(msg, KillMsg):
if isinstance(msg, KillMsg): if msg.name == '':
if msg.name == '': return
return elif isinstance(msg, ImageArgMsg):
if isinstance(msg, ImageArgMsg): self.arg = msg
self.arg = msg elif isinstance(msg, SetSeqMetaMsg):
if isinstance(msg, SetSeqMetaMsg): match msg.target:
match msg.target: case 'live':
case 'live': self.seq_meta_live = RfSequenceMeta.from_name(msg.name)
self.seq_meta_live = RfSequenceMeta.from_name(msg.name) case 'playback':
case 'playback': self.seq_meta_playback = RfSequenceMeta.from_name(msg.name)
self.seq_meta_playback = RfSequenceMeta.from_name(msg.name) elif isinstance(msg, SetPlayMode):
if isinstance(msg, SetPlayMode): logger.debug(f'set playmode {msg}')
logger.debug(f'set playmode {msg}') self.play_mode = msg.value
self.play_mode = msg.value elif isinstance(msg, SetRecordMsg):
if msg.value == 'live': self.record_enable = msg.enable
try: if msg.enable:
device_socket.disconnect(f"tcp://{PLAYBACK_SOCKET}") seq_meta = self.current_seq_meta
except: self.record_commit = msg.commit
pass seq_meta.commit = msg.commit
device_socket.connect(f"tcp://{LIVE_SOCKET}") p = Path(msg.base) / seq_meta.name
elif msg.value == 'playback': p.mkdir(parents=True, exist_ok=True)
try: self.record_path = p
device_socket.disconnect(f"tcp://{LIVE_SOCKET}")
except:
pass
device_socket.connect(f"tcp://{PLAYBACK_SOCKET}")
logger.debug('connect to playback')
if isinstance(msg, SetRecordMsg):
self.record_enable = msg.enable
if msg.enable:
seq_meta = self.current_seq_meta
self.record_commit = msg.commit
seq_meta.commit = msg.commit
p = Path(msg.base) / seq_meta.name
p.mkdir(parents=True, exist_ok=True)
self.record_path = p

View File

@ -4,6 +4,8 @@ import struct
from enum import auto, Enum from enum import auto, Enum
from pathlib import Path from pathlib import Path
from utils.RfMeta import RfFrameMeta
class BG(Enum): class BG(Enum):
Msg1 = auto() Msg1 = auto()
@ -34,6 +36,10 @@ class BG(Enum):
SetSidMsg = auto() SetSidMsg = auto()
ImagingConfigNameListMsg = auto() ImagingConfigNameListMsg = auto()
RfFrameMsg = auto() RfFrameMsg = auto()
RfFrameWithMetaMsg = auto()
BytesMsg = auto()
BeamformerMsg = auto()
RequestRfFrameMsg = auto()
class Msg: class Msg:
@ -249,19 +255,69 @@ class RfFrameMsg(Msg):
) + self.data ) + self.data
@classmethod @classmethod
def decode(cls, data: bytes) -> 'Msg': def decode(cls, data: bytes) -> 'RfFrameMsg':
return cls( return cls(
*struct.unpack('II', data[:8]), *struct.unpack('II', data[:8]),
data[8:] data[8:]
) )
class RfFrameWithMetaMsg(Msg):
SPLIT = struct.pack('I', 114514)
def __init__(self, sender: int, meta: RfFrameMeta, data: bytes):
self.sender = sender
self.meta = meta
self.data = data
def encode(self) -> bytes:
return struct.pack('I', self.sender) + self.meta.name.encode() + self.SPLIT + self.data
@classmethod
def decode(cls, data: bytes) -> 'RfFrameWithMetaMsg':
id2 = data.index(cls.SPLIT)
return cls(
sender=struct.unpack('I', data[:4])[0],
meta=RfFrameMeta.from_name(data[4:id2].decode()),
data=data[id2 + 4:],
)
@dataclasses.dataclass
class BytesMsg(Msg):
value: bytes
def encode(self) -> bytes:
return self.value
@classmethod
def decode(cls, data: bytes) -> 'Msg':
return cls(data)
def split(self):
pass
# id2 = r.index(Msg.magic(), 1)
# id3 = r.index(Msg.magic(), id2 + 1)
# print(id2, id3)
# seq_msg: SetSeqMetaMsg = Msg.decode_msg(r[0:id2])
# arg_msg: ImageArgMsg = Msg.decode_msg(r[id2:id3])
# b_msg: RfFrameMsg = Msg.decode_msg(r[id3:-1])
class BeamformerMsg(BytesMsg):
pass
@dataclasses.dataclass @dataclasses.dataclass
class RobotRtsiMsg(Msg): class RobotRtsiMsg(Msg):
pos: tuple[float, float, float, float, float, float] pos: tuple[float, float, float, float, float, float]
force: tuple[float, float, float, float, float, float] force: tuple[float, float, float, float, float, float]
class RequestRfFrameMsg(Msg):
pass
def test(): def test():
values = set(item.name for item in BG) values = set(item.name for item in BG)
for k in globals().keys(): for k in globals().keys():

View File

@ -6,8 +6,9 @@ from nodes.Beamformer import Beamformer
from nodes.Broker import Broker from nodes.Broker import Broker
from nodes.Device import Device from nodes.Device import Device
from nodes.ImageCV import ImageCV from nodes.ImageCV import ImageCV
from nodes.ImageFFMPEG import ImageFFMPEG
from nodes.Loader import Loader from nodes.Loader import Loader
from nodes.Muxer import Receiver from nodes.Muxer import Muxer
from nodes.Robot import Robot from nodes.Robot import Robot
from nodes.WebRTC import WebRTC from nodes.WebRTC import WebRTC
from qtonly import kde_pyqt6_mainui from qtonly import kde_pyqt6_mainui
@ -20,13 +21,14 @@ if __name__ == '__main__':
pps = [] pps = []
ps = [ ps = [
Broker(), Broker(),
# WebRTC(), WebRTC(),
kde_pyqt6_mainui, kde_pyqt6_mainui,
Device(level=logging.DEBUG), Device(level=logging.DEBUG),
ImageFFMPEG(),
ImageCV(level=logging.DEBUG), ImageCV(level=logging.DEBUG),
Beamformer(), Beamformer(level=logging.DEBUG),
Loader(), Loader(),
Receiver(), Muxer(level=logging.DEBUG),
Robot(), Robot(),
] ]
for p in ps: for p in ps:

View File

@ -1,2 +1,4 @@
if __name__ == '__main__': if __name__ == '__main__':
print(tuple(str((1, 2, 3)))) print(tuple(str((1, 2, 3))))
print([1,2,3][-1:1])
print([1,2,3][1:])

View File

@ -2,9 +2,12 @@ from miio.miioprotocol import MiIOProtocol
from config import SWITCH1_IP, SWITCH1_TOKEN, SWITCH2_IP, SWITCH2_TOKEN from config import SWITCH1_IP, SWITCH1_TOKEN, SWITCH2_IP, SWITCH2_TOKEN
from miio import Device from miio import Device
from utils.mi import c1_disconnect, c1_connect
if __name__ == '__main__': if __name__ == '__main__':
m = MiIOProtocol( # m = MiIOProtocol(
SWITCH1_IP, SWITCH1_TOKEN, # SWITCH1_IP, SWITCH1_TOKEN,
) # )
r = m.send('get_properties', [{'did': 'MYDID', 'siid': 2, 'piid': 1}]) # r = m.send('get_properties', [{'did': 'MYDID', 'siid': 2, 'piid': 1}])
print(r[0]['value']) # print(r[0]['value'])
c1_connect()