major improvements and rework

- add stream / instrument availability data
- events contain event kind for dispatching db methods
This commit is contained in:
2025-02-24 14:54:54 +01:00
parent 832252bbbb
commit c0aeca523a
6 changed files with 501 additions and 231 deletions

View File

@ -16,6 +16,14 @@ class EnumConvert(dict):
return float(self[value])
class TagsDict(dict):
def __init__(self, default_value):
self.default_value = default_value
def __missing__(self, key):
return self.default_value
class SecopStream(Stream):
ping_time = 0
@ -47,12 +55,12 @@ class SecopStream(Stream):
self.tags['device'] = self.device
self.modules = self.descr['modules']
self.convert = {}
self.original_id = {}
self.tags_dict = TagsDict(self.tags)
for mod, moddesc in self.modules.items():
for key in ('_original_id', 'original_id'):
value = moddesc.get(key)
if value:
self.original_id[mod] = value
self.tags_dict[mod] = dict(self.tags, device=value)
break
for param, desc in moddesc['accessibles'].items():
dt = desc['datainfo']
@ -64,11 +72,10 @@ class SecopStream(Stream):
self.send('ping')
def get_tags(self, key):
return dict(self.tags, device=self.original_id.get(key[0], self.device))
return self.tags_dict[key[0]]
def event_generator(self):
try:
cnt = 0
for msg in self.get_lines():
match = UPDATE.match(msg)
if match:
@ -78,23 +85,23 @@ class SecopStream(Stream):
cvt = self.convert.get(key)
if cvt:
data = json.loads(data)
tags = self.tags_dict[key[0]]
if cmd == 'error_update':
error = ': '.join(data[0:2])
print(msg, repr(error))
ts = data[2].get('t', time.time())
value = None
timestamp = data[2].get('t', time.time())
yield 'error', error, key, tags, timestamp
else:
error = None
ts = data[1].get('t', time.time())
value = cvt(data[0])
cnt += 1
yield key, value, error, ts, self.get_tags(key)
timestamp = data[1].get('t', time.time())
yield 'value', value, key, tags, timestamp
elif msg == 'active':
# from now on, no more waiting
self.notimeout()
except Exception as e:
print(self.uri, repr(e))
raise
SECOP_UDP_PORT = 10767
@ -115,6 +122,8 @@ class UdpStream(Base):
continue
if kind == 'for_other_node':
uri = msg.pop('uri')
if 'device' not in msg:
msg['device'] = uri.split('://', 1)[-1].split(':')[0]
kwargs = msg
elif kind == 'node':
uri = f"{addr[0]}:{msg['port']}"
@ -152,14 +161,17 @@ class ScanStream(UdpStream):
self.select_dict[sock.fileno()] = self
def send_fake_udp(uri, device='fake'):
def send_fake_udp(uri, device=None, instrument=None):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
msg = json.dumps({
msg = {
'SECoP': 'for_other_node',
'uri': uri,
'device': device,
}, ensure_ascii=False, separators=(',', ':')).encode('utf-8')
sock.sendto(msg, ('255.255.255.255', SECOP_UDP_PORT))
}
if device:
msg['device'] = device
msg['instrument'] = instrument or '0'
sock.sendto(json.dumps(msg, ensure_ascii=False, separators=(',', ':')).encode('utf-8'),
('255.255.255.255', SECOP_UDP_PORT))