Skip to content

Commit cf9d8db

Browse files
authored
Merge pull request #19 from ess-dmsc/add_ep00_schema
Add ep00 schema
2 parents 4277f7f + 27415b9 commit cf9d8db

File tree

6 files changed

+189
-0
lines changed

6 files changed

+189
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ https://github.com/ess-dmsc/streaming-data-types
1616
|ev42|Event Data|Y|
1717
|x5f2|Status messages|N|
1818
|tdct|Timestamps|Y|
19+
|ep00|EPICS Connection Info|Y|
1920

2021
\* whether it passes verification via the C++ FlatBuffers library.
2122

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from typing import Union, Optional
2+
import flatbuffers
3+
from streaming_data_types.fbschemas.epics_connection_info_ep00 import (
4+
EpicsConnectionInfo,
5+
EventType,
6+
)
7+
from streaming_data_types.utils import check_schema_identifier
8+
from collections import namedtuple
9+
10+
FILE_IDENTIFIER = b"ep00"
11+
12+
13+
def serialise_ep00(
14+
timestamp_ns: int,
15+
event_type: EventType,
16+
source_name: str,
17+
service_id: Optional[str] = None,
18+
) -> bytes:
19+
builder = flatbuffers.Builder(136)
20+
21+
if service_id is not None:
22+
service_id_offset = builder.CreateString(service_id)
23+
source_name_offset = builder.CreateString(source_name)
24+
25+
EpicsConnectionInfo.EpicsConnectionInfoStart(builder)
26+
if service_id is not None:
27+
EpicsConnectionInfo.EpicsConnectionInfoAddServiceId(builder, service_id_offset)
28+
EpicsConnectionInfo.EpicsConnectionInfoAddSourceName(builder, source_name_offset)
29+
EpicsConnectionInfo.EpicsConnectionInfoAddType(builder, event_type)
30+
EpicsConnectionInfo.EpicsConnectionInfoAddTimestamp(builder, timestamp_ns)
31+
32+
end = EpicsConnectionInfo.EpicsConnectionInfoEnd(builder)
33+
builder.Finish(end)
34+
35+
# Generate the output and replace the file_identifier
36+
buffer = builder.Output()
37+
buffer[4:8] = FILE_IDENTIFIER
38+
return bytes(buffer)
39+
40+
41+
EpicsConnection = namedtuple(
42+
"EpicsConnection", ("timestamp", "type", "source_name", "service_id",),
43+
)
44+
45+
46+
def deserialise_ep00(buffer: Union[bytearray, bytes]) -> EpicsConnection:
47+
check_schema_identifier(buffer, FILE_IDENTIFIER)
48+
49+
epics_connection = EpicsConnectionInfo.EpicsConnectionInfo.GetRootAsEpicsConnectionInfo(
50+
buffer, 0
51+
)
52+
53+
source_name = (
54+
epics_connection.SourceName() if epics_connection.SourceName() else b""
55+
)
56+
service_id = epics_connection.ServiceId() if epics_connection.ServiceId() else b""
57+
58+
return EpicsConnection(
59+
epics_connection.Timestamp(),
60+
epics_connection.Type(),
61+
source_name.decode(),
62+
service_id.decode(),
63+
)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# automatically generated by the FlatBuffers compiler, do not modify
2+
3+
# namespace:
4+
5+
import flatbuffers
6+
7+
8+
class EpicsConnectionInfo(object):
9+
__slots__ = ["_tab"]
10+
11+
@classmethod
12+
def GetRootAsEpicsConnectionInfo(cls, buf, offset):
13+
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
14+
x = EpicsConnectionInfo()
15+
x.Init(buf, n + offset)
16+
return x
17+
18+
# EpicsConnectionInfo
19+
def Init(self, buf, pos):
20+
self._tab = flatbuffers.table.Table(buf, pos)
21+
22+
# EpicsConnectionInfo
23+
def Timestamp(self):
24+
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
25+
if o != 0:
26+
return self._tab.Get(
27+
flatbuffers.number_types.Uint64Flags, o + self._tab.Pos
28+
)
29+
return 0
30+
31+
# EpicsConnectionInfo
32+
def Type(self):
33+
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
34+
if o != 0:
35+
return self._tab.Get(
36+
flatbuffers.number_types.Uint16Flags, o + self._tab.Pos
37+
)
38+
return 0
39+
40+
# EpicsConnectionInfo
41+
def SourceName(self):
42+
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
43+
if o != 0:
44+
return self._tab.String(o + self._tab.Pos)
45+
return None
46+
47+
# EpicsConnectionInfo
48+
def ServiceId(self):
49+
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
50+
if o != 0:
51+
return self._tab.String(o + self._tab.Pos)
52+
return None
53+
54+
55+
def EpicsConnectionInfoStart(builder):
56+
builder.StartObject(4)
57+
58+
59+
def EpicsConnectionInfoAddTimestamp(builder, timestamp):
60+
builder.PrependUint64Slot(0, timestamp, 0)
61+
62+
63+
def EpicsConnectionInfoAddType(builder, type):
64+
builder.PrependUint16Slot(1, type, 0)
65+
66+
67+
def EpicsConnectionInfoAddSourceName(builder, sourceName):
68+
builder.PrependUOffsetTRelativeSlot(
69+
2, flatbuffers.number_types.UOffsetTFlags.py_type(sourceName), 0
70+
)
71+
72+
73+
def EpicsConnectionInfoAddServiceId(builder, serviceId):
74+
builder.PrependUOffsetTRelativeSlot(
75+
3, flatbuffers.number_types.UOffsetTFlags.py_type(serviceId), 0
76+
)
77+
78+
79+
def EpicsConnectionInfoEnd(builder):
80+
return builder.EndObject()
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# automatically generated by the FlatBuffers compiler, do not modify
2+
3+
# namespace:
4+
5+
6+
class EventType(object):
7+
UNKNOWN = 0
8+
NEVER_CONNECTED = 1
9+
CONNECTED = 2
10+
DISCONNECTED = 3
11+
DESTROYED = 4

streaming_data_types/fbschemas/epics_connection_info_ep00/__init__.py

Whitespace-only changes.

tests/test_ep00.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import pytest
2+
from streaming_data_types.fbschemas.epics_connection_info_ep00 import EventType
3+
from streaming_data_types.epics_connection_info_ep00 import (
4+
serialise_ep00,
5+
deserialise_ep00,
6+
)
7+
8+
9+
class TestSerialisationEp00:
10+
original_entry = {
11+
"timestamp_ns": 1593620746000000000,
12+
"event_type": EventType.EventType.DISCONNECTED,
13+
"source_name": "test_source",
14+
"service_id": "test_service",
15+
}
16+
17+
def test_serialises_and_deserialises_ep00_message_correctly(self):
18+
buf = serialise_ep00(**self.original_entry)
19+
deserialised_tuple = deserialise_ep00(buf)
20+
21+
assert deserialised_tuple.timestamp == self.original_entry["timestamp_ns"]
22+
assert deserialised_tuple.type == self.original_entry["event_type"]
23+
assert deserialised_tuple.source_name == self.original_entry["source_name"]
24+
assert deserialised_tuple.service_id == self.original_entry["service_id"]
25+
26+
def test_if_buffer_has_wrong_id_then_throws(self):
27+
buf = serialise_ep00(**self.original_entry)
28+
29+
# Manually hack the id
30+
buf = bytearray(buf)
31+
buf[4:8] = b"1234"
32+
33+
with pytest.raises(RuntimeError):
34+
deserialise_ep00(buf)

0 commit comments

Comments
 (0)