fmu-manipulation-toolbox 1.9.2b2__tar.gz → 1.9.2b4__tar.gz
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.
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/PKG-INFO +2 -2
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/__version__.py +1 -0
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/cli/datalog2pcap.py +143 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/container.py +9 -4
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/operations.py +2 -2
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
- fmu_manipulation_toolbox-1.9.2b4/fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox.egg-info/PKG-INFO +2 -2
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox.egg-info/SOURCES.txt +1 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox.egg-info/entry_points.txt +1 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/setup.py +3 -2
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/tests/test_suite.py +44 -15
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/__version__.py +0 -1
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
- fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/README.md +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/__init__.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/__main__.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/assembly.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/checker.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/cli/__init__.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/cli/fmucontainer.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/cli/fmusplit.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/cli/fmutool.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/cli/utils.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/help.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/ls.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/remoting.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/checkbox-checked-hover.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/checkbox-checked.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/checkbox-unchecked-disabled.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/checkbox-unchecked-hover.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/checkbox-unchecked.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/container.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/drop_fmu.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmu.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/help.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/icon-round.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/icon.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/icon_fmu.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/license.txt +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/linux32/server_sm +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/linux64/server_sm +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/mask.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/resources/model.png +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/split.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/terminals.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/version.py +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox.egg-info/dependency_links.txt +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox.egg-info/requires.txt +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox.egg-info/top_level.txt +0 -0
- {fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmu_manipulation_toolbox
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2b4
|
|
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)](
|
|
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:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'V1.9.2b4'
|
|
@@ -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()
|
|
@@ -95,6 +95,7 @@ class EmbeddedFMUPort:
|
|
|
95
95
|
self.start_value = attrs.get("start", None)
|
|
96
96
|
self.initial = attrs.get("initial", None)
|
|
97
97
|
self.clock = attrs.get("clocks", None)
|
|
98
|
+
self.interval_variability = attrs.get("intervalVariability", None)
|
|
98
99
|
|
|
99
100
|
|
|
100
101
|
def xml(self, vr: int, name=None, causality=None, start=None, fmi_version=2) -> str:
|
|
@@ -1106,8 +1107,8 @@ class FMUContainer:
|
|
|
1106
1107
|
else:
|
|
1107
1108
|
local_per_type["clock"].append(link.vr)
|
|
1108
1109
|
for cport_to in link.cport_to_list:
|
|
1109
|
-
if cport_to.
|
|
1110
|
-
logger.info(f"LS-BUS: importer scheduling for '{cport_to.fmu.name}' '{cport_to.port.name}' (clock={cport_to.port.vr}, {link.vr})")
|
|
1110
|
+
if cport_to.port.interval_variability == "countdown":
|
|
1111
|
+
logger.info(f"LS-BUS: importer scheduling for '{cport_to.fmu.name}' '{cport_to.port.name}' (clock={cport_to.port.vr}, vr={link.vr})")
|
|
1111
1112
|
clock_list.append(cport_to, link.vr)
|
|
1112
1113
|
break
|
|
1113
1114
|
|
|
@@ -1179,7 +1180,7 @@ class FMUContainer:
|
|
|
1179
1180
|
clock_list.write_txt(txt_file)
|
|
1180
1181
|
|
|
1181
1182
|
def make_datalog(self, datalog_file):
|
|
1182
|
-
print(f"# Datalog filename")
|
|
1183
|
+
print(f"# Datalog filename", file=datalog_file)
|
|
1183
1184
|
print(f"{self.identifier}-datalog.csv", file=datalog_file)
|
|
1184
1185
|
|
|
1185
1186
|
ports = defaultdict(list)
|
|
@@ -1188,7 +1189,11 @@ class FMUContainer:
|
|
|
1188
1189
|
for output_port_name, output_port in self.outputs.items():
|
|
1189
1190
|
ports[output_port.port.type_name].append((output_port.vr, output_port_name))
|
|
1190
1191
|
for link in self.links.values():
|
|
1191
|
-
|
|
1192
|
+
if link.cport_from is None:
|
|
1193
|
+
# LS-BUS allows to connected to input clocks.
|
|
1194
|
+
ports[link.cport_to_list[0].port.type_name].append((link.vr, link.name))
|
|
1195
|
+
else:
|
|
1196
|
+
ports[link.cport_from.port.type_name].append((link.vr, link.name))
|
|
1192
1197
|
|
|
1193
1198
|
for type_name in EmbeddedFMUPort.ALL_TYPES:
|
|
1194
1199
|
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
|
|
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:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmu_manipulation_toolbox
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2b4
|
|
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)](
|
|
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:
|
|
@@ -22,6 +22,7 @@ fmu_manipulation_toolbox.egg-info/entry_points.txt
|
|
|
22
22
|
fmu_manipulation_toolbox.egg-info/requires.txt
|
|
23
23
|
fmu_manipulation_toolbox.egg-info/top_level.txt
|
|
24
24
|
fmu_manipulation_toolbox/cli/__init__.py
|
|
25
|
+
fmu_manipulation_toolbox/cli/datalog2pcap.py
|
|
25
26
|
fmu_manipulation_toolbox/cli/fmucontainer.py
|
|
26
27
|
fmu_manipulation_toolbox/cli/fmusplit.py
|
|
27
28
|
fmu_manipulation_toolbox/cli/fmutool.py
|
|
@@ -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
|
|
@@ -44,7 +44,8 @@ setup(
|
|
|
44
44
|
]},
|
|
45
45
|
entry_points={"console_scripts": ["fmutool = fmu_manipulation_toolbox.cli.fmutool:fmutool",
|
|
46
46
|
"fmucontainer = fmu_manipulation_toolbox.cli.fmucontainer:fmucontainer",
|
|
47
|
-
"fmusplit = fmu_manipulation_toolbox.cli.fmusplit:fmusplit"
|
|
47
|
+
"fmusplit = fmu_manipulation_toolbox.cli.fmusplit:fmusplit",
|
|
48
|
+
"datalog2pcap = fmu_manipulation_toolbox.cli.datalog2pcap:datalog2pcap",
|
|
48
49
|
],
|
|
49
50
|
"gui_scripts": ["fmutool-gui = fmu_manipulation_toolbox.gui.gui:main"]
|
|
50
51
|
},
|
|
@@ -53,7 +54,7 @@ setup(
|
|
|
53
54
|
description="FMU Manipulation Toolbox is a python package which helps to analyze, modify or combine "
|
|
54
55
|
"Functional Mock-up Units (FMUs) without recompilation.",
|
|
55
56
|
long_description="""FMU Manipulation Toolbox is a python package which helps to analyze, modify or combine
|
|
56
|
-
[Functional Mock-up Units (FMUs)](
|
|
57
|
+
[Functional Mock-up Units (FMUs)](https://fmi-standard.org/) without recompilation. It is highly customizable and comes with
|
|
57
58
|
a Python API.
|
|
58
59
|
|
|
59
60
|
FMU Manipulation Toolbox can be used in different ways:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import hashlib
|
|
1
2
|
import numpy as np
|
|
2
3
|
import pytest
|
|
3
4
|
import sys
|
|
@@ -14,6 +15,7 @@ from fmu_manipulation_toolbox.assembly import *
|
|
|
14
15
|
from fmu_manipulation_toolbox.cli.fmusplit import fmusplit
|
|
15
16
|
from fmu_manipulation_toolbox.cli.fmucontainer import fmucontainer
|
|
16
17
|
from fmu_manipulation_toolbox.cli.fmutool import fmutool
|
|
18
|
+
from fmu_manipulation_toolbox.cli.datalog2pcap import datalog2pcap
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class TestSuite:
|
|
@@ -49,17 +51,23 @@ class TestSuite:
|
|
|
49
51
|
with open(log_filename, mode="rt", newline=None) as a, open(ref_filename, mode="rt", newline=None) as b:
|
|
50
52
|
for i, (lineA, lineB) in enumerate(zip(a, b)):
|
|
51
53
|
if i > 10:
|
|
52
|
-
assert
|
|
54
|
+
assert lineA == lineB, \
|
|
55
|
+
f"files {log_filename} and {ref_filename} missmatch (excl. GUID):\n" \
|
|
56
|
+
f"{lineA}\n" \
|
|
57
|
+
f"vs.\n\n" \
|
|
58
|
+
f"{lineB}"
|
|
53
59
|
|
|
54
60
|
@staticmethod
|
|
55
61
|
def assert_identical_files(filename1, filename2):
|
|
62
|
+
assert Path(filename1).exists(), f"{filename1} does not exist"
|
|
63
|
+
assert Path(filename2).exists(), f"{filename2} does not exist"
|
|
56
64
|
with open(filename1, mode="rt", newline=None) as a, open(filename2, mode="rt", newline=None) as b:
|
|
57
65
|
for lineA, lineB in zip(a, b):
|
|
58
|
-
assert
|
|
59
|
-
f"file {filename1} and {filename2} missmatch (excl. GUID):\n"
|
|
60
|
-
f"{lineA}\n"
|
|
61
|
-
f"vs.\n\n"
|
|
62
|
-
f"{lineB}"
|
|
66
|
+
assert lineA == lineB, \
|
|
67
|
+
f"file {filename1} and {filename2} missmatch (excl. GUID):\n" \
|
|
68
|
+
f"{lineA}\n" \
|
|
69
|
+
f"vs.\n\n" \
|
|
70
|
+
f"{lineB}"
|
|
63
71
|
|
|
64
72
|
@staticmethod
|
|
65
73
|
def assert_identical_files_but_guid(filename1, filename2):
|
|
@@ -71,11 +79,11 @@ class TestSuite:
|
|
|
71
79
|
if keyword in lineA:
|
|
72
80
|
skip = True
|
|
73
81
|
break
|
|
74
|
-
assert
|
|
75
|
-
f"file {filename1} and {filename2} missmatch:\n"
|
|
76
|
-
f"{lineA}\n"
|
|
77
|
-
f"vs.\n\n"
|
|
78
|
-
f"{lineB}"
|
|
82
|
+
assert skip or lineA == lineB, \
|
|
83
|
+
f"file {filename1} and {filename2} missmatch:\n" \
|
|
84
|
+
f"{lineA}\n" \
|
|
85
|
+
f"vs.\n\n" \
|
|
86
|
+
f"{lineB}"
|
|
79
87
|
|
|
80
88
|
def assert_names_match_ref(self, fmu_filename):
|
|
81
89
|
fmu = FMU(fmu_filename)
|
|
@@ -91,9 +99,19 @@ class TestSuite:
|
|
|
91
99
|
fmu.repack(fmu_filename)
|
|
92
100
|
self.assert_names_match_ref(fmu_filename)
|
|
93
101
|
|
|
102
|
+
@staticmethod
|
|
103
|
+
def assert_md5(filename, expected_md5):
|
|
104
|
+
hash_md5 = hashlib.md5()
|
|
105
|
+
with open(filename, "rb") as f:
|
|
106
|
+
for chunk in iter(lambda: f.read(4096), b""):
|
|
107
|
+
hash_md5.update(chunk)
|
|
108
|
+
print(f"{filename}: {expected_md5} {hash_md5.hexdigest()}")
|
|
109
|
+
assert hash_md5.hexdigest() == expected_md5 ,\
|
|
110
|
+
f"Wrong md5 hash for {filename}. Expected {expected_md5} but got {hash_md5.hexdigest()}"
|
|
111
|
+
|
|
94
112
|
@staticmethod
|
|
95
113
|
def assert_file_exist(path):
|
|
96
|
-
assert
|
|
114
|
+
assert Path(path).exists()
|
|
97
115
|
|
|
98
116
|
def test_strip_top_level(self):
|
|
99
117
|
self.assert_operation_match_ref("operations/bouncing_ball-no-tl.fmu", OperationStripTopLevel())
|
|
@@ -295,16 +313,21 @@ class TestSuite:
|
|
|
295
313
|
sys.argv = ['fmusplit',
|
|
296
314
|
"-fmu", "containers/ssp/bouncing.fmu"]
|
|
297
315
|
fmusplit()
|
|
298
|
-
assert
|
|
299
|
-
assert
|
|
316
|
+
assert Path("containers/ssp/bouncing.dir/bb_position.fmu").exists()
|
|
317
|
+
assert Path("containers/ssp/bouncing.dir/bb_velocity.fmu").exists()
|
|
300
318
|
self.assert_identical_files("containers/ssp/REF-split-bouncing.json",
|
|
301
319
|
"containers/ssp/bouncing.dir/bouncing.json")
|
|
302
320
|
|
|
303
|
-
def
|
|
321
|
+
def test_ls_bus_nodes_and_bus(self):
|
|
304
322
|
assembly = Assembly("bus+nodes.json", fmu_directory=Path("ls-bus"))
|
|
305
323
|
assembly.make_fmu(fmi_version=3)
|
|
306
324
|
self.assert_simulation_log("ls-bus/bus+nodes.fmu", 0.1)
|
|
307
325
|
|
|
326
|
+
def test_ls_bus_nodes_only(self):
|
|
327
|
+
assembly = Assembly("nodes-only.json", fmu_directory=Path("ls-bus"))
|
|
328
|
+
assembly.make_fmu(fmi_version=3, datalog=True)
|
|
329
|
+
self.assert_simulation_log("ls-bus/nodes-only.fmu", 0.1)
|
|
330
|
+
|
|
308
331
|
def test_datalog(self):
|
|
309
332
|
assembly = Assembly("bouncing.csv", fmu_directory=Path("containers/bouncing_ball"), mt=True, debug=True)
|
|
310
333
|
assembly.make_fmu(filename="bouncing-datalog.fmu", datalog=True)
|
|
@@ -322,3 +345,9 @@ class TestSuite:
|
|
|
322
345
|
self.assert_simulation("containers/VanDerPol/VanDerPol-datalog.fmu", 0.1)
|
|
323
346
|
self.assert_file_exist("VanDerPol-Container-datalog.csv")
|
|
324
347
|
|
|
348
|
+
def test_datalog_pcap(self):
|
|
349
|
+
sys.argv = ['datalog2pcap',
|
|
350
|
+
'-can', 'ls-bus/REF-nodes-only-datalog.csv']
|
|
351
|
+
datalog2pcap()
|
|
352
|
+
|
|
353
|
+
self.assert_md5("ls-bus/REF-nodes-only-datalog.pcap", "ceab6b0161dbc93458bd47c057e80375")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
'V1.9.2b2'
|
fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/darwin64/container.dylib
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fmu_manipulation_toolbox-1.9.2b2 → fmu_manipulation_toolbox-1.9.2b4}/fmu_manipulation_toolbox/ls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|