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,33 @@
1
+ from cannect.schema.datadictionary import DataDictionary
2
+ from xml.etree.ElementTree import ElementTree
3
+
4
+
5
+ def formula_dictionary(filepath:str) -> DataDictionary:
6
+ tree = ElementTree(file=filepath)
7
+ data = DataDictionary()
8
+ for tag in tree.iter('Formula'):
9
+ if tag.get('type') != '5 Parameters':
10
+ continue
11
+ obj = DataDictionary()
12
+ obj.unit = tag.get('unit')
13
+ for n, param in enumerate(tag.iter('Parameter'), start=1):
14
+ obj[f'p{n}'] = param.get('value')
15
+
16
+ p1, p2, p3, p4, p5 = float(obj.p1), float(obj.p2), float(obj.p3), float(obj.p4), float(obj.p5)
17
+ if p3 != 0:
18
+ obj.quantization = p2 / p3
19
+ obj.offset = -p4 / p3
20
+ elif p1 != 0:
21
+ obj.quantization = abs(p4 / p1)
22
+ obj.offset = (-p4 * p5 - p2) / p1
23
+ else:
24
+ KeyError(f'Unknown Case For {tag.get("name")}')
25
+ data[tag.get('name')] = obj
26
+ return data
27
+
28
+
29
+ if __name__ == "__main__":
30
+ file = r"D:\ETASData\ASCET6.1\Export\_Formula\HNB_I4GDI_EU7.xml"
31
+ formula = formula_dictionary(file)
32
+ print(formula)
33
+ print(formula.k_q0p000244)
@@ -0,0 +1,29 @@
1
+ from random import choice, choices, shuffle
2
+ from time import time
3
+ from typing import List, Union
4
+ import string
5
+
6
+
7
+ def generateOID(count:int=1) -> Union[str, List[str]]:
8
+ syntax1 = [
9
+ '1ngg01pp', '1ngg00p9', '03000000', '1ngg01a0', '1ngg0140',
10
+ '000g00p9', '04136psg', '00000300', '038g01ah', '000g0136',
11
+ '1ngg013h', '1ngg019n', '1ngg01ah', '000g019n'
12
+ ]
13
+ syntax2 = ['1og7', '1mo7', '1o07', '1ng7', '1o87', '1no7', '1n87', '1n07', '1mg7']
14
+
15
+ oids = []
16
+ for n in range(count):
17
+ charset = string.ascii_lowercase + string.digits # 'abcdefghijklmnopqrstuvwxyz0123456789'
18
+ timestamp = str(int(time() * 1000000))
19
+ randomkey = list(timestamp[-8:]) + choices(charset, k=5)
20
+ shuffle(randomkey)
21
+ oids.append(f'_040g{choice(syntax1)}{choice(syntax2)}{"".join(randomkey)}')
22
+ if len(oids) == 1:
23
+ return oids[0]
24
+ return oids
25
+
26
+
27
+ if __name__ == "__main__":
28
+ for oid in generateOID(100):
29
+ print(oid)
@@ -0,0 +1,154 @@
1
+ from cannect.core.ascet import AmdIO, AmdSC
2
+ from cannect.core.subversion import Subversion
3
+ from cannect.config import env
4
+ from cannect.errors import AscetWorspaceFormatError, AmdDuplicationError, AmdNotFoundError
5
+ from pandas import DataFrame, concat
6
+ from pathlib import Path
7
+ from typing import Union
8
+ import os
9
+
10
+
11
+ class WorkspaceIO:
12
+
13
+ def __init__(self, path:str=""):
14
+ self.path = path = env.SVN_MODEL if not path else Path(path)
15
+
16
+ listdir = os.listdir(path)
17
+ if not "HNB_GASOLINE" in listdir:
18
+ raise AscetWorspaceFormatError('NO {HNB_GASOLINE} IN WORKSPACE DIRECTORY')
19
+ if not "HMC_ECU_Library" in listdir:
20
+ raise AscetWorspaceFormatError('NO {HMC_ECU_Library} IN WORKSPACE DIRECTORY')
21
+
22
+ fdb = ''
23
+ if '.svn' in listdir:
24
+ fdb = Path(path) / '.svn/wc.db'
25
+ for f in listdir:
26
+ if f.endswith('.aws'):
27
+ fdb = Path(path) / f
28
+
29
+ if not fdb:
30
+ raise AscetWorspaceFormatError('NO .aws OR wc.db IN WORKSPACE DIRECTORY')
31
+
32
+ if str(fdb).endswith('.db'):
33
+ db = Subversion.read_wcdb(fdb)
34
+ db = db[~db["local_relpath"].str.startswith("Personal")]
35
+ self.dbtype = 'wc'
36
+ else:
37
+ self.dbtype = 'ws'
38
+ # TODO
39
+ # .aws 파일 파싱
40
+ pass
41
+ self.db = db
42
+ return
43
+
44
+ def __getitem__(self, item):
45
+ return self.find(item)
46
+
47
+ def find(self, name:str) -> str:
48
+ # TODO
49
+ # .asw CASE 생성
50
+ if self.dbtype == 'ws':
51
+ pass
52
+ else:
53
+ if not name.endswith('.zip'):
54
+ name += '.zip'
55
+ query = self.db[self.db['kind'] == 'file'].copy()
56
+ query = query[query['local_relpath'].str.endswith(name)]
57
+ if query.empty:
58
+ raise AmdNotFoundError(f'MODULE {name} NOT FOUND')
59
+ if len(query) > 1:
60
+ raise AmdDuplicationError(rf'{query}\nMODULE {name} DUPLICATED: SPECIFY PARENT FOLDER')
61
+ return str(self.path / query.iloc[0]['local_relpath'])
62
+
63
+ @property
64
+ def HNB_GASOLINE(self) -> Path:
65
+ return self.path / 'HNB_GASOLINE'
66
+
67
+ @property
68
+ def HMC_ECU_Library(self) -> Path:
69
+ return self.path / 'HMC_ECU_Library'
70
+
71
+ def bcPath(self, n:Union[str, int]) -> str:
72
+ target = [path for path in os.listdir(self.HNB_GASOLINE) if str(n) in path]
73
+ if not target:
74
+ raise FileNotFoundError(f'#{n} BC Not Exist')
75
+ return str(self.HNB_GASOLINE / target[0])
76
+
77
+ def bcTree(self, n:Union[str, int]) -> DataFrame:
78
+ r"""
79
+ :param n:
80
+ :return:
81
+
82
+ 출력 예시)
83
+ bc file layer1 layer2 layer3 path
84
+ 0 _33_EnginePositionManagement CamPosA.zip CamPosition EdgeAdapt CamPosA D:\SVN\model\ascet\trunk\HNB_GASOLINE\_33_Engi...
85
+ 1 _33_EnginePositionManagement CamOfsD.zip CamPosition OffsetDiagnosis CamOfsD D:\SVN\model\ascet\trunk\HNB_GASOLINE\_33_Engi...
86
+ 2 _33_EnginePositionManagement CamSeg.zip CamPosition SegmentTime CamSeg D:\SVN\model\ascet\trunk\HNB_GASOLINE\_33_Engi...
87
+ ... ... ... ... ...
88
+ 29 _33_EnginePositionManagement EpmSv.zip ServiceLibrary EpmSvLib NaN D:\SVN\model\ascet\trunk\HNB_GASOLINE\_33_Engi...
89
+ 30 _33_EnginePositionManagement CamSync.zip Syncronization CamPhaseSync CamSyn D:\SVN\model\ascet\trunk\HNB_GASOLINE\_33_Engi...
90
+ 31 _33_EnginePositionManagement CrkSyn.zip Syncronization CrankPositionSync CrkSyn D:\SVN\model\ascet\trunk\HNB_GASOLINE\_33_Engi...
91
+ """
92
+ path = self.bcPath(n)
93
+ data = []
94
+ for root, paths, files in os.walk(path):
95
+ for file in files:
96
+ data.append({
97
+ 'bc': os.path.basename(path),
98
+ 'file': file,
99
+ 'path': os.path.join(root, file),
100
+ })
101
+ layers = [l for l in root.replace(path, "").split('/' if '/' in root else '\\') if l]
102
+ for n, layer in enumerate(layers):
103
+ data[-1].update({f'layer{n+1}': layer})
104
+ tree = DataFrame(data)
105
+ cols = [col for col in tree if not col == 'path'] + ['path']
106
+ return tree[cols]
107
+
108
+ def bcEL(self, n:Union[str, int]) -> DataFrame:
109
+ objs = []
110
+ tree = self.bcTree(n)
111
+ for i, row in tree.iterrows():
112
+ path = row['path']
113
+ amdsc = AmdSC(path)
114
+ amdio = AmdIO(amdsc.main)
115
+ frame = amdio.dataframe('Element')
116
+ # frame['bc'] = row['bc']
117
+
118
+ objs.append(frame)
119
+ data = concat(objs=objs, axis=0)
120
+
121
+ unique = data[data['scope'] == 'exported']
122
+ oids = dict(zip(unique['name'].values, unique['OID'].values))
123
+ def __eid(_row):
124
+ if _row.scope in ["exported"]:
125
+ return _row.OID
126
+ if _row["name"] in oids:
127
+ return oids[_row["name"]]
128
+ return None
129
+ data["UID"] = data.apply(__eid, axis=1)
130
+ return data
131
+
132
+ def bcIO(self, n:Union[str, int]) -> DataFrame:
133
+ el = self.bcEL(n).copy().set_index(keys='UID')
134
+ el = el[["model", "name", "unit", "modelType", "basicModelType", "kind", "scope"]]
135
+ im = el[el["scope"] == "imported"].copy()
136
+ ex = el[el["scope"] == "exported"].copy()
137
+ im["exportedBy"] = [ex.loc[i, "model"] if i in ex.index else "/* 외부 BC */" for i in im.index]
138
+ return concat([im, ex], axis=0)
139
+
140
+
141
+
142
+ if __name__ == "__main__":
143
+ from pandas import set_option
144
+ set_option('display.expand_frame_repr', False)
145
+
146
+
147
+ io = WorkspaceIO()
148
+ print(io["CanHSFPCMD"])
149
+ # print(io.bcPath(33))
150
+ # print(io.bcTree(33))
151
+ # print(io.bcEL(33))
152
+ # print(io.bcIO(33))
153
+
154
+ # io.bcIO(33).to_clipboard()
@@ -0,0 +1,2 @@
1
+ from . import ascet as AscetCAN
2
+ from . import db as DataBaseCAN
@@ -0,0 +1,3 @@
1
+ from .diag import CANDiag as ComDiag
2
+ from .comrx import ComRx
3
+ from .comdef import ComDef
@@ -0,0 +1,344 @@
1
+ from cannect.config import env
2
+ from cannect.core.can.rule import naming
3
+ from cannect.errors import CANDBError
4
+ from cannect.schema.candb import CanMessage, CanSignal
5
+
6
+ from datetime import datetime
7
+ from pandas import DataFrame, Series
8
+ from typing import Dict
9
+ import pandas as pd
10
+ import re
11
+
12
+
13
+ INFO = lambda revision: f"""* COMPANY: {env['COMPANY']}
14
+ * DIVISION: {env['DIVISION']}
15
+ * AUTHOR: {env['USERNAME']}
16
+ * CREATED: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
17
+ * DB VERSION: {revision}
18
+ {env["COPYRIGHT"]}
19
+
20
+ THIS MODEL IS AUTO-GENERATED.
21
+ """
22
+
23
+ INLINE = f"""
24
+ /* ----------------------------------------------------------------------------------------------------
25
+ Inline Function : Memory Copy
26
+ ---------------------------------------------------------------------------------------------------- */
27
+ inline void __memcpy(void *dst, const void *src, size_t len) {{
28
+ size_t i;
29
+ char *d = dst;
30
+ const char *s = src;
31
+ for (i = 0; i < len; i++)
32
+ d[i] = s[i];
33
+ }}
34
+
35
+ /* ----------------------------------------------------------------------------------------------------
36
+ Inline Function : Message Counter Check
37
+ ---------------------------------------------------------------------------------------------------- */
38
+ inline void cntvld(uint8 *vld, uint8 *timer, uint8 recv, uint8 calc, uint8 thres) {{
39
+ if ( recv == calc ) {{
40
+ *timer += 1;
41
+ if ( *timer >= thres ) {{
42
+ *timer = thres;
43
+ *vld = 0;
44
+ }}
45
+ }}
46
+ else {{
47
+ *timer = 0;
48
+ *vld = 1;
49
+ }}
50
+ }}
51
+
52
+ /* ----------------------------------------------------------------------------------------------------
53
+ Inline Function : CRC Check
54
+ ---------------------------------------------------------------------------------------------------- */
55
+ inline void crcvld(uint8 *vld, uint8 *timer, uint8 recv, uint8 calc, uint8 thres) {{
56
+ if ( recv == calc ) {{
57
+ *timer = 0;
58
+ *vld = 1;
59
+ }}
60
+ else {{
61
+ *timer += 1;
62
+ if ( *timer >= thres ) {{
63
+ *timer = thres;
64
+ *vld = 0;
65
+ }}
66
+ }}
67
+ }}
68
+
69
+ /* ----------------------------------------------------------------------------------------------------
70
+ Inline Function : Alive Counter Check
71
+ ---------------------------------------------------------------------------------------------------- */
72
+ inline void alvvld(uint8 *vld, uint8 *timer, uint8 recv, uint8 calc, uint8 thres) {{
73
+ if ( ( recv == calc ) || ( (recv - calc) > 10 ) ) {{
74
+ *timer += 1;
75
+ if ( *timer >= thres ) {{
76
+ *timer = thres;
77
+ *vld = 0;
78
+ }}
79
+ }}
80
+ else {{
81
+ *timer = 0;
82
+ *vld = 1;
83
+ }}
84
+ }}
85
+ """
86
+
87
+
88
+ def SignalDecode(signal:CanSignal, rule:naming=None) -> str:
89
+ if signal.empty:
90
+ return ""
91
+ if not rule:
92
+ rule = naming(signal.Message)
93
+ name = signal.SignalRenamed if signal.SignalRenamed else signal.name
94
+ size = 8 if signal.Length <= 8 else 16 if signal.Length <= 16 else 32
95
+ buff = f'{rule.tag}.B.{name}'
96
+ elem = f'{name}_Can'
97
+ if signal.Message == "L_BMS_22_100ms" and signal.Length == 32:
98
+ return f"""{elem} = (uint32)({buff}_1
99
+ + ({buff}_2 << 8)
100
+ + ({buff}_3 << 16)
101
+ + ({buff}_4 << 24));"""
102
+
103
+ if signal["Value Type"].lower() == "unsigned":
104
+ return f"{elem} = (uint{size}){buff};"
105
+
106
+ if signal.SignedProcessing.lower() == "complement":
107
+ if signal.Length in [8, 16, 32]:
108
+ return f"{elem} = (sint{size}){buff};"
109
+ else:
110
+ msb = f"( {buff} >> {signal.Length - 1} ) && 1"
111
+ neg = f"(sint{size})({buff} | {hex(2 ** size - 2 ** signal.Length).upper().replace('X', 'x')})"
112
+ pos = f"(sint{size}){buff}"
113
+ return f"{elem} = {msb} ? {neg} : {pos};"
114
+ elif signal.SignedProcessing.lower() == "absolute":
115
+ msb = f"( {buff} >> {signal.Length - 1} ) && 1"
116
+ neg = f"(sint{size})( (~{buff} + 1) | {hex(2 ** size - 2 ** (signal.Length - 1)).upper().replace('X', 'x')} )"
117
+ pos = f"(sint{size}){buff}"
118
+
119
+ syn = f"{elem} = {msb} ? {neg} : {pos};"
120
+ rtz = f"if ( {buff} == {hex(2 ** (signal.Length - 1)).upper().replace('X', 'x')} ) {{ {elem} = 0x0; }}"
121
+
122
+ if str(signal.name) in ["TCU_TqRdctnVal", "TCU_EngTqLimVal", "L_TCU_TqRdctnVal", "L_TCU_EngTqLimVal"]:
123
+ syn += f'\n{rtz}'
124
+ return syn
125
+ else:
126
+ raise CANDBError("Signed Signal must be specified the processing method.")
127
+
128
+
129
+ class MessageValidator:
130
+ def __init__(self, alv_or_crc:CanSignal, rule:naming=None):
131
+ var = f'{alv_or_crc.name}_Can'
132
+ calc =f'{alv_or_crc.name}Calc'
133
+ self.decode = SignalDecode(alv_or_crc, rule)
134
+ self.encode = ''
135
+ if alv_or_crc.empty:
136
+ self.calcCode = ''
137
+ self.validate = ''
138
+ return
139
+ elif alv_or_crc.isCrc():
140
+ self.calcCode = f'{calc} = CRC{alv_or_crc.Length}bit_Calculator.calc( {alv_or_crc.ID}, {rule.tag}.Data, {rule.dlc} );'
141
+ self.validate = f'crcvld( &{rule.crcValid}, &{rule.crcTimer}, {var}, {calc}, {rule.thresholdTime} );'
142
+ elif alv_or_crc.isAliveCounter():
143
+ self.calcCode = f'{calc} = {var};'
144
+ self.validate = f'alvvld( &{rule.aliveCountValid}, &{rule.aliveCountTimer}, {var}, {calc}, {rule.thresholdTime} );'
145
+ else:
146
+ pass
147
+ return
148
+
149
+
150
+ class MessageCode:
151
+ SEND_TYPE = {
152
+ "P": "Periodic",
153
+ "PE": "Periodic On Event",
154
+ "EC": "Event On Change",
155
+ "EW": "Event On Write",
156
+ }
157
+
158
+ def __init__(self, message:CanMessage, exclude_tsw:bool=True):
159
+ self.message = message
160
+ self.name = name = str(message.name)
161
+ self.names = naming(self.name)
162
+ self.exclude_tsw = exclude_tsw
163
+
164
+ self.srv_name = lambda md: f"#define COMPILE_UNUSED__{md.upper()}_IMPL__{name}"
165
+ return
166
+
167
+ def __getitem__(self, item):
168
+ return self.message[item]
169
+
170
+ def messageAlign(self) -> list:
171
+ buffer = [f"Reserved_{n // 8}" for n in range(8 * self["DLC"])]
172
+ self.message.ITERATION_INCLUDES_CRC = self.message.ITERATION_INCLUDES_ALIVECOUNTER = True
173
+ for sig in self.message:
174
+ index = sig.StartBit
175
+ while index < (sig.StartBit + sig.Length):
176
+ buffer[index] = sig.SignalRenamed if sig.SignalRenamed else sig.Signal
177
+ index += 1
178
+
179
+ # Exception
180
+ cnt = {}
181
+ for n, sig in enumerate(buffer.copy()):
182
+ if sig.startswith('xEV_Tot'):
183
+ if not sig in cnt:
184
+ cnt[sig] = 0
185
+ buffer[n] = f'{buffer[n]}_{(cnt[sig] // 8) + 1}'
186
+ cnt[sig] += 1
187
+
188
+ aligned = []
189
+ count, name = 0, buffer[0]
190
+ for n, sig in enumerate(buffer):
191
+ if sig == name:
192
+ count += 1
193
+ if n == 8 * self["DLC"] - 1:
194
+ aligned.append(f"uint32 {name} : {count};")
195
+ else:
196
+ aligned.append(f"uint32 {name} : {count};")
197
+ count, name = 1, sig
198
+
199
+ eigen = []
200
+ aligned_copy = aligned.copy()
201
+ for n, struct in enumerate(aligned):
202
+ label = struct.split(" : ")[0].replace("uint32 ", "")
203
+ if label in eigen:
204
+ aligned_copy[n] = aligned_copy[n].replace(label, f'{label}_{eigen.count(label)}')
205
+ eigen.append(label)
206
+
207
+ return aligned_copy
208
+
209
+ def signalDecode(self, spliter:str="\n\t") -> str:
210
+ code = []
211
+ for sig in self.message:
212
+ if sig.isAliveCounter() or sig.isCrc():
213
+ continue
214
+ code.append(SignalDecode(sig, self.names))
215
+ return spliter.join(code)
216
+
217
+ @property
218
+ def def_name(self) -> str:
219
+ chn = "PL2" if self["Channel"] == "H" else "PL1" if self["Channel"] == "L" else "P"
220
+ bsw = f"CAN_MSGNAME_{self['Message']}_{chn}"
221
+ if self["Message"] == "EGSNXUpStream_Data":
222
+ bsw = "CAN_MSGNAME_EGSNXUpStream_B1_data_1"
223
+ if self["Message"] == "EGSNXUpStream_Req":
224
+ bsw = "CAN_MSGNAME_EGSNXUpStream_B1_Rqst"
225
+ if self["Message"] == "HCU_11_P_00ms":
226
+ bsw = "CAN_MSGNAME_HCU_11_00ms_P"
227
+ if self["Message"] == "HCU_11_H_00ms":
228
+ bsw = "CAN_MSGNAME_HCU_11_00ms_PL2"
229
+ if self["Message"] == "IMU_01_10ms":
230
+ bsw = "CAN_MSGNAME_YRS_01_10ms_P"
231
+ if self.message.isTsw() and self.exclude_tsw:
232
+ bsw = 255
233
+ asw = f'MSGNAME_{naming(self["Message"]).tag}'
234
+ return f"#define {asw}\t{bsw}"
235
+
236
+ @property
237
+ def struct(self) -> str:
238
+ aligned = '\n\t\t'.join(self.messageAlign())
239
+ return f"""
240
+ /* ------------------------------------------------------------------------------
241
+ MESSAGE\t\t\t: {self["Message"]}
242
+ MESSAGE ID\t\t: {self["ID"]}
243
+ MESSAGE DLC\t: {self["DLC"]}
244
+ SEND TYPE\t\t: {self["Send Type"]}
245
+ -------------------------------------------------------------------------------- */
246
+ typedef union {{
247
+ uint8 Data[{self["DLC"]}];
248
+ struct {{
249
+ {aligned}
250
+ }} B;
251
+ }} CanFrm_{self.names.tag};"""
252
+
253
+ @property
254
+ def method(self) -> str:
255
+ names = self.names
256
+ aliveCounter = MessageValidator(self.message.aliveCounter, names)
257
+ crc = MessageValidator(self.message.crc, names)
258
+ code = f"""
259
+ /* ------------------------------------------------------------------------------
260
+ MESSAGE\t\t\t: {self.name}
261
+ MESSAGE ID\t\t: {self["ID"]}
262
+ MESSAGE DLC\t: {self["DLC"]}
263
+ SEND TYPE\t\t: {self.SEND_TYPE[self["Send Type"]]}
264
+ VERSION\t\t\t: {self["Version"]}
265
+ -------------------------------------------------------------------------------- */
266
+ if ( CanFrm_Recv( MSGNAME_{names.tag}, {names.buffer}, &{names.dlc} ) == CAN_RX_UPDATED ) {{
267
+
268
+ CanFrm_{names.tag} {names.tag} = {{0, }};
269
+ __memcpy( {names.tag}.Data, {names.buffer}, {names.dlc} );
270
+
271
+ { crc.decode }
272
+ { crc.calcCode }
273
+ { aliveCounter.decode }
274
+
275
+ { self.signalDecode() }
276
+
277
+ { names.counter }++;
278
+ }}
279
+
280
+ cntvld( &{names.messageCountValid}, &{names.messageCountTimer}, {names.counter}, {names.counterCalc}, {names.thresholdTime} );
281
+ { crc.validate }
282
+ { aliveCounter.validate }
283
+
284
+ { names.counterCalc } = { names.counter };
285
+ { aliveCounter.calcCode }
286
+ """
287
+ pcode = code[1:].splitlines()
288
+ ccode = []
289
+ for n, line in enumerate(pcode):
290
+ if n:
291
+ prev_line = pcode[n-1].replace("\t", "").replace(" ", "")
292
+ curr_line = line.replace("\t", "").replace(" ", "")
293
+ if prev_line == curr_line == "":
294
+ continue
295
+ ccode.append(line)
296
+ return "\n".join(ccode)
297
+
298
+ def to_rx(self, model: str) -> str:
299
+ tab, i = '\t', 0
300
+ send_type = {
301
+ "P": "Periodic",
302
+ "PE": "Periodic On Event",
303
+ "EC": "Event On Change",
304
+ "EW": "Event On Write",
305
+ }
306
+ syntax = f"""
307
+ /* ------------------------------------------------
308
+ MESSAGE\t\t\t: {self["Message"]}
309
+ MESSAGE ID\t\t: {self["ID"]}
310
+ MESSAGE DLC\t: {self["DLC"]}
311
+ SEND TYPE\t\t: {send_type[self["Send Type"]]}
312
+ CHANNEL\t\t\t: {self["Channel"]}-CAN
313
+ -------------------------------------------------- */"""
314
+ if self["SystemConstant"]:
315
+ syntax += f"\n#if ( {self['SystemConstant']} )"
316
+ if self["Codeword"]:
317
+ syntax += f"\nif ( {self['Codeword']} ) {{"
318
+ i += 1
319
+ syntax += f"\n{tab * i}{model.upper()}_IMPL__{self['Message']}();\n"
320
+ if self["Codeword"]:
321
+ syntax += f"}}\n"
322
+ if self["SystemConstant"]:
323
+ syntax += f"#endif\n"
324
+ return syntax
325
+
326
+ @classmethod
327
+ def method_contains_message(cls, context: Dict[str, str]) -> DataFrame:
328
+ status = {}
329
+ for method, code in context.items():
330
+ if code is None:
331
+ status[method] = None
332
+ else:
333
+ fs = [f.split("__")[-1] for f in re.findall(r'\bCOMDEF_\w*', code)]
334
+ status[method] = Series(index=fs, data=fs)
335
+ return pd.concat(status, axis=1)
336
+
337
+ if __name__ == "__main__":
338
+ from pyems.candb import CAN_DB
339
+
340
+ testDB = CAN_DB.to_developer_mode("HEV")
341
+
342
+ code = MessageCode(testDB.messages["L_BMS_22_100ms"])
343
+ print(code.def_name)
344
+ print(code.method)