fmu-manipulation-toolbox 1.9.2b2__py3-none-any.whl → 1.9.2b3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- 'V1.9.2b2'
1
+ 'V1.9.2b3'
@@ -0,0 +1,143 @@
1
+ import argparse
2
+ import csv
3
+ import logging
4
+ import sys
5
+
6
+ from pathlib import Path
7
+ from typing import *
8
+
9
+ from .utils import setup_logger, close_logger, make_wide
10
+ from ..version import __version__ as version
11
+
12
+ logger = setup_logger()
13
+
14
+ class DatalogConverter:
15
+ def __init__(self, cvs_filename: Union[Path, str]):
16
+ self.csv_filename = Path(cvs_filename)
17
+ self.pcap_filename = self.csv_filename.with_suffix(".pcap")
18
+
19
+ def open_pcap(self):
20
+ logger.info(f"Creating PCAP file '{self.pcap_filename}'...")
21
+ file = open(self.pcap_filename, "wb")
22
+ file.write(int(0xA1B2C3D4).to_bytes(4, byteorder="big")) # Magic number
23
+ # meaning the timestamp are in min seconds and microseconds
24
+
25
+ file.write(int(2).to_bytes(2, byteorder="big")) # Major Version of fileformat
26
+ file.write(int(4).to_bytes(2, byteorder="big")) # Minor Version
27
+ file.write(int(0).to_bytes(4, byteorder="big")) # Reserved. SHOULD BE 0.
28
+ file.write(int(0).to_bytes(4, byteorder="big")) # Reserved. SHOULD BE 0.
29
+
30
+ file.write(int(0xFFFF).to_bytes(4, byteorder="big")) # snaplen indicating the maximum number of octets
31
+ # captured from each packet.
32
+
33
+ file.write(int(227).to_bytes(4, byteorder="big")) # link type. his field is defined in the Section
34
+ # # 8.1 IANA registry.
35
+ return file
36
+
37
+ def open_csv(self):
38
+ logger.debug(f"Loading '{self.csv_filename}'")
39
+ file = open(self.csv_filename, "rt")
40
+ return file
41
+
42
+ def decode_hexstring(self, hex_string: bytes, time_s, time_us):
43
+ opcode = int.from_bytes(hex_string[0:4], byteorder="little")
44
+ length = int.from_bytes(hex_string[4:8], byteorder="little")
45
+ can_id = int.from_bytes(hex_string[8:12], byteorder="little")
46
+ if opcode == 0x10: # TRANSMIT
47
+ rtr = int.from_bytes(hex_string[13:14], byteorder="little")
48
+ ide = int.from_bytes(hex_string[12:13], byteorder="little")
49
+ data_length = int.from_bytes(hex_string[14:16], byteorder="little")
50
+ raw_data = hex_string[16:]
51
+
52
+ logger.debug(f"time={time_s}.{time_us:06d} OP=0x{opcode:04X} len={length} {data_length} id={can_id}"
53
+ f" ide={ide} rtr={rtr} len={data_length} {raw_data}")
54
+
55
+ # TimeStamp
56
+ self.pcapfile.write(time_s.to_bytes(4, byteorder="big"))
57
+ self.pcapfile.write(time_us.to_bytes(4, byteorder="big"))
58
+
59
+ # Packet length
60
+ packet_length = data_length + 8
61
+ self.pcapfile.write(packet_length.to_bytes(4, byteorder="big"))
62
+ self.pcapfile.write(packet_length.to_bytes(4, byteorder="big"))
63
+
64
+ # Control and flags
65
+ control = (can_id & 0x1FFFFFFF) | ((rtr & 0b1) << 30) | ((ide & 0b1) << 31)
66
+ self.pcapfile.write(control.to_bytes(4, byteorder="big"))
67
+
68
+ # Frame Length
69
+ self.pcapfile.write(data_length.to_bytes(1, byteorder="big"))
70
+
71
+ # Reserved
72
+ self.pcapfile.write(int(0).to_bytes(2, byteorder="big"))
73
+
74
+ # DLC
75
+ dlc = int(data_length) # Classic CAN
76
+ self.pcapfile.write(dlc.to_bytes(1, byteorder="big"))
77
+
78
+ # PAYLOAD
79
+ self.pcapfile.write(raw_data)
80
+
81
+ def convert(self):
82
+ with self.open_csv() as self.csvfile, self.open_pcap() as self.pcapfile:
83
+ csv_reader = csv.DictReader(self.csvfile)
84
+
85
+ data_column_names = [ name for name in csv_reader.fieldnames if "_Data" in name ]
86
+ clock_column_names = {}
87
+
88
+ for column_name in data_column_names:
89
+ splitted_name = column_name.split(".")
90
+ splitted_name[-1] = splitted_name[-1].replace("_Data", "_Clock")
91
+ clock_column_name = ".".join(splitted_name)
92
+
93
+ if clock_column_name in csv_reader.fieldnames:
94
+ logger.debug(f"{column_name} is clocked by {clock_column_name}")
95
+ clock_column_names[column_name] = clock_column_name
96
+
97
+ for row in csv_reader:
98
+ time_s, time_us = divmod(float(row["time"]), 1)
99
+ time_s = int(time_s)
100
+ time_us = int(time_us * 1000000)
101
+
102
+ for names in data_column_names:
103
+ hex_data = row[names]
104
+ if hex_data:
105
+ try:
106
+ clock = row[clock_column_names[names]] == "1"
107
+ except KeyError:
108
+ clock = True
109
+ if clock:
110
+ self.decode_hexstring(bytes.fromhex(hex_data), time_s, time_us)
111
+
112
+
113
+ def datalog2pcap():
114
+ logger.info(f"FMUContainer version {version}")
115
+ logger.warning(f"Datalog2PCAP is still experimental.")
116
+
117
+ parser = argparse.ArgumentParser(prog="datalog2pcap", description="Convert datalog from container to PCAP file.",
118
+ formatter_class=make_wide(argparse.ArgumentDefaultsHelpFormatter),
119
+ add_help=False,
120
+ epilog="see: https://github.com/grouperenault/fmu_manipulation_toolbox/blob/main/"
121
+ "doc/datalog.md")
122
+
123
+ parser.add_argument('-h', '-help', action="help")
124
+
125
+ parser.add_argument("-can", action="store", dest="can_filename", default=None,
126
+ metavar="can-datalog.csv", required=True,
127
+ help="Datalog with CAN data and clocks.")
128
+
129
+ parser.add_argument("-debug", action="store_true", dest="debug",
130
+ help="Add lot of useful log during the process.")
131
+
132
+ config = parser.parse_args(sys.argv[1:])
133
+
134
+ if config.debug:
135
+ logger.setLevel(logging.DEBUG)
136
+
137
+ DatalogConverter(config.can_filename).convert()
138
+
139
+ close_logger(logger)
140
+
141
+
142
+ if __name__ == "__main__":
143
+ datalog2pcap()
@@ -1179,7 +1179,7 @@ class FMUContainer:
1179
1179
  clock_list.write_txt(txt_file)
