Skip to content

Commit 22b6064

Browse files
authored
Merge pull request #16 from poledna/master
UDP Support V0.1
2 parents 83778ae + 41383ff commit 22b6064

File tree

5 files changed

+395
-203
lines changed

5 files changed

+395
-203
lines changed

examples/tinyPDC.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from synchrophasor.pdc import Pdc
22
from synchrophasor.frame import DataFrame
3-
3+
import pickle
4+
import socket
45
"""
56
tinyPDC will connect to pmu_ip:pmu_port and send request
67
for header message, configuration and eventually
@@ -10,23 +11,32 @@
1011

1112
if __name__ == "__main__":
1213

13-
pdc = Pdc(pdc_id=7, pmu_ip="127.0.0.1", pmu_port=1410)
14+
pdc = Pdc(pdc_id=7, pmu_ip=socket.gethostbyname("rasp"), pmu_port=10000,method='udp')
1415
pdc.logger.setLevel("DEBUG")
1516

1617
pdc.run() # Connect to PMU
1718

18-
header = pdc.get_header() # Get header message from PMU
19+
# header = pdc.get_header() # Get header message from PMU
1920
config = pdc.get_config() # Get configuration from PMU
2021

2122
pdc.start() # Request to start sending measurements
22-
23+
timestamps=[]
24+
i=0
2325
while True:
2426

2527
data = pdc.get() # Keep receiving data
2628

2729
if type(data) == DataFrame:
28-
print(data.get_measurements())
30+
data=data.get_measurements()
31+
i+=1
32+
timestamps.append(data['time'])
2933

3034
if not data:
31-
pdc.quit() # Close connection
35+
continue
36+
if i==240:
3237
break
38+
39+
pdc.stop()
40+
pdc.quit()
41+
with open("timestamps","wb+")as handle:
42+
pickle.dump(timestamps,handle)

synchrophasor/frame.py

+30-33
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929
__license__ = "BSD-3"
3030
__version__ = "1.0.0-alpha"
3131

32+
###############################################################
33+
34+
# UDP connection was implemented by Yuri Poledna under the supervision of
35+
36+
# Prof. Eduardo Parente in R&D project supported by Brazilian electric utility
37+
38+
# Companhia Paranaense de Energia – COPEL.
39+
###############################################################
3240

3341
class CommonFrame(metaclass=ABCMeta):
3442
"""
@@ -75,15 +83,17 @@ def __init__(self, frame_type, pmu_id_code, soc=None, frasec=None, version=1):
7583
:param int version:
7684
:return:
7785
"""
78-
86+
7987
self.set_frame_type(frame_type)
8088
self.set_version(version)
8189
self.set_id_code(pmu_id_code)
82-
90+
8391
if soc or frasec:
8492
self.set_time(soc, frasec)
8593

8694

95+
def get_receivedData():
96+
return self.receivedData
8797
def set_frame_type(self, frame_type):
8898
"""
8999
### set_frame_type() ###
@@ -133,7 +143,7 @@ def get_frame_type(self):
133143

