2019-02-18 18:05:05 +01:00
|
|
|
import re
|
2020-06-07 18:13:29 +01:00
|
|
|
from datetime import datetime
|
2020-06-07 23:24:21 +02:00
|
|
|
from functools import total_ordering
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
|
|
|
|
@total_ordering
|
2019-02-18 18:05:05 +01:00
|
|
|
class Timestamp:
|
2020-06-07 23:24:21 +02:00
|
|
|
"""Parsing the VILLASnode human-readable timestamp format"""
|
|
|
|
|
|
|
|
def __init__(self, seconds=None, nanoseconds=None,
|
|
|
|
offset=None, sequence=None):
|
|
|
|
self.seconds = seconds
|
|
|
|
self.nanoseconds = nanoseconds
|
|
|
|
self.offset = offset
|
|
|
|
self.sequence = sequence
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
@classmethod
|
|
|
|
def now(cls, offset=None, sequence=None):
|
|
|
|
n = datetime.utcnow()
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
secs = int(n.timestamp())
|
|
|
|
nsecs = 1000 * n.microsecond
|
2020-06-07 18:13:29 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
return Timestamp(seconds=secs, nanoseconds=nsecs,
|
|
|
|
offset=offset, sequence=sequence)
|
2020-06-07 18:13:29 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
@classmethod
|
|
|
|
def parse(cls, ts):
|
|
|
|
m = re.match(r'(\d+)(?:\.(\d+))?([-+]\d+(?:\.\d+)?'
|
|
|
|
r'(?:e[+-]?\d+)?)?(?:\((\d+)\))?', ts)
|
2020-06-07 18:13:29 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
seconds = int(m.group(1)) # Mandatory
|
|
|
|
nanoseconds = int(m.group(2)) if m.group(2) else None
|
|
|
|
offset = float(m.group(3)) if m.group(3) else None
|
|
|
|
sequence = int(m.group(4)) if m.group(4) else None
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
return Timestamp(seconds, nanoseconds, offset, sequence)
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
def __str__(self):
|
|
|
|
str = "%u" % (self.seconds)
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
if self.nanoseconds is not None:
|
|
|
|
str += ".%09u" % self.nanoseconds
|
|
|
|
if self.offset is not None:
|
|
|
|
str += "+%u" % self.offset
|
|
|
|
if self.sequence is not None:
|
|
|
|
str += "(%u)" % self.sequence
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
return str
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
def __float__(self):
|
|
|
|
sum = float(self.seconds)
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
if self.nanoseconds is not None:
|
|
|
|
sum += self.nanoseconds * 1e-9
|
|
|
|
if self.offset is not None:
|
|
|
|
sum += self.offset
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
return sum
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
def __eq__(self, other):
|
|
|
|
return float(self) == float(other)
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
def __lt__(self, other):
|
|
|
|
return float(self) < float(other)
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
|
|
|
|
@total_ordering
|
2019-02-18 18:05:05 +01:00
|
|
|
class Sample:
|
2020-06-07 23:24:21 +02:00
|
|
|
"""Parsing a VILLASnode sample from a file (not a UDP package!!)"""
|
|
|
|
|
|
|
|
def __init__(self, ts, values):
|
|
|
|
self.ts = ts
|
|
|
|
self.values = values
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
@classmethod
|
|
|
|
def parse(cls, line):
|
|
|
|
csv = line.split()
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
ts = Timestamp.parse(csv[0])
|
|
|
|
vs = []
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
for value in csv[1:]:
|
|
|
|
try:
|
|
|
|
v = float(value)
|
|
|
|
except ValueError:
|
|
|
|
value = value.lower()
|
|
|
|
try:
|
|
|
|
v = complex(value)
|
|
|
|
except Exception:
|
|
|
|
if value.endswith('i'):
|
|
|
|
v = complex(value.replace('i', 'j'))
|
|
|
|
else:
|
|
|
|
raise ValueError()
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
vs.append(v)
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
return Sample(ts, vs)
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
def __str__(self):
|
2020-07-05 13:13:30 +01:00
|
|
|
return '%s\t%s' % (self.ts, "\t".join(map(str, self.values)))
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
def __eq__(self, other):
|
|
|
|
return self.ts == other.ts
|
2019-02-18 18:05:05 +01:00
|
|
|
|
2020-06-07 23:24:21 +02:00
|
|
|
def __lt__(self, other):
|
|
|
|
return self.ts < other.ts
|