1180
1180
 
1181
1181
  def make_datalog(self, datalog_file):
1182
- print(f"# Datalog filename")
1182
+ print(f"# Datalog filename", file=datalog_file)
1183
1183
  print(f"{self.identifier}-datalog.csv", file=datalog_file)
1184
1184
 
1185
1185
  ports = defaultdict(list)
@@ -1188,7 +1188,11 @@ class FMUContainer:
1188
1188
  for output_port_name, output_port in self.outputs.items():
1189
1189
  ports[output_port.port.type_name].append((output_port.vr, output_port_name))
1190
1190
  for link in self.links.values():
1191
- ports[link.cport_from.port.type_name].append((link.vr, link.name))
1191
+ if link.cport_from is None:
1192
+ # LS-BUS allows to connected to input clocks.
1193
+ ports[link.cport_to_list[0].port.type_name].append((link.vr, link.name))
1194
+ else:
1195
+ ports[link.cport_from.port.type_name].append((link.vr, link.name))
1192
1196
 
1193
1197
  for type_name in EmbeddedFMUPort.ALL_TYPES:
1194
1198
  print(f"# {type_name}: <VR> <NAME>" , file=datalog_file)
@@ -61,7 +61,7 @@ class FMUPort:
61
61
  self.dimension = None
62
62
 
63
63
  def dict_level(self, nb):
64
- return " ".join([f'{key}="{value}"' for key, value in self.attrs_list[nb].items()])
64
+ return " ".join([f'{key}="{Manipulation.escape(value)}"' for key, value in self.attrs_list[nb].items()])
65
65
 
