@@ -37,6 +37,33 @@ def get_local_ip(remote):
3737 sock .close ()
3838
3939
40+ class Frame :
41+ """Stream frame constisting of a header and multiple data batches"""
42+
43+ # The magic header half-word at the start of each packet.
44+ magic = 0x057B
45+ header_fmt = struct .Struct ("<HBBI" )
46+ header = namedtuple ("Header" , "magic format_id batches sequence" )
47+ parsers = {}
48+
49+ @classmethod
50+ def register (cls , fmt ):
51+ """Register a format"""
52+ cls .parsers [fmt .format_id ] = fmt
53+
54+ @classmethod
55+ def parse (cls , data ):
56+ """Parse known length frame"""
57+ header = cls .header ._make (cls .header_fmt .unpack_from (data ))
58+ if header .magic != cls .magic :
59+ raise ValueError (f"Bad frame magic: { header .magic :#04x} " )
60+ try :
61+ parser = cls .parsers [header .format_id ]
62+ except KeyError as exc :
63+ raise ValueError (f"No parser for format: { header .format_id } " ) from exc
64+ return parser (header , data [cls .header_fmt .size :])
65+
66+
4067class AdcDac :
4168 """Stabilizer default striming data format"""
4269
@@ -79,6 +106,9 @@ def to_traces(self):
79106 ]
80107
81108
109+ Frame .register (AdcDac )
110+
111+
82112class ThermostatEem :
83113 """Thermostat-EEM format"""
84114
@@ -99,8 +129,12 @@ def to_si(self):
99129 )
100130
101131
132+ Frame .register (ThermostatEem )
133+
134+
102135class Fls :
103136 """FLS application stream format"""
137+
104138 format_id = 2
105139
106140 def __init__ (self , header , body ):
@@ -122,11 +156,15 @@ def demod(self):
122156 return self .to_mu ()[:, :, :2 ]
123157
124158
159+ Frame .register (Fls )
160+
161+
125162class Mpll :
126163 """MPLL application stream format"""
164+
127165 format_id = 4
128166
129- dtype = np .dtype ([("demod" , "<i4" , (2 ,2 )), ("phase" , "<i4" ), ("frequency" , "<i4" )])
167+ dtype = np .dtype ([("demod" , "<i4" , (2 , 2 )), ("phase" , "<i4" ), ("frequency" , "<i4" )])
130168
131169 def __init__ (self , header , body ):
132170 self .header = header
@@ -141,31 +179,29 @@ def to_mu(self):
141179 return np .frombuffer (self .body , self .dtype )
142180
143181
144- class Frame :
145- """Stream frame constisting of a header and multiple data batches"""
182+ Frame .register (Mpll )
146183
147- # The magic header half-word at the start of each packet.
148- magic = 0x057B
149- header_fmt = struct .Struct ("<HBBI" )
150- header = namedtuple ("Header" , "magic format_id batches sequence" )
151- parsers = {
152- AdcDac .format_id : AdcDac ,
153- ThermostatEem .format_id : ThermostatEem ,
154- Fls .format_id : Fls ,
155- Mpll .format_id : Mpll ,
156- }
157184
158- @classmethod
159- def parse (cls , data ):
160- """Parse known length frame"""
161- header = cls .header ._make (cls .header_fmt .unpack_from (data ))
162- if header .magic != cls .magic :
163- raise ValueError (f"Bad frame magic: { header .magic :#04x} " )
164- try :
165- parser = cls .parsers [header .format_id ]
166- except KeyError as exc :
167- raise ValueError (f"No parser for format: { header .format_id } " ) from exc
168- return parser (header , data [cls .header_fmt .size :])
185+ class Fls2 :
186+ """FLS2 application stream format"""
187+
188+ format_id = 5
189+
190+ def __init__ (self , header , body ):
191+ self .header = header
192+ self .body = body
193+
194+ def size (self ):
195+ """Return the data size of the frame in bytes"""
196+ return len (self .body )
197+
198+ def to_mu (self ):
199+ """Return the raw data in machine units"""
200+ data = np .frombuffer (self .body , "<i4" )
201+ return data
202+
203+
204+ Frame .register (Fls2 )
169205
170206
171207class Stream (asyncio .DatagramProtocol ):
@@ -199,6 +235,13 @@ async def open(cls, port=9293, addr="0.0.0.0", local="0.0.0.0", maxsize=1):
199235 socket .IP_ADD_MEMBERSHIP ,
200236 multiaddr + local ,
201237 )
238+ try :
239+ # OS filter
240+ sock .setsockopt (
241+ socket .IPPROTO_IP , getattr (socket , "IP_MULTICAST_ALL" , 49 ), 0
242+ )
243+ except OSError :
244+ pass # Windows
202245 sock .bind ((addr , port ))
203246 return await loop .create_datagram_endpoint (
204247 lambda : cls (maxsize ),
0 commit comments