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.
Files changed (58) hide show
  1. cannect/__init__.py +30 -0
  2. cannect/api/__init__.py +0 -0
  3. cannect/config.py +114 -0
  4. cannect/core/__init__.py +0 -0
  5. cannect/core/ascet/__init__.py +3 -0
  6. cannect/core/ascet/amd.py +698 -0
  7. cannect/core/ascet/formula.py +33 -0
  8. cannect/core/ascet/oid.py +29 -0
  9. cannect/core/ascet/ws.py +154 -0
  10. cannect/core/can/__init__.py +2 -0
  11. cannect/core/can/ascet/__init__.py +3 -0
  12. cannect/core/can/ascet/_db2code.py +344 -0
  13. cannect/core/can/ascet/_db2elem.py +399 -0
  14. cannect/core/can/ascet/comdef.py +256 -0
  15. cannect/core/can/ascet/comrx.py +139 -0
  16. cannect/core/can/ascet/diag.py +691 -0
  17. cannect/core/can/db/__init__.py +4 -0
  18. cannect/core/can/db/reader.py +148 -0
  19. cannect/core/can/db/schema.py +269 -0
  20. cannect/core/can/db/specification/__init__.py +0 -0
  21. cannect/core/can/db/specification/message.py +230 -0
  22. cannect/core/can/db/specification/styles.py +81 -0
  23. cannect/core/can/db/specification/wrapper.py +161 -0
  24. cannect/core/can/db/vcs.py +104 -0
  25. cannect/core/can/rule.py +229 -0
  26. cannect/core/can/testcase/__init__.py +0 -0
  27. cannect/core/can/testcase/unitcase/__init__.py +0 -0
  28. cannect/core/can/testcase/unitcase/asw2can.py +48 -0
  29. cannect/core/can/testcase/unitcase/decode.py +63 -0
  30. cannect/core/can/testcase/unitcase/diagnosis.py +479 -0
  31. cannect/core/can/testcase/unitcase/encode.py +60 -0
  32. cannect/core/ir/__init__.py +2 -0
  33. cannect/core/ir/changehistory.py +310 -0
  34. cannect/core/ir/delivereables.py +71 -0
  35. cannect/core/ir/diff.py +97 -0
  36. cannect/core/ir/ir.py +581 -0
  37. cannect/core/ir/sdd.py +148 -0
  38. cannect/core/mdf.py +66 -0
  39. cannect/core/subversion.py +136 -0
  40. cannect/core/testcase/__init__.py +3 -0
  41. cannect/core/testcase/plotter.py +181 -0
  42. cannect/core/testcase/style.py +981 -0
  43. cannect/core/testcase/testcase.py +160 -0
  44. cannect/core/testcase/unitcase.py +227 -0
  45. cannect/errors.py +20 -0
  46. cannect/schema/__init__.py +5 -0
  47. cannect/schema/candb.py +226 -0
  48. cannect/schema/datadictionary.py +60 -0
  49. cannect/utils/__init__.py +3 -0
  50. cannect/utils/excel.py +29 -0
  51. cannect/utils/logger.py +81 -0
  52. cannect/utils/ppt.py +236 -0
  53. cannect/utils/tools.py +207 -0
  54. cannect-1.0.0.dist-info/METADATA +214 -0
  55. cannect-1.0.0.dist-info/RECORD +58 -0
  56. cannect-1.0.0.dist-info/WHEEL +5 -0
  57. cannect-1.0.0.dist-info/licenses/LICENSE +21 -0
  58. cannect-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,4 @@
1
+ from .reader import CANDBReader as Reader
2
+ from .schema import SCHEMA, toJSpreadSheet, standardize
3
+ from .vcs import CANDBVcs as VCS
4
+ from .specification.wrapper import Specification
@@ -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