66
66
  def write_xml(self, fmi_version: int, file):
67
67
  if fmi_version == 2:
@@ -177,7 +177,7 @@ class Manipulation:
177
177
  self.current_port = FMUPort()
178
178
  self.current_port.push_attrs(attrs)
179
179
  elif self.fmu.fmi_version == 2 and name in self.fmu.FMI2_TYPES:
180
- if self.current_port: # <Enumeration> can be found before port defition. Ignored.
180
+ if self.current_port: # <Enumeration> can be found before port definition. Ignored.
181
181
  self.current_port.fmi_type = name
182
182
  self.current_port.push_attrs(attrs)
183
183
  elif self.fmu.fmi_version == 3 and name in self.fmu.FMI3_TYPES:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmu_manipulation_toolbox
3
- Version: 1.9.2b2
3
+ Version: 1.9.2b3
4
4
  Summary: FMU Manipulation Toolbox is a python package which helps to analyze, modify or combine Functional Mock-up Units (FMUs) without recompilation.
5
5
  Home-page: https://github.com/grouperenault/fmu_manipulation_toolbox/
6
6
  Author: Nicolas.LAURENT@Renault.com
@@ -23,7 +23,7 @@ Dynamic: requires-python
23
23
  Dynamic: summary
24
24
 
25
25
  FMU Manipulation Toolbox is a python package which helps to analyze, modify or combine
