cannect 1.0.0__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.
- cannect/__init__.py +30 -0
- cannect/api/__init__.py +0 -0
- cannect/config.py +114 -0
- cannect/core/__init__.py +0 -0
- cannect/core/ascet/__init__.py +3 -0
- cannect/core/ascet/amd.py +698 -0
- cannect/core/ascet/formula.py +33 -0
- cannect/core/ascet/oid.py +29 -0
- cannect/core/ascet/ws.py +154 -0
- cannect/core/can/__init__.py +2 -0
- cannect/core/can/ascet/__init__.py +3 -0
- cannect/core/can/ascet/_db2code.py +344 -0
- cannect/core/can/ascet/_db2elem.py +399 -0
- cannect/core/can/ascet/comdef.py +256 -0
- cannect/core/can/ascet/comrx.py +139 -0
- cannect/core/can/ascet/diag.py +691 -0
- cannect/core/can/db/__init__.py +4 -0
- cannect/core/can/db/reader.py +148 -0
- cannect/core/can/db/schema.py +269 -0
- cannect/core/can/db/specification/__init__.py +0 -0
- cannect/core/can/db/specification/message.py +230 -0
- cannect/core/can/db/specification/styles.py +81 -0
- cannect/core/can/db/specification/wrapper.py +161 -0
- cannect/core/can/db/vcs.py +104 -0
- cannect/core/can/rule.py +229 -0
- cannect/core/can/testcase/__init__.py +0 -0
- cannect/core/can/testcase/unitcase/__init__.py +0 -0
- cannect/core/can/testcase/unitcase/asw2can.py +48 -0
- cannect/core/can/testcase/unitcase/decode.py +63 -0
- cannect/core/can/testcase/unitcase/diagnosis.py +479 -0
- cannect/core/can/testcase/unitcase/encode.py +60 -0
- cannect/core/ir/__init__.py +2 -0
- cannect/core/ir/changehistory.py +310 -0
- cannect/core/ir/delivereables.py +71 -0
- cannect/core/ir/diff.py +97 -0
- cannect/core/ir/ir.py +581 -0
- cannect/core/ir/sdd.py +148 -0
- cannect/core/mdf.py +66 -0
- cannect/core/subversion.py +136 -0
- cannect/core/testcase/__init__.py +3 -0
- cannect/core/testcase/plotter.py +181 -0
- cannect/core/testcase/style.py +981 -0
- cannect/core/testcase/testcase.py +160 -0
- cannect/core/testcase/unitcase.py +227 -0
- cannect/errors.py +20 -0
- cannect/schema/__init__.py +5 -0
- cannect/schema/candb.py +226 -0
- cannect/schema/datadictionary.py +60 -0
- cannect/utils/__init__.py +3 -0
- cannect/utils/excel.py +29 -0
- cannect/utils/logger.py +81 -0
- cannect/utils/ppt.py +236 -0
- cannect/utils/tools.py +207 -0
- cannect-1.0.0.dist-info/METADATA +214 -0
- cannect-1.0.0.dist-info/RECORD +58 -0
- cannect-1.0.0.dist-info/WHEEL +5 -0
- cannect-1.0.0.dist-info/licenses/LICENSE +21 -0
- cannect-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from cannect.core.can.db.schema import SCHEMA
|
|
2
|
+
from cannect.core.can.db.vcs import CANDBVcs
|
|
3
|
+
from cannect.schema.candb import CanSignal, CanMessage
|
|
4
|
+
from cannect.schema.datadictionary import DataDictionary
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from pandas import DataFrame
|
|
8
|
+
from typing import Dict, Union
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CANDBReader:
|
|
14
|
+
"""
|
|
15
|
+
CAN DB 데이터프레임
|
|
16
|
+
데이터프레임 R/W 및 메시지, 신호 단위 접근
|
|
17
|
+
"""
|
|
18
|
+
def __init__(self, src:Union[str, DataFrame]='', **kwargs):
|
|
19
|
+
if isinstance(src, DataFrame):
|
|
20
|
+
source = kwargs["source"] if "source" in kwargs else 'direct'
|
|
21
|
+
traceability = kwargs["traceability"] if "traceability" in kwargs else 'Untraceable'
|
|
22
|
+
__db__ = src.copy()
|
|
23
|
+
else:
|
|
24
|
+
if not str(src):
|
|
25
|
+
src = CANDBVcs().json
|
|
26
|
+
source = src
|
|
27
|
+
traceability = "_".join(os.path.basename(source).split("_")[:-1])
|
|
28
|
+
__db__ = pd.read_json(source, orient='index')
|
|
29
|
+
|
|
30
|
+
__db__ = __db__[~__db__["Message"].isna()]
|
|
31
|
+
for col, prop in SCHEMA.items():
|
|
32
|
+
if col not in __db__.columns:
|
|
33
|
+
continue
|
|
34
|
+
if not isinstance(__db__[col].dtype, prop["dtype"]):
|
|
35
|
+
if prop["dtype"] == float:
|
|
36
|
+
__db__[col] = __db__[col].apply(lambda v: 0 if not v else v)
|
|
37
|
+
try:
|
|
38
|
+
__db__[col] = __db__[col].astype(prop["dtype"])
|
|
39
|
+
except ValueError as e:
|
|
40
|
+
raise ValueError(f'Error while type casting :{col} to {prop["dtype"]}; {e}')
|
|
41
|
+
__db__.fillna("", inplace=True)
|
|
42
|
+
|
|
43
|
+
self.db = __db__
|
|
44
|
+
self.source = source
|
|
45
|
+
self.traceability = traceability
|
|
46
|
+
self.revision = traceability.split("_V")[0].split("_")[-1]
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
def __str__(self) -> str:
|
|
50
|
+
return str(self.db)
|
|
51
|
+
|
|
52
|
+
def __repr__(self):
|
|
53
|
+
return repr(self.db)
|
|
54
|
+
|
|
55
|
+
def __getitem__(self, item):
|
|
56
|
+
__get__ = self.db.__getitem__(item)
|
|
57
|
+
if isinstance(__get__, DataFrame):
|
|
58
|
+
return CANDBReader(__get__, source=self.source, traceability=self.traceability)
|
|
59
|
+
return __get__
|
|
60
|
+
|
|
61
|
+
def __len__(self) -> int:
|
|
62
|
+
return len(self.db)
|
|
63
|
+
|
|
64
|
+
def __setitem__(self, key, value):
|
|
65
|
+
self.db.__setitem__(key, value)
|
|
66
|
+
|
|
67
|
+
def __getattr__(self, item):
|
|
68
|
+
try:
|
|
69
|
+
return super().__getattribute__(item)
|
|
70
|
+
except AttributeError:
|
|
71
|
+
return self.db.__getattr__(item)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def messages(self) -> DataDictionary:
|
|
75
|
+
return DataDictionary({msg:CanMessage(df) for msg, df in self.db.groupby(by="Message")})
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def signals(self) -> Union[Dict[str, CanSignal], DataDictionary]:
|
|
79
|
+
return DataDictionary({str(sig["Signal"]):CanSignal(sig) for _, sig in self.db.iterrows()})
|
|
80
|
+
|
|
81
|
+
def mode(self, engine_spec:str):
|
|
82
|
+
return CANDBReader(self[self[f'{engine_spec} Channel'] != ""].copy(), source=self.source, traceability=self.traceability)
|
|
83
|
+
|
|
84
|
+
def is_developer_mode(self):
|
|
85
|
+
return "Channel" in self.db.columns
|
|
86
|
+
|
|
87
|
+
def to_developer_mode(self, engine_spec:str):
|
|
88
|
+
"""
|
|
89
|
+
:param engine_spec: ["ICE", "HEV"]
|
|
90
|
+
:return:
|
|
91
|
+
"""
|
|
92
|
+
channel = f'{engine_spec} Channel'
|
|
93
|
+
base = self[self[channel] != ""].copy()
|
|
94
|
+
|
|
95
|
+
# Channel P,H 메시지 구분
|
|
96
|
+
def _msg2chn(msg:str, chn:str) -> str:
|
|
97
|
+
if not msg.endswith("ms"):
|
|
98
|
+
return f"{msg}_{chn}"
|
|
99
|
+
empty = []
|
|
100
|
+
for part in msg.split("_"):
|
|
101
|
+
if part.endswith("ms"):
|
|
102
|
+
empty.append(chn)
|
|
103
|
+
empty.append(part)
|
|
104
|
+
return "_".join(empty)
|
|
105
|
+
|
|
106
|
+
base["Channel"] = base[channel]
|
|
107
|
+
base["WakeUp"] = base[f"{engine_spec} WakeUp"]
|
|
108
|
+
base["Signal"] = base[["Signal", "SignalRenamed"]].apply(
|
|
109
|
+
lambda x: x["SignalRenamed"] if x["SignalRenamed"] else x["Signal"],
|
|
110
|
+
axis=1
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
multi_channel_message = base[base[channel].str.contains(',')]['Message'].unique()
|
|
114
|
+
objs = [base]
|
|
115
|
+
for msg in multi_channel_message:
|
|
116
|
+
signals = base[base["Message"] == msg]
|
|
117
|
+
channels = []
|
|
118
|
+
for chn in signals[channel].unique():
|
|
119
|
+
if len(chn) >= len(channels):
|
|
120
|
+
channels = chn.split(",")
|
|
121
|
+
for chn in channels:
|
|
122
|
+
unique = signals[signals[channel].str.contains(chn)].copy()
|
|
123
|
+
unique["Message"] = unique["Message"].apply(lambda x: _msg2chn(x, chn))
|
|
124
|
+
unique["Signal"] = unique["Signal"] + f"_{chn}"
|
|
125
|
+
unique["SignalRenamed"] = unique["SignalRenamed"].apply(lambda x: x + f"_{chn}" if x else "")
|
|
126
|
+
unique["Channel"] = chn
|
|
127
|
+
objs.append(unique)
|
|
128
|
+
|
|
129
|
+
base = pd.concat(objs=objs, axis=0, ignore_index=True)
|
|
130
|
+
base = base[~base["Message"].isin(multi_channel_message)]
|
|
131
|
+
return CANDBReader(base, source=self.source, traceability=self.traceability)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
from pandas import set_option
|
|
136
|
+
set_option('display.expand_frame_repr', False)
|
|
137
|
+
|
|
138
|
+
db = CANDBReader()
|
|
139
|
+
# print(db)
|
|
140
|
+
print(db.source)
|
|
141
|
+
print(db.traceability)
|
|
142
|
+
print(db.revision)
|
|
143
|
+
# print(db.to_developer_mode("ICE").revision)
|
|
144
|
+
# print(db.messages['ABS_ESC_01_10ms'])
|
|
145
|
+
# print(db.columns)
|
|
146
|
+
# print(db.is_developer_mode())
|
|
147
|
+
# db2 = db.to_developer_mode("HEV")
|
|
148
|
+
# print(db2[db2["Message"].str.contains("MCU")])
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
from cannect.schema.datadictionary import DataDictionary
|
|
2
|
+
from pandas import Index
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
SCHEMA =__meta__ = DataDictionary({
|
|
6
|
+
"ECU":{
|
|
7
|
+
"synonyms": ["ecu", "controller", "sender", "tx", "송출제어기"],
|
|
8
|
+
"dtype": str,
|
|
9
|
+
"width": 100,
|
|
10
|
+
"align": "center",
|
|
11
|
+
},
|
|
12
|
+
"Message":{
|
|
13
|
+
"synonyms": ["message", "msg"],
|
|
14
|
+
"dtype": str,
|
|
15
|
+
"width": 140,
|
|
16
|
+
"align": "center",
|
|
17
|
+
},
|
|
18
|
+
"ID":{
|
|
19
|
+
"synonyms": ["id"],
|
|
20
|
+
"dtype": str,
|
|
21
|
+
"width": 60,
|
|
22
|
+
"align": "center",
|
|
23
|
+
},
|
|
24
|
+
"DLC":{
|
|
25
|
+
"synonyms": ["dlc"],
|
|
26
|
+
"dtype": int,
|
|
27
|
+
"width": 30,
|
|
28
|
+
"align": "center",
|
|
29
|
+
},
|
|
30
|
+
"Send Type":{
|
|
31
|
+
"synonyms": ["sendtype"],
|
|
32
|
+
"dtype": str,
|
|
33
|
+
"width": 30,
|
|
34
|
+
"align": "center",
|
|
35
|
+
},
|
|
36
|
+
"Cycle Time":{
|
|
37
|
+
"synonyms": ["cycletime"],
|
|
38
|
+
"dtype": int,
|
|
39
|
+
"width": 30,
|
|
40
|
+
"align": "center",
|
|
41
|
+
},
|
|
42
|
+
"Signal":{
|
|
43
|
+
"synonyms": ["signal", "sig"],
|
|
44
|
+
"dtype": str,
|
|
45
|
+
"width": 200,
|
|
46
|
+
"align": "left",
|
|
47
|
+
},
|
|
48
|
+
"Definition":{
|
|
49
|
+
"synonyms": ["definition"],
|
|
50
|
+
"dtype": str,
|
|
51
|
+
"width": 240,
|
|
52
|
+
"align": "left",
|
|
53
|
+
},
|
|
54
|
+
"Length":{
|
|
55
|
+
"synonyms": ["length", "Length\n(Bit)"],
|
|
56
|
+
"dtype": int,
|
|
57
|
+
"width": 30,
|
|
58
|
+
"align": "center",
|
|
59
|
+
},
|
|
60
|
+
"StartBit":{
|
|
61
|
+
"synonyms": ["startbit", "Startbit", "address"],
|
|
62
|
+
"dtype": int,
|
|
63
|
+
"width": 30,
|
|
64
|
+
"align": "center",
|
|
65
|
+
},
|
|
66
|
+
"Sig Receivers":{
|
|
67
|
+
"synonyms": ["Destination", "receiver"],
|
|
68
|
+
"dtype": str,
|
|
69
|
+
"width": 80,
|
|
70
|
+
"align": "left",
|
|
71
|
+
},
|
|
72
|
+
"UserSigValidity":{
|
|
73
|
+
"synonyms": [],
|
|
74
|
+
"dtype": str,
|
|
75
|
+
"width": 60,
|
|
76
|
+
"align": "center",
|
|
77
|
+
},
|
|
78
|
+
"Value Table":{
|
|
79
|
+
"synonyms": ["table"],
|
|
80
|
+
"dtype": str,
|
|
81
|
+
"width": 140,
|
|
82
|
+
"align": "left",
|
|
83
|
+
},
|
|
84
|
+
"Value Type":{
|
|
85
|
+
"synonyms": ["type"],
|
|
86
|
+
"dtype": str,
|
|
87
|
+
"width": 80,
|
|
88
|
+
"align": "center",
|
|
89
|
+
},
|
|
90
|
+
"GenSigStartValue":{
|
|
91
|
+
"synonyms": ["startvalue", "initialValue", "initial"],
|
|
92
|
+
"dtype": str,
|
|
93
|
+
"width": 80,
|
|
94
|
+
"align": "center",
|
|
95
|
+
},
|
|
96
|
+
"Factor":{
|
|
97
|
+
"synonyms": ["factor"],
|
|
98
|
+
"dtype": float,
|
|
99
|
+
"width": 60,
|
|
100
|
+
"align": "center",
|
|
101
|
+
},
|
|
102
|
+
"Offset":{
|
|
103
|
+
"synonyms": ["offset"],
|
|
104
|
+
"dtype": float,
|
|
105
|
+
"width": 60,
|
|
106
|
+
"align": "center",
|
|
107
|
+
},
|
|
108
|
+
"Min":{
|
|
109
|
+
"synonyms": ["min"],
|
|
110
|
+
"dtype": float,
|
|
111
|
+
"width": 60,
|
|
112
|
+
"align": "center",
|
|
113
|
+
},
|
|
114
|
+
"Max":{
|
|
115
|
+
"synonyms": ["max"],
|
|
116
|
+
"dtype": float,
|
|
117
|
+
"width": 60,
|
|
118
|
+
"align": "center",
|
|
119
|
+
},
|
|
120
|
+
"Unit":{
|
|
121
|
+
"synonyms": ["unit"],
|
|
122
|
+
"dtype": str,
|
|
123
|
+
"width": 60,
|
|
124
|
+
"align": "center",
|
|
125
|
+
},
|
|
126
|
+
"Local Network Wake Up Request":{
|
|
127
|
+
"synonyms": [],
|
|
128
|
+
"dtype": str,
|
|
129
|
+
"width": 40,
|
|
130
|
+
"align": "center",
|
|
131
|
+
},
|
|
132
|
+
"Network Request Holding Time":{
|
|
133
|
+
"synonyms": [],
|
|
134
|
+
"dtype": str,
|
|
135
|
+
"width": 30,
|
|
136
|
+
"align": "center",
|
|
137
|
+
},
|
|
138
|
+
"Description":{
|
|
139
|
+
"synonyms": ["description"],
|
|
140
|
+
"dtype": str,
|
|
141
|
+
"width": 100,
|
|
142
|
+
"align": "left",
|
|
143
|
+
},
|
|
144
|
+
"Version":{
|
|
145
|
+
"synonyms": ["version"],
|
|
146
|
+
"dtype": str,
|
|
147
|
+
"width": 80,
|
|
148
|
+
"align": "center",
|
|
149
|
+
},
|
|
150
|
+
"Requirement ID": {
|
|
151
|
+
"synonyms": [],
|
|
152
|
+
"dtype": str,
|
|
153
|
+
"width": 100,
|
|
154
|
+
"align": "center",
|
|
155
|
+
},
|
|
156
|
+
"Required Date": {
|
|
157
|
+
"synonyms": [],
|
|
158
|
+
"dtype": str,
|
|
159
|
+
"width": 60,
|
|
160
|
+
"align": "center",
|
|
161
|
+
},
|
|
162
|
+
"Remark": {
|
|
163
|
+
"synonyms": [],
|
|
164
|
+
"dtype": str,
|
|
165
|
+
"width": 100,
|
|
166
|
+
"align": "center",
|
|
167
|
+
},
|
|
168
|
+
"Status": {
|
|
169
|
+
"synonyms": [],
|
|
170
|
+
"dtype": str,
|
|
171
|
+
"width": 60,
|
|
172
|
+
"align": "center",
|
|
173
|
+
},
|
|
174
|
+
"ByteOrder": {
|
|
175
|
+
"synonyms": [],
|
|
176
|
+
"dtype": str,
|
|
177
|
+
"width": 80,
|
|
178
|
+
"align": "center",
|
|
179
|
+
},
|
|
180
|
+
"ICE Channel":{
|
|
181
|
+
"synonyms": [],
|
|
182
|
+
"dtype": str,
|
|
183
|
+
"width": 60,
|
|
184
|
+
"align": "center",
|
|
185
|
+
},
|
|
186
|
+
"ICE WakeUp":{
|
|
187
|
+
"synonyms": [],
|
|
188
|
+
"dtype": str,
|
|
189
|
+
"width": 60,
|
|
190
|
+
"align": "center",
|
|
191
|
+
},
|
|
192
|
+
"HEV Channel":{
|
|
193
|
+
"synonyms": [],
|
|
194
|
+
"dtype": str,
|
|
195
|
+
"width": 60,
|
|
196
|
+
"align": "center",
|
|
197
|
+
},
|
|
198
|
+
"HEV WakeUp": {
|
|
199
|
+
"synonyms": [],
|
|
200
|
+
"dtype": str,
|
|
201
|
+
"width": 60,
|
|
202
|
+
"align": "center",
|
|
203
|
+
},
|
|
204
|
+
"SystemConstant":{
|
|
205
|
+
"synonyms": [],
|
|
206
|
+
"dtype": str,
|
|
207
|
+
"width": 160,
|
|
208
|
+
"align": "center",
|
|
209
|
+
},
|
|
210
|
+
"Codeword":{
|
|
211
|
+
"synonyms": [],
|
|
212
|
+
"dtype": str,
|
|
213
|
+
"width": 160,
|
|
214
|
+
"align": "center",
|
|
215
|
+
},
|
|
216
|
+
"Formula":{
|
|
217
|
+
"synonyms": [],
|
|
218
|
+
"dtype": str,
|
|
219
|
+
"width": 140,
|
|
220
|
+
"align": "center",
|
|
221
|
+
},
|
|
222
|
+
"SignedProcessing":{
|
|
223
|
+
"synonyms": [],
|
|
224
|
+
"dtype": str,
|
|
225
|
+
"width": 100,
|
|
226
|
+
"align": "center",
|
|
227
|
+
},
|
|
228
|
+
"InterfacedVariable":{
|
|
229
|
+
"synonyms": [],
|
|
230
|
+
"dtype": str,
|
|
231
|
+
"width": 200,
|
|
232
|
+
"align": "left",
|
|
233
|
+
},
|
|
234
|
+
"SignalRenamed":{
|
|
235
|
+
"synonyms": [],
|
|
236
|
+
"dtype": str,
|
|
237
|
+
"width": 200,
|
|
238
|
+
"align": "left",
|
|
239
|
+
},
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def standardize(columns: Index) -> list:
|
|
244
|
+
standard_columns = []
|
|
245
|
+
for col in __meta__:
|
|
246
|
+
if col in columns:
|
|
247
|
+
standard_columns.append(col)
|
|
248
|
+
continue
|
|
249
|
+
for synonym in __meta__[col].synonyms:
|
|
250
|
+
if synonym in columns:
|
|
251
|
+
standard_columns.append(col)
|
|
252
|
+
if not col in standard_columns:
|
|
253
|
+
raise KeyError(f"Cannot find {col} in columns; {columns}")
|
|
254
|
+
return standard_columns
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def toJSpreadSheet(columns: Index=None) -> list:
|
|
258
|
+
if columns is None:
|
|
259
|
+
columns = list(__meta__.keys())
|
|
260
|
+
else:
|
|
261
|
+
columns = standardize(columns)
|
|
262
|
+
|
|
263
|
+
return [{
|
|
264
|
+
"type": "text",
|
|
265
|
+
"width": __meta__[col].width,
|
|
266
|
+
"title": col,
|
|
267
|
+
"align": __meta__[col].align
|
|
268
|
+
} for col in columns]
|
|
269
|
+
|
|
File without changes
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
from cannect.schema.candb import CanMessage
|
|
2
|
+
|
|
3
|
+
from docx.document import Document
|
|
4
|
+
from docx.styles.styles import Styles
|
|
5
|
+
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
|
|
6
|
+
from docx.shared import Inches, Pt, RGBColor
|
|
7
|
+
from docx.oxml import parse_xml
|
|
8
|
+
from docx.oxml.ns import nsdecls
|
|
9
|
+
from typing import List
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Message:
|
|
13
|
+
COLORS = [
|
|
14
|
+
'C4BC96',
|
|
15
|
+
'8DB3E2',
|
|
16
|
+
'B8CCE4',
|
|
17
|
+
'E5B8B7',
|
|
18
|
+
'D6E3BC',
|
|
19
|
+
'CCC0D9',
|
|
20
|
+
'FBD4B4',
|
|
21
|
+
'B6DDE8'
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
def __init__(self, doc:Document):
|
|
25
|
+
self.doc:Document = doc
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
def _coloring(self, msg:CanMessage) -> List[str]:
|
|
29
|
+
colors = ['A6A6A6'] * msg['DLC'] * 8
|
|
30
|
+
for n in range(msg['DLC'] * 8):
|
|
31
|
+
for m, sig in enumerate(msg):
|
|
32
|
+
if sig['StartBit'] <= n < (sig['StartBit'] + sig['Length']):
|
|
33
|
+
colors[n] = self.COLORS[m % len(self.COLORS)]
|
|
34
|
+
break
|
|
35
|
+
return colors
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def messageOverviewStyle(self) -> Styles:
|
|
39
|
+
if not hasattr(self, "_overview_style"):
|
|
40
|
+
style = self.doc.styles.add_style("_overview_style", WD_PARAGRAPH_ALIGNMENT.CENTER)
|
|
41
|
+
style.font.name = "현대산스 text"
|
|
42
|
+
style.font.size = Pt(11)
|
|
43
|
+
style.font.color.rgb = RGBColor(0, 0, 0)
|
|
44
|
+
style.font.bold = True
|
|
45
|
+
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
|
46
|
+
self.__setattr__("_overview_style", style)
|
|
47
|
+
return self.__getattribute__("_overview_style")
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def messageOverviewContentStyle(self) -> Styles:
|
|
51
|
+
if not hasattr(self, "_overview_content_style"):
|
|
52
|
+
style = self.doc.styles.add_style("_overview_content_style", WD_PARAGRAPH_ALIGNMENT.CENTER)
|
|
53
|
+
style.font.name = "현대산스 text"
|
|
54
|
+
style.font.size = Pt(11)
|
|
55
|
+
style.font.color.rgb = RGBColor(0, 0, 0)
|
|
56
|
+
style.font.bold = False
|
|
57
|
+
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
|
|
58
|
+
self.__setattr__("_overview_content_style", style)
|
|
59
|
+
return self.__getattribute__("_overview_content_style")
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def messageLayoutNumberStyle(self) -> Styles:
|
|
63
|
+
if not hasattr(self, "_layout_number_style"):
|
|
64
|
+
style = self.doc.styles.add_style("_layout_number_style", WD_PARAGRAPH_ALIGNMENT.CENTER)
|
|
65
|
+
style.font.name = "현대산스 text"
|
|
66
|
+
style.font.size = Pt(9)
|
|
67
|
+
style.font.color.rgb = RGBColor(0, 0, 0)
|
|
68
|
+
style.font.bold = True
|
|
69
|
+
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
|
70
|
+
self.__setattr__("_layout_number_style", style)
|
|
71
|
+
return self.__getattribute__("_layout_number_style")
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def messageLayoutStyle(self) -> Styles:
|
|
75
|
+
if not hasattr(self, "_layout_style"):
|
|
76
|
+
style = self.doc.styles.add_style("_layout_style", WD_PARAGRAPH_ALIGNMENT.CENTER)
|
|
77
|
+
style.font.name = "현대산스 text"
|
|
78
|
+
style.font.size = Pt(7)
|
|
79
|
+
style.font.color.rgb = RGBColor(0, 0, 0)
|
|
80
|
+
style.font.bold = False
|
|
81
|
+
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
|
|
82
|
+
self.__setattr__("_layout_style", style)
|
|
83
|
+
return self.__getattribute__("_layout_style")
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def signalListHeadingStyle(self) -> Styles:
|
|
87
|
+
if not hasattr(self, "_signal_style"):
|
|
88
|
+
style = self.doc.styles.add_style("_signal_style", WD_PARAGRAPH_ALIGNMENT.CENTER)
|
|
89
|
+
style.font.name = "현대산스 text"
|
|
90
|
+
style.font.size = Pt(10)
|
|
91
|
+
style.font.color.rgb = RGBColor(0, 0, 0)
|
|
92
|
+
style.font.bold = True
|
|
93
|
+
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
|
94
|
+
self.__setattr__("_signal_style", style)
|
|
95
|
+
return self.__getattribute__("_signal_style")
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def signalListStyle(self) -> Styles:
|
|
99
|
+
if not hasattr(self, "_signal_content_style"):
|
|
100
|
+
style = self.doc.styles.add_style("_signal_content_style", WD_PARAGRAPH_ALIGNMENT.CENTER)
|
|
101
|
+
style.font.name = "현대산스 text"
|
|
102
|
+
style.font.size = Pt(10)
|
|
103
|
+
style.font.color.rgb = RGBColor(0, 0, 0)
|
|
104
|
+
style.font.bold = False
|
|
105
|
+
style.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
|
106
|
+
self.__setattr__("_signal_content_style", style)
|
|
107
|
+
return self.__getattribute__("_signal_content_style")
|
|
108
|
+
|
|
109
|
+
def addHeading(
|
|
110
|
+
self,
|
|
111
|
+
text:str,
|
|
112
|
+
level:int=1,
|
|
113
|
+
fontSize:int=20,
|
|
114
|
+
bold:bool=True,
|
|
115
|
+
alignCenter:bool=True
|
|
116
|
+
):
|
|
117
|
+
heading = self.doc.add_heading(text, level=level)
|
|
118
|
+
if alignCenter:
|
|
119
|
+
heading.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
|
120
|
+
runner = heading.runs[0]
|
|
121
|
+
runner.font.name = "현대산스 Text"
|
|
122
|
+
runner.font.size = Pt(fontSize)
|
|
123
|
+
runner.font.bold = bold
|
|
124
|
+
runner.font.color.rgb = RGBColor(0, 0, 0)
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
def addMessageHeading(self, msg:CanMessage):
|
|
128
|
+
self.addHeading(f"{msg['ID']}: {msg.name}", level=2, fontSize=14, alignCenter=False)
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
def addMessageSpec(self, msg:CanMessage):
|
|
132
|
+
specs = {
|
|
133
|
+
"ECU": "SENDER",
|
|
134
|
+
"ID": "ID",
|
|
135
|
+
"Message": "MESSAGE",
|
|
136
|
+
"DLC": "DLC",
|
|
137
|
+
"Send Type": "SEND TYPE",
|
|
138
|
+
"Cycle Time": "CYCLE TIME [ms]",
|
|
139
|
+
"ByteOrder": "BYTE ORDER",
|
|
140
|
+
"SystemConstant": "SYSCON",
|
|
141
|
+
"Codeword": "CODEWORD"
|
|
142
|
+
}
|
|
143
|
+
self.addHeading("Message Overview", level=3, fontSize=12, bold=True, alignCenter=False)
|
|
144
|
+
table = self.doc.add_table(rows=len(specs), cols=2)
|
|
145
|
+
table.style = 'Table Grid'
|
|
146
|
+
for n, (key, value) in enumerate(specs.items()):
|
|
147
|
+
left = table.rows[n].cells[0]
|
|
148
|
+
left.width = Inches(2.0)
|
|
149
|
+
name = left.paragraphs[0]
|
|
150
|
+
name.text = value
|
|
151
|
+
name.style = self.messageOverviewStyle
|
|
152
|
+
|
|
153
|
+
right = table.rows[n].cells[1]
|
|
154
|
+
right.width = self.doc.sections[0].page_width
|
|
155
|
+
text = right.paragraphs[0]
|
|
156
|
+
text.text = str(msg[key])
|
|
157
|
+
text.style = self.messageOverviewContentStyle
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
def addMessageLayout(self, msg:CanMessage):
|
|
161
|
+
self.addHeading("Message Layout", level=3, fontSize=12, bold=True, alignCenter=False)
|
|
162
|
+
color = self._coloring(msg)
|
|
163
|
+
table = self.doc.add_table(rows=msg['DLC'] * 2, cols=8)
|
|
164
|
+
for n, row in enumerate(table.rows):
|
|
165
|
+
byte = int(n / 2)
|
|
166
|
+
for m, cell in enumerate(row.cells):
|
|
167
|
+
bit = 8 * byte + 7 - m
|
|
168
|
+
sig = msg.signals[msg.signals["StartBit"] == int(bit)]
|
|
169
|
+
sig = '' if sig.empty else sig.iloc[0]["Signal"]
|
|
170
|
+
|
|
171
|
+
text = cell.paragraphs[0]
|
|
172
|
+
text.text = str(bit) if not n % 2 else sig
|
|
173
|
+
text.style = self.messageLayoutNumberStyle if not n % 2 else self.messageLayoutStyle
|
|
174
|
+
cell._tc.get_or_add_tcPr().append(
|
|
175
|
+
parse_xml(r'<w:shd {} w:fill="{}"/>'.format(nsdecls('w'), color[bit]))
|
|
176
|
+
)
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
def addSignalList(self, msg:CanMessage):
|
|
180
|
+
specs = {
|
|
181
|
+
"Signal": "Signal",
|
|
182
|
+
"InterfacedVariable": "@EMS",
|
|
183
|
+
"Length": "Len.",
|
|
184
|
+
"StartBit": "Addr.",
|
|
185
|
+
"Value Type": "Type",
|
|
186
|
+
"Factor": "Factor",
|
|
187
|
+
"Offset": "Offset",
|
|
188
|
+
"Unit": "Unit"
|
|
189
|
+
}
|
|
190
|
+
self.addHeading("Signal List", level=3, fontSize=12, bold=True, alignCenter=False)
|
|
191
|
+
table = self.doc.add_table(rows=len(msg.signals) + 1, cols=8)
|
|
192
|
+
table.style = "Table Grid"
|
|
193
|
+
for n, row in enumerate(table.rows):
|
|
194
|
+
for m, key in enumerate(specs.keys()):
|
|
195
|
+
if not n:
|
|
196
|
+
text = row.cells[m].paragraphs[0]
|
|
197
|
+
text.text = specs[key]
|
|
198
|
+
text.style = self.signalListHeadingStyle
|
|
199
|
+
else:
|
|
200
|
+
text = row.cells[m].paragraphs[0]
|
|
201
|
+
text.text = str(msg.signals.iloc[n - 1][key]).replace('"', '')
|
|
202
|
+
text.style = self.signalListStyle
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
def addSignalProperty(self, msg:CanMessage):
|
|
206
|
+
specs = {
|
|
207
|
+
"Signal": "Signal",
|
|
208
|
+
"Definition": "Definition",
|
|
209
|
+
"Value Table": "Value Table"
|
|
210
|
+
}
|
|
211
|
+
self.addHeading("Signal Property", level=3, fontSize=12, bold=True, alignCenter=False)
|
|
212
|
+
|
|
213
|
+
for sig in msg:
|
|
214
|
+
table = self.doc.add_table(rows=3, cols=2)
|
|
215
|
+
table.style = 'Table Grid'
|
|
216
|
+
for n, (key, value) in enumerate(specs.items()):
|
|
217
|
+
left = table.rows[n].cells[0]
|
|
218
|
+
left.width = Inches(2.0)
|
|
219
|
+
name = left.paragraphs[0]
|
|
220
|
+
name.text = value
|
|
221
|
+
name.style = self.messageOverviewStyle
|
|
222
|
+
|
|
223
|
+
right = table.rows[n].cells[1]
|
|
224
|
+
right.width = self.doc.sections[0].page_width
|
|
225
|
+
text = right.paragraphs[0]
|
|
226
|
+
text.text = sig[key].replace("/0x", "\n0x") if key == "Value Table" else sig[key]
|
|
227
|
+
text.style = self.messageOverviewContentStyle
|
|
228
|
+
self.doc.add_paragraph()
|
|
229
|
+
self.doc.add_paragraph("\n")
|
|
230
|
+
return
|