134144
def extract_frame_type(byte_data):
135145
"""This method will only return type of the frame. It shall be used for stream splitter
136-
since there is no need to create instance of specific frame which will cause lower performance."""
146+
since there Phasor 5 Angle(rad): 0.6818265914916992is no need to create instance of specific frame which will cause lower performance."""
137147

138148
# Check if frame is valid
139149
if not CommandFrame._check_crc(byte_data):
@@ -226,12 +236,11 @@ def set_time(self, soc=None, frasec=None):
226236

227237
t = time() # Get current timestamp
228238

229-
if soc:
239+
if soc is not None:
230240
self.set_soc(soc)
231241
else:
232242
self.set_soc(int(t)) # Get current timestamp
233-
234-
if frasec:
243+
if frasec is not None:
235244
if isinstance(frasec, collections.Sequence):
236245
self.set_frasec(*frasec)
237246
else:
@@ -241,7 +250,6 @@ def set_time(self, soc=None, frasec=None):
241250
# overflow (24 bit number).
242251
self.set_frasec(int((((repr((t % 1))).split("."))[1])[0:6]))
243252

244-
245253
def set_soc(self, soc):
246254
"""
247255
### set_soc() ###
@@ -370,8 +378,6 @@ def set_frasec(self, fr_seconds, leap_dir="+", leap_occ=False, leap_pen=False, t
370378
frasec |= fr_seconds # Bits 23-0: Fraction of second.
371379

372380
self._frasec = frasec
373-
374-
375381
def get_frasec(self):
376382

377383
return self._int2frasec(self._frasec)
@@ -392,7 +398,7 @@ def _int2frasec(frasec_int):
392398
leap_occ = bool(leap_occ)
393399
leap_pen = bool(leap_pen)
394400

395-
fr_seconds = frasec_int & (2**23-1)
401+
fr_seconds = frasec_int & (2**24-1)
396402

397403
return fr_seconds, leap_dir, leap_occ, leap_pen, time_quality
398404

@@ -592,7 +598,6 @@ def _int2format(data_format):
592598
def _check_crc(byte_data):
593599

594600
crc_calculated = crc16xmodem(byte_data[0:-2], 0xffff).to_bytes(2, "big") # Calculate CRC
595-
596601
if byte_data[-2:] != crc_calculated:
597602
return False
598603

@@ -632,7 +637,6 @@ def convert2bytes(self, byte_message):
632637

633638
@abstractmethod
634639
def convert2frame(byte_data, cfg=None):
635-
636640
convert_method = {
637641
0: DataFrame.convert2frame,
638642
1: HeaderFrame.convert2frame,
@@ -1114,7 +1118,7 @@ def _phunit2int(scale, phasor_type="v"):
11141118
* ``scale`` **(int)** - scale factor.
11151119
* ``phasor_type`` **(char)** - ``v`` - voltage, ``i`` - current.
11161120
Default value: ``v``.
1117-
1121+
phasor
11181122
**Returns:**
11191123
11201124
* ``int`` which represents phasor channels conversion factor.
@@ -1847,14 +1851,15 @@ class DataFrame(CommonFrame):
18471851
TRIGGER_REASON_WORDS = { code: word for word, code in TRIGGER_REASON.items() }
18481852

18491853

1850-
def __init__(self, pmu_id_code, stat, phasors, freq, dfreq, analog, digital, cfg, soc=None, frasec=None):
1854+
def __init__(self, pmu_id_code, stat, phasors, freq, dfreq, analog, digital, cfg, soc=None, frasec=None,receivedData1=b'0'):
18511855

18521856
if not isinstance(cfg, ConfigFrame2):
18531857
raise FrameError("CFG should describe current data stream (ConfigurationFrame2)")
18541858

18551859
# Common frame for Configuration frame 2 with PMU simulator ID CODE which sends configuration frame.
18561860
super().__init__("data", pmu_id_code, soc, frasec)
1857-
1861+
1862+
self.receivedData=receivedData1
18581863
self.cfg = cfg
18591864
self.set_stat(stat)
18601865
self.set_phasors(phasors)
@@ -1864,6 +1869,8 @@ def __init__(self, pmu_id_code, stat, phasors, freq, dfreq, analog, digital, cfg
18641869
self.set_digital(digital)
18651870

18661871

1872+
def getReceivedData(self):
1873+
return self.receivedData
18671874
def set_stat(self, stat):
18681875

18691876
if self.cfg._num_pmu > 1:
@@ -2037,24 +2044,18 @@ def get_phasors(self, convert2polar=True):
20372044

20382045
@staticmethod
20392046
def _phasor2int(phasor, data_format):
2040-
20412047
if not isinstance(phasor, tuple):
20422048
raise TypeError("Provide phasor measurement as tuple. Rectangular - (Re, Im); Polar - (Mg, An).")
20432049

20442050
if isinstance(data_format, int):
20452051
data_format = DataFrame._int2format(data_format)
20462052

20472053
if data_format[0]: # Polar representation
2048-
20492054
if data_format[1]: # Floating Point
2050-
2051-
if not -3.142 <= phasor[1] <= 3.142:
2052-
raise ValueError("Angle must be in range -3.14 <= ANGLE <= 3.14")
2053-
2055+
# raise ValueError("Angle must be in range -3.14 <= ANGLE <= 3.14")
20542056
mg = pack("!f", float(phasor[0]))
20552057
an = pack("!f", float(phasor[1]))
20562058
measurement = mg + an
2057-
20582059
else: # Polar 16-bit representations
20592060

20602061
if not 0 <= phasor[0] <= 65535:
@@ -2085,7 +2086,6 @@ def _phasor2int(phasor, data_format):
20852086
re = pack("!h", phasor[0])
20862087
im = pack("!h", phasor[1])
20872088
measurement = re + im
2088-
20892089
return int.from_bytes(measurement, "big", signed=False)
20902090

20912091

@@ -2141,15 +2141,12 @@ def _freq2int(freq, data_format):
21412141
data_format = DataFrame._int2format(data_format)
21422142

21432143
if data_format[3]: # FREQ/DFREQ floating point
2144-
if not -32.767 <= freq <= 32.767:
2145-
raise ValueError("FREQ must be in range -32.767 <= FREQ <= 32.767.")
2146-
2144+
#raise ValueError("FREQ must be in range -32.767 <= FREQ <= 32.767.")
21472145
freq = unpack("!I", pack("!f", float(freq)))[0]
21482146
else:
21492147
if not -32767 <= freq <= 32767:
21502148
raise ValueError("FREQ must be 16-bit signed integer. -32767 <= FREQ <= 32767.")
21512149
freq = unpack("!H", pack("!h", freq))[0]
2152-
21532150
return freq
21542151

21552152

@@ -2368,12 +2365,12 @@ def get_measurements(self):
23682365
"phasors": self.get_phasors(),
23692366
"analog": self.get_analog(),
23702367
"digital": self.get_digital(),
2371-
"frequency": self.cfg.get_fnom() + self.get_freq() / 1000,
2368+
#"frequency": self.cfg.get_fnom() + self.get_freq() / 1000,
2369+
"frequency": self.get_freq(),
23722370
"rocof": self.get_dfreq()
23732371
})
2374-
23752372
data_frame = { "pmu_id": self._pmu_id_code,
2376-
"time": self.get_soc() + self.get_frasec()[0] / self.cfg.get_time_base(),
2373+
"time": (self.get_soc() + (self.get_frasec()[0] / self.cfg.get_time_base())),
23772374
"measurements": measurements }
23782375

23792376
return data_frame
@@ -2414,7 +2411,8 @@ def convert2bytes(self):
24142411

24152412
@staticmethod
24162413
def convert2frame(byte_data, cfg):
2417-
2414+
2415+
24182416
try:
24192417

24202418
if not CommonFrame._check_crc(byte_data):
@@ -2429,7 +2427,6 @@ def convert2frame(byte_data, cfg):
24292427
pmu_code = int.from_bytes(byte_data[4:6], byteorder="big", signed=False)
24302428
soc = int.from_bytes(byte_data[6:10], byteorder="big", signed=False)
24312429
frasec = CommonFrame._int2frasec(int.from_bytes(byte_data[10:14], byteorder="big", signed=False))
2432-
24332430
start_byte = 14
24342431

24352432
if num_pmu > 1:
@@ -2515,7 +2512,7 @@ def convert2frame(byte_data, cfg):
25152512
digital.append(dig)
25162513
start_byte += 2
25172514

2518-
return DataFrame(pmu_code, stat, phasors, freq, dfreq, analog, digital, cfg, soc, frasec)
2515+
return DataFrame(pmu_code, stat, phasors, freq, dfreq, analog, digital, cfg, soc, frasec, byte_data)
25192516

25202517
except Exception as error:
25212518
raise FrameError("Error while creating Data frame: " + str(error))

0 commit comments

Comments
 (0)