26
- [Functional Mock-up Units (FMUs)](http://fmi-standard.org/) without recompilation. It is highly customizable and comes with
26
+ [Functional Mock-up Units (FMUs)](https://fmi-standard.org/) without recompilation. It is highly customizable and comes with
27
27
  a Python API.
28
28
 
29
29
  FMU Manipulation Toolbox can be used in different ways:
@@ -1,17 +1,18 @@
1
1
  fmu_manipulation_toolbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  fmu_manipulation_toolbox/__main__.py,sha256=g0ZhVsMiAs5KnhyVNwTe01N2PQjAg7F9YCnXHZB-HwA,356
3
- fmu_manipulation_toolbox/__version__.py,sha256=dxTf1L29N2UnXoeZR07PLwi-F5jmAKLCVbVRdBuxS8g,11
3
+ fmu_manipulation_toolbox/__version__.py,sha256=vSeu0JAhY6t02nCo5EseN6q_Sda8XNzKJeVB4BF160c,11
4
4
  fmu_manipulation_toolbox/assembly.py,sha256=QmFihza_I0hK0Ia6tWbjdZeoREhveLrv3d7ERrBUaDk,27217
5
5
  fmu_manipulation_toolbox/checker.py,sha256=Dh47b3blibCWjHCeZ61Y_w9Ug0PWvEuSiemZtp-llQA,3141
6
- fmu_manipulation_toolbox/container.py,sha256=5LpfqWMSkujZqkw37Y1sI2tM2BKTDOUXvyj9c-jIpqM,56680
6
+ fmu_manipulation_toolbox/container.py,sha256=AI2eEapQQDU1uEhAxKKb9mOTRigatRCJvvXir-l6aBQ,56912
7
7
  fmu_manipulation_toolbox/help.py,sha256=j8xmnCrwQpaW-SZ8hSqA1dlTXgaqzQWc4Yr3RH_oqck,6012
8
8
  fmu_manipulation_toolbox/ls.py,sha256=wmyoKrvDLXpL-PFz6cUhLLqxDMD5E9L_P4KswWpQHsk,975
9
- fmu_manipulation_toolbox/operations.py,sha256=8noR84f6Ow2sMY6d0oer5BDZ48WBRSKgwOB-aTKElzg,21154
9
+ fmu_manipulation_toolbox/operations.py,sha256=y3QDMiLaG1TUhIQ4r_onWp1kGm8QZaFfTOdQr0oC7_A,21177
10
10
  fmu_manipulation_toolbox/remoting.py,sha256=N25MDFkIcEWe9CIT1M4L9kea3j-8E7i2I1VOI6zIAdw,3876
11
11
  fmu_manipulation_toolbox/split.py,sha256=6D99SAGNu4B3PSaSsliWc6Bb5aSBZMxL8t0v8TJBI3Y,16499
12
12
  fmu_manipulation_toolbox/terminals.py,sha256=mGGS4tdE6cJuz-2zvwc7drpmT0QJ7YPe8ENw2UGlEHA,5062
13
13
  fmu_manipulation_toolbox/version.py,sha256=L26Cc3PH97SOa4G9yiYnafrdolK0G_DCQZZTvv3YXqI,392
14
14
  fmu_manipulation_toolbox/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ fmu_manipulation_toolbox/cli/datalog2pcap.py,sha256=A0KNHVTzEvzKaT5HG0zgHVRC5G1bXoIbfLRXuvOsE-U,6080
15
16
  fmu_manipulation_toolbox/cli/fmucontainer.py,sha256=ZLoC8QMVBVG2S3cdNthMIQ0gYIU9WUbYj8Aj2vxzyfs,5338
16
17
  fmu_manipulation_toolbox/cli/fmusplit.py,sha256=sLzdxiC4R5hJYJo9F2TZOMrJOHcadqCvUo9KoCjUaxE,1773
17
18
  fmu_manipulation_toolbox/cli/fmutool.py,sha256=E-CCymksBwGFlS3-zJ7DIDA8xIdp_synsxMDYXst8dc,6186
@@ -33,7 +34,7 @@ fmu_manipulation_toolbox/resources/icon_fmu.png,sha256=EuygB2xcoM2WAfKKdyKG_UvTL
33
34
  fmu_manipulation_toolbox/resources/license.txt,sha256=5ODuU8g8pIkK-NMWXu_rjZ6k7gM7b-N2rmg87-2Kmqw,1583
34
35
  fmu_manipulation_toolbox/resources/mask.png,sha256=px1U4hQGL0AmZ4BQPknOVREpMpTSejbah3ntkpqAzFA,3008
35
36
  fmu_manipulation_toolbox/resources/model.png,sha256=EAf_HnZJe8zYGZygerG1MMt2U-tMMZlifzXPj4_iORA,208788
36
- fmu_manipulation_toolbox/resources/darwin64/container.dylib,sha256=EpQwj07DRShKXq8lzqjFXiAWLwJXQyRPa3TrLjULZCM,230608
37
+ fmu_manipulation_toolbox/resources/darwin64/container.dylib,sha256=fqp6EDPyPUUhFDC4KDCo00ErfyyoSmoiz5ABDSifL-U,230624
37
38
  fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd,sha256=OGfyJtaJntKypX5KDpuZ-nV1oYLZ6HV16pkpKOmYox4,2731
38
39
  fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd,sha256=HwyV7LBse-PQSv4z1xjmtzPU3Hjnv4mluq9YdSBNHMQ,3704
39
40
  fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd,sha256=JM4j_9q-pc40XYHb28jfT3iV3aYM5JLqD5aRjO72K1E,18939
@@ -53,19 +54,19 @@ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd,sha256=TaHRoUBIFtmdEwBKB
53
54
  fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd,sha256=CK_F2t5LfyQ6eSNJ8soTFMVK9DU8vD2WiMi2MQvjB0g,3746
54
55
  fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd,sha256=3YU-3q1-c-namz7sMe5cxnmOVOJsRSmfWR02PKv3xaU,19171
55
56
  fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd,sha256=YQSBwXt4IsDlyegY8bX-qQHGSfE5TipTPfo2g2yqq1c,3082
56
- fmu_manipulation_toolbox/resources/linux32/client_sm.so,sha256=Cd4EwnFamF-6cmA0uNJ-xDIs5wkmhfgdeFVAJLBzumY,34756
57
+ fmu_manipulation_toolbox/resources/linux32/client_sm.so,sha256=Ty7ZerSlOQweg51EVxCLLKnli2EalqmXf05Mnh_JLtU,34664
57
58
  fmu_manipulation_toolbox/resources/linux32/server_sm,sha256=gzKU0BTeaRkvhTMQtHHj3K8uYFyEdyGGn_mZy_jG9xo,21304
58
- fmu_manipulation_toolbox/resources/linux64/client_sm.so,sha256=4aaTSTwCFk0iigVqw67ZMmt9Udj89W6placdTydzcAo,32592
59
- fmu_manipulation_toolbox/resources/linux64/container.so,sha256=8SEqRP87xhzmkgIlFbgXyyxcSml4Gl_MKmfH7nHEjd8,189944
59
+ fmu_manipulation_toolbox/resources/linux64/client_sm.so,sha256=PrKEimiEXw6jMZlvtIHeYaSrQgLhWq-9XqCXxD96zkE,32464
60
+ fmu_manipulation_toolbox/resources/linux64/container.so,sha256=QSyFbCqfByxXPIF-u60rFKZ1BtDzG26QHHN_GWPgxgg,189912
60
61
  fmu_manipulation_toolbox/resources/linux64/server_sm,sha256=MZn6vITN2qpBHYt_RaK2VnFFp00hk8fTALBHmXPtLwc,22608
61
- fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=WPAutfVhZ3wMOwM2nuJYaOQby-Nooz6dwX_Jv14zUgI,17920
62
- fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=b6a25dyuw5E06sJwRWNTHwB8ZHwjTxybOE0H9wCHYac,15360
63
- fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=FDxyTCrsryoSHLKhEIBRbNYDzQfUxYW1B2ICKeskfZo,21504
64
- fmu_manipulation_toolbox/resources/win64/container.dll,sha256=uV6DVwERwLDcsAl2jzgQhNLte5xjGfaUMCu2gwMIC8s,153088
65
- fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=TCF38KOmVIltgBxw84fa22Zx8ZcJ_lHtAVVZzUm6Ncc,18432
66
- fmu_manipulation_toolbox-1.9.2b2.dist-info/licenses/LICENSE.txt,sha256=0Q8zhEwTu1K-MDmg8Khay5j56BIz2VLI6RcijIFbU_g,1255
67
- fmu_manipulation_toolbox-1.9.2b2.dist-info/METADATA,sha256=uHdjOJ_iuBOy-KDuoM-bM2rZu7XrVjzD_HQYeFLE-lI,1898
68
- fmu_manipulation_toolbox-1.9.2b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
69
- fmu_manipulation_toolbox-1.9.2b2.dist-info/entry_points.txt,sha256=6VNL31b5le8S9zp2H0R9ERWmzCy9WuSzVEDcHbWX_70,268
70
- fmu_manipulation_toolbox-1.9.2b2.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
71
- fmu_manipulation_toolbox-1.9.2b2.dist-info/RECORD,,
62
+ fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=35hvSqIQVDIYk6fbqN_90Lg6rwJqk3SD0mwxyXBVi7U,17920
63
+ fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=T7Juqe7mbig8TVVdIOXX6PejTL7o60V8-QAfgm4lA1I,15360
64
+ fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=mEgQ-U3OSGXuD4D-obf14RfRDAVEU3x5Q1d1FCuVIkE,20992
65
+ fmu_manipulation_toolbox/resources/win64/container.dll,sha256=nxdh21lnohIhyNxDsDb6-vJ0yWagX0mDDNnfEXpioXc,152064
66
+ fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=i1LesWTMSZcJX66RZ5qh2YkDCfnwuKj7i2VFQIql2Fo,18432
67
+ fmu_manipulation_toolbox-1.9.2b3.dist-info/licenses/LICENSE.txt,sha256=0Q8zhEwTu1K-MDmg8Khay5j56BIz2VLI6RcijIFbU_g,1255
68
+ fmu_manipulation_toolbox-1.9.2b3.dist-info/METADATA,sha256=Z0MV66dhTl6JHi4Xv6UdM8NuJ2csCCiNGnMv_dUlciU,1899
69
+ fmu_manipulation_toolbox-1.9.2b3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
+ fmu_manipulation_toolbox-1.9.2b3.dist-info/entry_points.txt,sha256=VOWf1jbG1O-2JrqXOvSoHRRfdH3RNONvz-2RIPHNX0s,338
71
+ fmu_manipulation_toolbox-1.9.2b3.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
72
+ fmu_manipulation_toolbox-1.9.2b3.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  [console_scripts]
2
+ datalog2pcap = fmu_manipulation_toolbox.cli.datalog2pcap:datalog2pcap
2
3
  fmucontainer = fmu_manipulation_toolbox.cli.fmucontainer:fmucontainer
3
4
  fmusplit = fmu_manipulation_toolbox.cli.fmusplit:fmusplit
4
5
  fmutool = fmu_manipulation_toolbox.cli.fmutool:fmutool