Open fullipsori opened 1 year ago
package com.autoever.poc.parser.can;
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors;
import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList;
import com.autoever.poc.parser.Parseable;
public class EventParser implements Parseable{
private Element mNode;
public String category;
public String name;
public String bitwise;
public int preTime;
public int postTime;
public List<TriggerParser> triggers;
public List<Object> msgTable;
public Boolean preTriggerCondition = null;
public EventParser(Element node) {
this.mNode = node;
category = mNode.getAttribute("Category");
name = mNode.getAttribute("Name");
bitwise = mNode.getAttribute("BIT_WISE");
preTime = Integer.parseInt(mNode.getAttribute("preData"));
postTime = Integer.parseInt(mNode.getAttribute("postData"));
triggers = PolicyParser.GetElements.apply(mNode.getChildNodes(), "Trigger")
.stream().map(e -> new TriggerParser(e, triggable))
.peek(e -> msgTable.add(e.returnVal))
.collect(Collectors.toList());
}
@Override
public void parse() {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
private Triggable triggable = (time, status) -> {
// TODO Auto-generated method stub
boolean rvalue = false;
if(bitwise.equals("OR")) {
rvalue = false;
if(triggers.stream().anyMatch(t -> t.status)) {
rvalue = true;
}
} else {
rvalue = true;
if(triggers.stream().anyMatch(t -> !t.status)) {
rvalue = false;
}
}
if(preTriggerCondition != null) {
if(preTriggerCondition != rvalue && status == false) {
if(rvalue) {
preTriggerCondition = rvalue;
return Arrays.asList(
name, String.valueOf(preTime), String.valueOf(postTime), category, "OnTrue"
);
}else {
preTriggerCondition = rvalue;
return Arrays.asList(
name, String.valueOf(preTime), String.valueOf(postTime), category, "OnFalse"
);
}
}
}
if(status&& rvalue) {
return Arrays.asList(
name, String.valueOf(preTime), String.valueOf(postTime), category, "OnChange"
);
}else if(status&& !rvalue) {
return Arrays.asList(
name, String.valueOf(preTime), String.valueOf(postTime), category, "OnFalse"
);
}
preTriggerCondition = rvalue;
return null;
};
}
package com.autoever.poc.parser.can;
import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.BiFunction; import java.util.stream.Collectors; import java.util.stream.IntStream;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList;
import com.autoever.poc.parser.Parseable;
public class PolicyParser implements Parseable {
private String filename;
private Path xmlFilePath;
private Element rootNode;
private Optional<Element> preCondition;
private String KeyStatus;
private TriggerParser KeyTrig;
private List<EventParser> EventList = new ArrayList<>();
private Triggable triggerable = (a,b) -> null;
public PolicyParser(String xmlfile, DocumentBuilder documentBuilder) {
this.xmlFilePath = Paths.get(xmlfile);
this.filename = this.xmlFilePath.getFileName().toString().substring(0, this.xmlFilePath.getFileName().toString().lastIndexOf('.'));
try {
Document document = documentBuilder.parse(xmlFilePath.toFile());
rootNode = document.getDocumentElement();
} catch (Exception e) {
rootNode = null;
}
preCondition = null;
EventList.clear();
}
public static BiFunction<NodeList, String, Optional<Element>> GetElement = (nodelist, name) -> IntStream.range(0, nodelist.getLength())
.mapToObj(nodelist::item)
.filter(n-> n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().equals(name))
.map(n -> (Element)n)
.findFirst();
public static BiFunction<NodeList, String, List<Element>> GetElements = (nodelist, name) -> IntStream.range(0, nodelist.getLength())
.mapToObj(nodelist::item)
.filter(n-> n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().equals(name))
.map(n -> (Element)n)
.collect(Collectors.toList());
public long minPreTime;
public Object[] msgFilter = {Optional.empty(),Optional.empty(),Optional.empty(),Optional.empty(),Optional.empty(),Optional.empty()};
@Override
public void parse() {
// DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // DocumentBuilder documentBuilder; try { // documentBuilder = factory.newDocumentBuilder();
if(rootNode == null) return;
NodeList children = rootNode.getChildNodes();
preCondition = GetElement.apply(children, "PreCondition");
preCondition.ifPresent(e -> {
KeyStatus = e.getAttribute("Key");
GetElement.apply(e.getChildNodes(), "Trigger").ifPresent(ele -> {
KeyTrig = new TriggerParser(ele, triggerable);
});
});
for(Element event : GetElements.apply(children, "Event")) {
EventParser e = new EventParser(event);
if(minPreTime < e.preTime) {
minPreTime = e.preTime;
}
EventList.add(e);
// [returnVal=[,,],returnVal]
for(Object el : e.msgTable) {
List<Object> ta = (List<Object>)el;
int ch = Integer.parseInt((String)ta.get(0));
int id = Integer.parseInt((String)ta.get(1));
if(msgFilter[ch] == null) {
msgFilter[ch] = new HashMap<Integer,Object>();
}
((Map<Integer,Object>)msgFilter[ch]).compute(id, (k, v) -> (v == null)? Arrays.asList(ta.get(2)): ((List<Object>)v).add(ta.get(2)));
if(ta.size() > 3) { //tpdtID type?
int tpdtID = Integer.parseInt((String)ta.get(3));
((Map<Integer,Object>)msgFilter[ch]).compute(tpdtID, (k, v) -> (v == null)? Arrays.asList(ta.get(2)): ((List<Object>)v).add(ta.get(2)));
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
};
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// new PolicyParser("d:/projects/vdms/resources/policy/BM-15C-0008.xml").parse(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder; try { documentBuilder = factory.newDocumentBuilder(); }catch(Exception e) { e.printStackTrace(); } }
}
package com.autoever.poc.parser.can;
import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class PolicyRepository {
public Map<String, Document> mPolicyMap = new HashMap<>();
private static PolicyRepository mInstance = new PolicyRepository();
public static PolicyRepository getInstance() {
return mInstance;
}
public static void LoadPolicy(String dirPath, String ext) {
if(dirPath == null || dirPath.isBlank()) return;
Map<String, Document> policyMap = PolicyRepository.getInstance().mPolicyMap;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder;
try {
documentBuilder = factory.newDocumentBuilder();
policyMap.clear();
Files.list(Paths.get(dirPath))
.filter(path -> path.toString().endsWith(ext))
.forEach(path -> {
try {
String filename = path.getFileName().toString();
policyMap.put(
filename.substring(0, filename.lastIndexOf('.')),
documentBuilder.parse(path.toFile())
);
} catch (Exception e) {
e.printStackTrace();
}
});
} catch (Exception e) {
return;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
LoadPolicy("d:/projects/vdms/resources/policy", "xml");
PolicyRepository.getInstance().mPolicyMap.entrySet()
.forEach(entry -> {
System.out.println("filename:" + entry.getKey() + " precondition:" + entry.getValue().getDocumentElement().getAttribute("timeZone"));
});
}
}
package com.autoever.poc.parser.can;
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional;
import org.w3c.dom.Element; import org.w3c.dom.NodeList;
import com.autoever.poc.common.StringUtils; import com.autoever.poc.parser.Parseable;
public class TriggerParser implements Parseable{
public boolean status = false;
public BaseParser callback = null;
public List<Object> returnVal = new ArrayList<>();
public Integer ch;
public Integer id;
public String msgType;
public String type;
/* Signal */
public int sigstartbit;
public int siglength;
public String sigendian;
public String sigtype;
public float sigfactor;
public float sigoffset;
/* Condition */
public String conditionformula;
public float conditionvalue;
public float conditionduration;
/* parse */
public long time;
public int lastLength = 0;
public Triggable EventCallback;
private Element mNode;
public TriggerParser(Element node, Triggable cb) {
this.mNode = node;
this.EventCallback = cb;
status = false;
callback = null;
returnVal.clear();
NodeList nodeList = mNode.getChildNodes();
Optional<Element> msgxml = PolicyParser.GetElement.apply(nodeList, "Message");
msgxml.ifPresent(e -> {
ch = Integer.parseInt(e.getAttribute("Channel"));
id = Integer.parseInt(e.getAttribute("ID"), 16);
msgType = e.getAttribute("type");
});
if(msgType.equals("E")) {
id &= 0x00FFFFFF;
}else {
id &= 0x7FF;
}
type = mNode.getAttribute("type");
if(type.equals("CAN")) {
Optional<Element> sigxml = PolicyParser.GetElement.apply(nodeList, "Siganl");
sigxml.ifPresent(e -> {
sigstartbit = Integer.parseInt(e.getAttribute("Startbit"));
siglength = Integer.parseInt(e.getAttribute("Length"));
sigendian = e.getAttribute("endian");
sigtype = e.getAttribute("type");
sigfactor = Float.parseFloat(e.getAttribute("factor"));
sigoffset = Float.parseFloat(e.getAttribute("offset"));
});
Optional<Element> conditionxml = PolicyParser.GetElement.apply(nodeList, "condition");
conditionxml.ifPresent(e -> {
conditionformula = e.getAttribute("compare");
conditionvalue = Float.parseFloat(e.getAttribute("value"));
conditionduration =Float.parseFloat(e.getAttribute("duration"));
});
callback = canParseable;
returnVal = Arrays.asList(ch,id,callback);
}else if(type.equals("UDS")) {
callback = udsParseable;
lastLength = 0;
returnVal = Arrays.asList(ch,id,callback);
}else if(type.equals("DM1")) {
callback = dmParseable;
lastDmSize = 0;
nowDmSize = 0;
lastDm1 = null;
dm1Data = null;
dmFlag = false;
Optional<Element> msgxml2 = PolicyParser.GetElement.apply(mNode.getChildNodes(), "TPDT");
msgxml2.ifPresent(e -> {
tpdtID = Integer.parseInt(e.getAttribute("ID"), 16);
if("E".equals(msgType)) {
tpdtID &= 0x00FFFFFF;
}else {
tpdtID &= 0x7FF;
}
lamp = e.getAttribute("Lamp");
});
returnVal = Arrays.asList(ch,id,callback,tpdtID);
}
}
@Override
public void parse() {
// TODO Auto-generated method stub
}
// [DataChannel, DeltaTime, MSGInfo, DataID, DLC, data[10:10 + dlc_Size[DLC]], temp, self.BaseTime, self.VehicleKey]
// temp = dlcsize + data[10:10+dlcSize[DLC]]
public Float lastvalue = null;
public double conditionTime = 0.0;
public static CanParseable canParseable = (instance, message) -> {
TriggerParser trigger = (TriggerParser)instance;
List<String> canmsg = (List<String>)message;
byte[] rawdata = canmsg.get(5).getBytes();
trigger.time = Long.parseLong(canmsg.get(1));
long baseTime = Long.parseLong(canmsg.get(7));
int rawvalue = 0;
int startbyte = trigger.sigstartbit >> 3;
int lastbyte = (trigger.sigstartbit + trigger.siglength -1) >> 3;
/** fullipsori: java 에서 동작하는지 확인 필요함 **/
if("Little".equals(trigger.sigendian)) {
for(int i=lastbyte; i > startbyte-1; i--) {
rawvalue = rawvalue*256 + rawdata[i];
}
rawvalue = rawvalue >> (trigger.sigstartbit % 8);
}else {
for(int i=startbyte; i<lastbyte+1; i++) {
rawvalue = rawvalue * 256 + rawdata[i];
}
rawvalue = rawvalue >> ((8000 - trigger.sigstartbit - trigger.siglength) % 8);
}
rawvalue = rawvalue & ((int)Math.pow(2,trigger.siglength) -1);
if("signed".equals(trigger.sigtype)) {
if((rawvalue & (1<<(trigger.siglength-1))) != 0) {
rawvalue = (-(((~rawvalue) & ((int)Math.pow(2, trigger.siglength) -1)) + 1));
}
}
float value = rawvalue * trigger.sigfactor + trigger.sigoffset;
boolean rvalue = false;
switch(trigger.conditionformula) {
case "GE": {
if(value >= trigger.conditionvalue)
rvalue = true;
break;
}
case "GT": {
if(value > trigger.conditionvalue)
rvalue = true;
break;
}
case "LE": {
if(value <= trigger.conditionvalue)
rvalue = true;
break;
}
case "LT": {
if(value < trigger.conditionvalue)
rvalue = true;
break;
}
case "EQ": {
if(value == trigger.conditionvalue)
rvalue = true;
break;
}
case "NEQ": {
if(value != trigger.conditionvalue)
rvalue = true;
break;
}
case "DIFF": {
if(trigger.lastvalue == null) {
trigger.lastvalue = value;
}else if(value != trigger.lastvalue) {
trigger.status = true;
trigger.lastvalue = value;
return trigger.EventCallback.OnCalled(trigger.time, true);
}
return null;
}
}
if(trigger.status != rvalue) {
if(trigger.conditionTime + trigger.conditionduration <= trigger.time + baseTime) {
trigger.status = rvalue;
trigger.conditionTime = trigger.time + baseTime;
if(!"DIFF".equals(trigger.conditionformula)) {
//fullipsori check second parm (trigger.time)
return trigger.EventCallback.OnCalled(trigger.time, false);
}
}
}else {
trigger.status = rvalue;
if(trigger.conditionTime == 0) {
trigger.conditionTime = trigger.time + baseTime;
if(!"DIFF".equals(trigger.conditionformula)) {
return trigger.EventCallback.OnCalled(trigger.time, false);
}
}
}
return null;
};
// [DataChannel, DeltaTime, MSGInfo, DataID, DLC, data[10:10 + dlc_Size[DLC]], temp, self.BaseTime, self.VehicleKey]
// temp = dlcsize + data[10:10+dlcSize[DLC]]
public int lastDmSize = 0;
public int nowDmSize;
public byte[] dm1Data;
public boolean dmFlag = false;
public int tpdtID = 0;
public byte[] lastDm1=null;
public String lamp = "";
public static DMParseable dmParseable = (instance, message) -> {
TriggerParser trigger = (TriggerParser)instance;
List<String> dm1msg = (List<String>)message;
byte[] rawdata = dm1msg.get(5).getBytes(); //fullipsori "ISO8859-1"
trigger.time = Long.parseLong(dm1msg.get(1));
if(trigger.id == (Integer.parseInt(dm1msg.get(3)) & 0x00FFFFFF)) {
if(rawdata[5] == 0xCA && rawdata[6] == 0xFE) {
trigger.nowDmSize = (rawdata[2] & 0xF) * 256 + rawdata[1];
trigger.dm1Data = rawdata;
}else {
trigger.dm1Data = null;
}
}else if(trigger.tpdtID == (Integer.parseInt(dm1msg.get(3)) & 0x00FFFFFF) && trigger.lamp.equals("False")) {
if(trigger.dm1Data != null && rawdata[0] == 1) {
if(trigger.lastDmSize == 0) {
trigger.lastDmSize = trigger.nowDmSize;
}else {
if(trigger.nowDmSize != trigger.lastDmSize) {
trigger.status = true;
trigger.lastDmSize = trigger.nowDmSize;
trigger.lastDm1 = StringUtils.mergeByteArray(Arrays.copyOfRange(rawdata, 3, 6), Arrays.copyOfRange(rawdata, 7, rawdata.length));
trigger.dm1Data = null;
return trigger.EventCallback.OnCalled(trigger.time, true);
}
}
if(trigger.lastDm1 == null) {
trigger.status = true;
trigger.lastDm1 = StringUtils.mergeByteArray(Arrays.copyOfRange(rawdata, 3, 6), Arrays.copyOfRange(rawdata, 7, rawdata.length));
trigger.dm1Data = null;
return trigger.EventCallback.OnCalled(trigger.time, true);
}else {
if(Arrays.equals(trigger.lastDm1, StringUtils.mergeByteArray(Arrays.copyOfRange(rawdata, 3, 6), Arrays.copyOfRange(rawdata, 7, rawdata.length)))) {
trigger.status = true;
trigger.lastDm1 = StringUtils.mergeByteArray(Arrays.copyOfRange(rawdata, 3, 6), Arrays.copyOfRange(rawdata, 7, rawdata.length));
trigger.dm1Data = null;
return trigger.EventCallback.OnCalled(trigger.time, true);
}
}
}
}else if(trigger.tpdtID == (Integer.parseInt(dm1msg.get(3)) & 0x00FFFFFF) && "AWL".equals(trigger.lamp)) {
if(trigger.dm1Data != null && rawdata[0] == 1) {
boolean rvalue = false;
//fullipsori bit 확인
int awlStatus = (rawdata[1] & 0B00001100) >> 2;
if(awlStatus == 1) {
rvalue = true;
}
trigger.status = rvalue;
return trigger.EventCallback.OnCalled(trigger.time, false);
}
}else if(trigger.tpdtID == (Integer.parseInt(dm1msg.get(3)) & 0x00FFFFFF) && "RSL".equals(trigger.lamp)) {
if(trigger.dm1Data != null && rawdata[0] == 1) {
boolean rvalue = false;
int awlStatus = (rawdata[1] & 0B00110000) >> 4;
if(awlStatus == 1) {
rvalue = true;
}
trigger.status = rvalue;
return trigger.EventCallback.OnCalled(trigger.time, false);
}
}
return null;
};
public static UDSParseable udsParseable = (instance, message) -> {
TriggerParser trigger = (TriggerParser)instance;
List<String> udsmsg = (List<String>)message;
byte[] rawdata = udsmsg.get(5).getBytes(); //fullipsori "ISO8859-1"
trigger.time = Long.parseLong(udsmsg.get(1));
int frameType = ((int)rawdata[0]) >> 4;;
int length;
if(frameType == 0) {
length = rawdata[0] & 0xF;
if(rawdata[1] == 0x59 || rawdata[1] == 0x58) {
if(trigger.lastLength == 0) {
trigger.lastLength = length;
if(length > 3) {
trigger.status = true;
return trigger.EventCallback.OnCalled(trigger.time, true);
}
}else {
if(trigger.lastLength != length && length > 3) {
trigger.status = true;
trigger.lastLength = length;
return trigger.EventCallback.OnCalled(trigger.time, true);
}else if(trigger.lastLength != length && length <= 3) {
trigger.status = false;
trigger.lastLength = length;
return trigger.EventCallback.OnCalled(trigger.time, true);
}
}
}
}else if(frameType == 1) {
length = (rawdata[0] & 0xF) * 256 + rawdata[1];
if(rawdata[2] == 0x59 || rawdata[2] == 0x58) {
if(trigger.lastLength != length) {
trigger.status = true;
trigger.lastLength = length;
return trigger.EventCallback.OnCalled(trigger.time, true);
}
}
}
return null; //check null or False
};
public static void main(String[] args) {
// TODO Auto-generated method stub
byte[] x = {0x01, 0x02, 0x03,0x04};
int rawvalue = 0;
for(int i=3; i > -1; i--) {
rawvalue = rawvalue*256 + x[i];
}
rawvalue = rawvalue >> ( 3% 8);
rawvalue = rawvalue & ((int)Math.pow(2, 28) -1);
if((rawvalue & (1<<(28-1))) != 0) {
rawvalue = (-(((~rawvalue) & ((int)Math.pow(2, 28) - 1)) + 1));
}
System.out.println("rawvalue:" + rawvalue);
rawvalue = 0;
for(int i=0; i<4; i++) {
rawvalue = rawvalue * 256 + x[i];
}
rawvalue = rawvalue >> ((8000 - 3 - 28) % 8);
rawvalue = rawvalue & ((int)Math.pow(2, 28) -1);
System.out.println("rawvalue:" + rawvalue);
System.out.println("x:" + x[2]*256);
System.out.println("x:" + (x[1] & 0B00000010));
System.out.println("x:" + (x[1] & 0B00000001));
System.out.println("a:" + 0B00000010);
}
}
import os import time import sys import struct import xml.etree.ElementTree as ETXML import bisect import numpy as np import pandas as pd import json
class VDMSRAW: def init(self, file, binary, vehicleKeyId, baseTime): self.VehicleKey = vehicleKeyId self.BaseTime = baseTime self.FPID = [] self.header = 0 self.RecordSum = 0 self.RealTime = 0 self.mode = None self.binData = binary self.InFile = None self.headerSize = 0
if file:
self.mode = "file"
try:
self.InFile = open(file, 'rb', 1024)
except:
print("File Read Error!!")
elif self.binData:
self.mode = "bin"
self.binIndex = 0
else:
raise ValueError("no data")
def rewind(self):
try:
if self.mode == "file" and self.InFile:
self.InFile.seek(self.headerSize)
elif self.mode == "bin":
self.binIndex = 0
else:
pass
except:
raise Exception("rewind Exception")
def close(self):
try:
if self.mode == "file" and self.InFile:
self.InFile.close()
else:
pass
except:
print("File close Exception")
def readStream(self, size):
try:
if self.mode == "bin":
data = self.binData[self.binIndex:self.binIndex+size]
self.binIndex += size
return data
elif self.mode == "file":
data = self.InFile.read(size)
return data
else:
raise Exception("unknown read mode")
except:
raise
def getMSG(self):
dlc_Size = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64]
try:
data = self.readStream(1)
DLC = data[0]
temp = data
except:
return None
MSGInfo = ""
data = self.readStream(10 + dlc_Size[DLC])
temp += data
DeltaTime, DataFlag, DataChannel, DataID = struct.unpack('!IBBI', data[0:10])
DeltaTime = DeltaTime * 0.00005 # 1 tick is 50us
if DataFlag == 2:
MSGInfo = "Error Frame"
else:
if (DataFlag and 1) == 1:
MSGInfo = "Extended ID"
else:
MSGInfo = "Standard ID"
if (DataFlag and 4) == 4:
MSGInfo = MSGInfo + " FD"
return [DataChannel, DeltaTime, MSGInfo, DataID, DLC, data[10:10 + dlc_Size[DLC]], temp, self.BaseTime, self.VehicleKey]
class triggeringThread: def init(self): self.trigMergeList = [] self.msgList = [] self.msgTimeList = [] self.KeyFlag = False
def findIdx(self, t, timeList): # Input time msgTimeList Idx
temp = bisect.bisect(timeList, t)
if temp == 0:
return temp
try:
if t - timeList[temp-1] < timeList[temp] - t:
return temp-1
else:
return temp
except:
return temp-1
def processSingleFile(self, raw, policy):
self.check_count = 0
self.all_count = 0
while True:
msg = raw.getMSG()
if msg == None:
break
self.all_count += 1
# [DataChannel, DeltaTime, MSGInfo, DataID, DLC, data[10:10 + dlc_Size[DLC]], temp, self.BaseTime, self.VehicleKey]
# temp = dlcsize + data[10:10+dlcSize[DLC]]
self.msgTimeList.append(msg[1])
self.msgList.append(msg[6])
# PreCondition -> Trigger -> Message -> id,ch, type(CAN) -> callback(parseCAN) test(test or checkTriggers)
if (msg[3] & 0x00FFFFFF) == policy.keyTrig.id and msg[0] == policy.keyTrig.ch:
policy.keyTrig.callback(msg) # call parseCAN
# trig ok?
try:
# preCondition 을 체크 않하거나 체크하는 경우 Trigger 조건에 만족하는지 체크
if policy.KeyStatus.upper() != 'ON' or policy.keyTrig.status == True:
self.KeyFlag = True
else:
self.KeyFlag = False
trigData = []
if self.KeyFlag == True and policy.msgFilter[msg[0]].get(msg[3] & 0x00FFFFFF) != None:
self.check_count += 1
for callBack in policy.msgFilter[msg[0]][msg[3] & 0x00FFFFFF]:
trig = callBack(msg)
if trig is not None:
trigData.append(trig)
if len(trigData) > 0:
for trig in trigData:
for removeTrig in trigData:
if removeTrig == trig:
continue
else:
if removeTrig[0] == trig[0]:
trigData.remove(trig)
for trig in trigData:
if trig != None:
# print("trig:", trig)
# trigData[4] : On True, On False, On Change
# msg: [DataChannel, DeltaTime, MSGInfo, DataID, DLC, fdata[10:10 + dlc_Size[DLC]],temp, self.BaseTime, self.VehicleKey]
# trig: [preTime, postTime, deltaTime, triggerName, value, category, status="OnTrue"]
# self.trigMergeList.append([msg[1] - trig[1], msg[1] + trig[2], msg[1], trig[0], False, trig[3], trig[4]])
self.trigMergeList.append([msg[1] - trig[1], msg[1] + trig[2], msg[1], trig[0], 0, trig[3], trig[4]])
except:
None
def triggerListToFile(self):
for trig in self.trigMergeList: # trig[7] : On True, On False, On Change
preIdx = self.findIdx(trig[0], self.msgTimeList)
postIdx = self.findIdx(trig[1], self.msgTimeList)
# print("Event Process : ", trig, preIdx, postIdx)
return
def Main(self, vdmsRAW, policy):
self.processSingleFile(vdmsRAW, policy)
print('check_count:', self.check_count, ' all_count:', self.all_count)
self.triggerListToFile()
""" xml 내의 Trigger type 에 대한 parsing 진행 """ import os import time import sys import struct import xml.etree.ElementTree as ETXML import bisect import numpy as np import pandas as pd import json
class TriggerParser(): def init(self, xmls, cb):
self.status = False
self.callback = None
self.returnVal = []
# parsing Message properties
msgxml = xmls.find('Message')
self.ch = int(msgxml.attrib['Channel'])
self.id = int(msgxml.attrib['ID'].replace('0x', ''), 16)
self.msgType = msgxml.attrib['type']
if self.msgType == 'E':
self.id = self.id & 0x00FFFFFF
else:
self.id = self.id & 0x7FF
self.type = xmls.attrib['type']
################################################
self.lastvalue = None
self.lastDmSize = None
self.conditionTime = 0.0
self.EventCallback = cb
if self.type == 'CAN':
## Parsing Signal properties
sigxml = xmls.find('Siganl')
self.sigstartbit = int(sigxml.attrib['Startbit'])
self.siglength = int(sigxml.attrib['Length'])
self.sigendian = sigxml.attrib['endian']
self.sigtype = sigxml.attrib['type']
self.sigfactor = float(sigxml.attrib['factor'])
self.sigoffset = float(sigxml.attrib['offset'])
## Parsing condition properties
conditionxml = xmls.find('condition')
self.conditionformula = conditionxml.attrib['compare']
self.conditionvalue = float(conditionxml.attrib['value'])
self.conditionduration = float(conditionxml.attrib['duration'])
#####
self.callback = self.parseCAN
self.returnVal = [self.ch, self.id, self.callback]
elif self.type == 'UDS':
self.callback = self.parseUDS
self.lastLength = 0
self.returnVal = [self.ch, self.id, self.callback]
elif self.type == 'DM1':
self.callback = self.parseDM1
self.lastDmSize = 0
self.nowDmSize = 0
self.lastDm1 = None
self.dm1Data = 0
self.dmFLag = False
msgxml2 = xmls.find('TPDT')
self.tpdtID = int(msgxml2.attrib['ID'].replace('0x', ''), 16)
if self.msgType == 'E':
self.tpdtID = self.tpdtID & 0x00FFFFFF
else:
self.tpdtID = self.tpdtID & 0x7FF
self.lamp = msgxml2.attrib['Lamp']
self.returnVal = [self.ch, self.id, self.callback, self.tpdtID]
def parseCAN(self, canmsg):
self.time = canmsg[1]
baseTime = canmsg[7]
rawvalue = 0
startbyte = self.sigstartbit >> 3
lastbyte = (self.sigstartbit + self.siglength - 1) >> 3
if self.sigendian == "Little":
for i in range(lastbyte, startbyte - 1, -1):
rawvalue = rawvalue * 256 + canmsg[5][i]
rawvalue = rawvalue >> (self.sigstartbit % 8)
else:
for i in range(startbyte, lastbyte + 1, 1):
rawvalue = rawvalue * 256 + canmsg[5][i]
rawvalue = rawvalue >> ((8000 - self.sigstartbit - self.siglength) % 8)
rawvalue = rawvalue & (2 ** self.siglength - 1)
if self.sigtype == "signed":
if (rawvalue & (1 << (self.siglength - 1))) != 0:
rawvalue = (-(((~rawvalue) & (2 ** self.siglength - 1)) + 1))
value = rawvalue * self.sigfactor + self.sigoffset
rvalue = False
if self.conditionformula == 'GE':
if value >= self.conditionvalue:
rvalue = True
elif self.conditionformula == 'GT':
if value > self.conditionvalue:
rvalue = True
elif self.conditionformula == 'LE':
if value <= self.conditionvalue:
rvalue = True
elif self.conditionformula == 'LT':
if value < self.conditionvalue:
rvalue = True
elif self.conditionformula == 'EQ':
if value == self.conditionvalue:
rvalue = True
elif self.conditionformula == 'NEQ':
if value != self.conditionvalue:
rvalue = True
elif self.conditionformula == 'DIFF':
if self.lastvalue == None:
self.lastvalue = value
elif value != self.lastvalue:
self.status = True
self.lastvalue = value
return self.EventCallback(self.time, True)
return None
if self.status != rvalue:
if self.conditionTime + self.conditionduration <= self.time + baseTime:
self.status = rvalue
self.conditionTime = self.time + baseTime
if self.conditionformula != 'DIFF':
return self.EventCallback(self.time)
else:
self.status = rvalue
if self.conditionTime == 0: # for init Event condition
self.conditionTime = self.time + baseTime
if self.conditionformula != 'DIFF':
return self.EventCallback(self.time)
self.conditionTime = self.time + baseTime
return None
def parseUDS(self, udsmsg):
self.time = udsmsg[1]
frameType = udsmsg[5][0] >> 4
if frameType == 0 : # Single, First Frame Only
Length = udsmsg[5][0] & 0xF
if udsmsg[5][1] == 0x59 or udsmsg[5][1] == 0x58: # SID 19, ReadDTCInformation
if self.lastLength == 0:
self.lastLength = Length
if Length > 3:
self.status = True
return self.EventCallback(self.time, True)
else:
if self.lastLength != Length and Length > 3:
self.status = True
self.lastLength = Length
return self.EventCallback(self.time, True)
elif self.lastLength != Length and Length <= 3:
self.status = False
self.lastLength = Length
return self.EventCallback(self.time, True)
elif frameType == 1: # Single, First Frame Only
Length = (udsmsg[5][0] & 0xF)*256 + udsmsg[5][1]
if udsmsg[5][2] == 0x59 or udsmsg[5][2] == 0x58: # SID 19, ReadDTCInformation
if self.lastLength != Length:
self.status = True
self.lastLength = Length
return self.EventCallback(self.time, True)
return False
def parseDM1(self, dm1msg):
self.time = dm1msg[1]
if self.id == (dm1msg[3] & 0x00FFFFFF): # TPCM
if dm1msg[5][5] == 0xCA and dm1msg[5][6] == 0xFE:
self.nowDmSize = (dm1msg[5][2] & 0xF)*256 + dm1msg[5][1]
self.dm1Data = dm1msg[5]
else:
self.dm1Data = 0
elif self.tpdtID == (dm1msg[3] & 0x00FFFFFF) and self.lamp == "False": # TPDT
if self.dm1Data != 0 and dm1msg[5][0] == 1:
if self.lastDmSize == 0: # size
self.lastDmSize = self.nowDmSize
else:
if self.nowDmSize != self.lastDmSize:
self.status = True
self.lastDmSize = self.nowDmSize
self.lastDm1 = (dm1msg[5][3:6]+dm1msg[5][7:])
self.dm1Data = 0
return self.EventCallback(self.time, True)
if self.lastDm1 == None: # data
self.status = True
self.lastDm1 = (dm1msg[5][3:6]+dm1msg[5][7:])
self.dm1Data = 0
return self.EventCallback(self.time, True)
else:
if self.lastDm1 != (dm1msg[5][3:6]+dm1msg[5][7:]):
self.status = True
self.lastDm1 = (dm1msg[5][3:6]+dm1msg[5][7:])
self.dm1Data = 0
return self.EventCallback(self.time, True)
elif self.tpdtID == (dm1msg[3] & 0x00FFFFFF) and self.lamp == "AWL": # TPDT
if self.dm1Data != 0 and dm1msg[5][0] == 1:
rvalue = False
awlStatus = (dm1msg[5][1]&0b00001100)>>2
if awlStatus == 1:
rvalue = True
self.status = rvalue
return self.EventCallback(self.time)
elif self.tpdtID == (dm1msg[3] & 0x00FFFFFF) and self.lamp == "RSL": # TPDT
if self.dm1Data != 0 and dm1msg[5][0] == 1:
rvalue = False
awlStatus = (dm1msg[5][1]&0b00110000)>>4
if awlStatus == 1:
rvalue = True
self.status = rvalue
return self.EventCallback(self.time)
return False
class EventParser(): def init(self, xmls): self.category = xmls.attrib['Category'] self.name = xmls.attrib['Name'] self.bitwise = xmls.attrib['BIT_WISE'] self.preTime = int(xmls.attrib['preData']) self.postTime = int(xmls.attrib['postData']) self.triggers=[] self.msgTable = [] self.preTriggerConditon = None self.msgCnt = 0
## 1. Parse Trigger property in XML.
## 2. callback = parseCAN
## 3. EventCallback = self.checkTriggers
## 4. msgTable = returnVal([message.ch, message.id, callback])
triggerList = xmls.findall('Trigger')
for t in triggerList:
trig = TriggerParser(t, self.checkTriggers) # append EventCallback = checkTriggers
self.triggers.append(trig)
self.msgTable.append(trig.returnVal)
def checkTriggers(self, time, onchange = False):
rvalue = False
if self.bitwise == "OR":
rvalue = False
for t in self.triggers:
if t.status == True:
rvalue = True
break
else:
rvalue = True
for t in self.triggers:
if t.status == False:
rvalue = False
break
if self.preTriggerConditon != None:
if self.preTriggerConditon != rvalue and onchange == False:
if rvalue == True:
# print("On True : %s %f" % (self.name, time))
self.preTriggerConditon = rvalue
return [self.name, self.preTime, self.postTime, self.category, "OnTrue"]
else:
# print("On False : %s %f" % (self.name, time))
self.preTriggerConditon = rvalue
return [self.name, self.preTime, self.postTime, self.category, "OnFalse"]
if onchange == True and rvalue == True:
# print("On Change : %s %f" % (self.name, time))
return [self.name, self.preTime, self.postTime, self.category, "OnChange"]
elif onchange == True and rvalue == False:
# print("On False* : %s %f" % (self.name, time))
return [self.name, self.preTime, self.postTime, self.category, "OnFalse"]
'''
if onchange == True and rvalue == True:
print("On Change : %s %f" % (self.name, time))
return [self.name, self.preTime, self.postTime, self.category, "OnChange"]
'''
self.preTriggerConditon = rvalue
return None
class PolicyParser(): def init(self, configfile): self.EventList = [] self.msgFilter = [{}, {}, {}, {}, {}, {}] self.minPreTime = 0 self.KeyStatus = 'ON'
self.readXMLFile(configfile)
def readXMLFile(self, policyFile):
# xml Read
try:
Top = ETXML.parse(policyFile)
print("Read policy file: ", policyFile)
except:
print("wrong policy file: %s" % policyFile)
keyXmls = Top.find('PreCondition')
self.KeyStatus = keyXmls.attrib['Key']
self.keyTrig = TriggerParser(keyXmls.find('Trigger'), test)
# trig XML passing
Eventxmls = Top.findall('Event')
for event in Eventxmls:
e = EventParser(event)
if self.minPreTime < e.preTime:
self.minPreTime = e.preTime
# EventList = [EventParser, EventParser]
self.EventList.append(e)
# msgTable
# # CAN : [self.ch, self.id, self.callback]
# # DM1 : [self.ch, self.id, self.callback, self.tpdtID]
# # msgFilter
# # # CAN : [{},{id: [parseCAN, parseCAN]},{},{},{}]
# # # DM1 : [{},{id(1): [parseDM1, parseDM1]},{},{},{tpdtID(4): parseDM1}]
for ta in e.msgTable: # msgTable = result of [message.id, message.ch, parseCAN]
if len(ta) > 3:
if self.msgFilter[ta[0]].get(ta[1]) != None: # returnVal
self.msgFilter[ta[0]][ta[1]].append(ta[2])
else:
self.msgFilter[ta[0]][ta[1]] = [ta[2]]
if self.msgFilter[ta[0]].get(ta[3]) != None:
self.msgFilter[ta[0]][ta[3]].append(ta[2])
else:
self.msgFilter[ta[0]][ta[3]] = [ta[2]]
else:
if self.msgFilter[ta[0]].get(ta[1]) != None:
self.msgFilter[ta[0]][ta[1]].append(ta[2])
else:
self.msgFilter[ta[0]][ta[1]] = [ta[2]]
def test(a, b=True): return
import sys, os import numpy as np import pandas as pd import json
FILENAME = 'VM-21C-0004_177554_1684869240.dat'
DOWNLOAD_ROOT = 'd:/projects/vdms/resources/download/' POLICY_ROOT = 'd:/projects/vdms/resources/policy/' CAN_FILE_PATH = DOWNLOADROOT + FILENAME filename = os.path.splitext(FILENAME)[0] tokens = filename.split("") BIN_DATA = '' can_data = None
vdmsRAW = VDMSRAW(CAN_FILE_PATH, BIN_DATA, tokens[1], int(tokens[2])) mainclass = triggeringThread() vdmsRAW.rewind() mainclass.Main(vdmsRAW, PolicyParser(POLICY_ROOT + tokens[0] + '.xml')) vdmsRAW.close()
data_np = np.array(mainclass.trigMergeList, dtype=object) data_df = pd.DataFrame(data_np) if not data_df.empty:
data_df.columns = ['preTime', 'postTime', 'deltaTime', 'eventName', 'value', 'category', 'status']
can_data = f'{{"can_data": {data_df.to_json(orient="records")}}}'
print("ended")
import os import time import sys import struct import binascii import datetime import pandas as pd import json import xml.etree.ElementTree as ETXML
class CCPRAW: def init(self, file, binary): self.mode = None self.binData = binary self.InFile = None self.headerSize = 0
if file:
self.mode = "file"
try:
self.InFile = open(file, 'rb', 1024)
except:
print("File read Error!!")
elif self.binData:
self.mode = "bin"
self.binIndex = 0
else:
raise ValueError("no data")
def rewind(self):
try:
if self.mode == "file" and self.InFile:
self.InFile.seek(self.headerSize)
elif self.mode == "bin":
self.binIndex = 0
else:
pass
except:
raise Exception("rewind Exception")
def close(self):
try:
if self.mode == "file" and self.InFile:
self.InFile.close()
else:
pass
except:
print("File close Exception")
def readStream(self, size):
try:
if self.mode == "bin":
data = self.binData[self.binIndex:self.binIndex+size]
self.binIndex += size
return data
elif self.mode == "file":
data = self.InFile.read(size)
return data
else:
raise Exception("unknown read mode")
except:
raise
def getMSG(self):
dlc_Size = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64]
try:
data = self.readStream(1)
DLC = data[0]
temp = data
except:
return None
if not DLC:
return None
data = self.readStream(10 + dlc_Size[DLC])
DeltaTime, DataFlag, DataChannel, DataID = struct.unpack('!IBBI', data[0:10])
DeltaTime = DeltaTime * 0.00005
return [DeltaTime, DataFlag, DataChannel, DataID, data[10:10 + dlc_Size[DLC]]]
def parse_ccp_data(val, odtMap): cmd = int(val[:1].hex(), 16) value = struct.unpack('<B'+odtMap[cmd-10][2],val) ret = {} for i in range(len(odtMap[cmd-10][0])): ret[odtMap[cmd-10][0][i]] = value[i+1] return ret
def processSingleFile(ccpRaw, odtMap): prev_cmd = 0 result = [] while True: msg = ccpRaw.getMSG() if msg == None: break ccp_data = msg[4] if prev_cmd != 0: if (prev_cmd != 255) and (ccp_data[0] >= 0x0a and ccp_data <= 0x3b): print(ccp_data[0], msg[0]) parsed = parse_ccp_data(ccp_data, odtMap) print(parsed) result.append(msg, parsed) prev_cmd = ccp_data[0] else: prev_cmd = ccp_data[0] else: prev_cmd = ccp_data[0]
return result
def generate_odt_map(measurement_list): odt_map = [] max_odt = 50 for i in range(max_odt): odt_map.append([[],7,''])
# 4Byte
for m in measurement_list:
if m[1] in ('SLONG','ULONG'):
for i in range(max_odt):
if odt_map[i][1] >= 4:
odt_map[i][0].append(m[0])
odt_map[i][1] -= 4
odt_map[i][2]+='L'
break
else:
pass
# 2Byte
for m in measurement_list:
if m[1] in ('SWORD','UWORD'):
for i in range(max_odt):
if odt_map[i][1] >= 2:
odt_map[i][0].append(m[0])
odt_map[i][1] -= 2
odt_map[i][2]+='H'
break
else:
pass
# 1Byte
for m in measurement_list:
if m[2] == 'UBYTE':
for i in range(max_odt):
if odt_map[i][1] >= 1:
odt_map[i][0].append(m[0])
odt_map[i][1] -= 1
odt_map[i][2]+='B'
break
else:
pass
# 남은공간은 Byte로 채움(Python unpack 처리 시 편의를 위해)
for i in range(len(odt_map)):
for j in range(odt_map[i][1]):
odt_map[i][2]+='B'
return odt_map
def get_odt_map(evt_file): tree = ETXML.parse(evt_file) root=tree.getroot() measurements = root.findall('.//Measurement') measurement_list = [] for measurement in measurements: measurement_list.append([measurement.findall('identName')[0].text,measurement.findall('Datatype')[0].text])
return generate_odt_map(measurement_list)
def load_evt(command, evtFolder): updated_evts = '' evt_files = []
if command.upper() == 'LOAD' or command.upper() == 'RELOAD':
evtList = os.listdir(evtFolder)
for evt in evtList:
filename = os.path.splitext(evt)[0]
EVT_DATAS[filename] = get_odt_map(evtFolder + '/' + filename + '.evt')
evt_files.append(filename)
if evt_files is not None:
updated_evt = ','.join(evt_files)
return updated_evt
EVT_DATAS = {}
evt_file = "d:/projects/from_hyuncar/ccp_source/0525/20230522133456_decrypted.evt" odtMap= get_odt_map(evt_file)
odtMap
odt_map = [[['heat_sys.msr_heat_oper', 'msr_tb_2', 'SK_Y.u8CcvDtc'], 0, 'LHB'], [['heat_relay_on_status', 'msr_tb_1', 'SK_Y.u8CcvDtcIndex'], 0, 'LHB'], [['nvm_soh_avg_max', 'msr_tb_3', 'SK_Y.u8OcvDtc'], 0, 'LHB'], [['nvm_soh_calc_cnt', 'msr_tb_4', 'SK_Y.u8OcvDtcIndex'], 0, 'LHB'], [['nvm_soh_target', 'msr_tb_5', 'SK_Y.u8RsDtc'], 0, 'LHB'], [['SOC', 'msr_tb_6', 'SK_Y.u8RsDtcIndex'], 0, 'LHB'], [['rec_soc_reset.last_type', 'msr_tb_7', 'nvm_batt_sk_safety_fail'], 0, 'LHB'], [['chg_oper_state', 'msr_tb_8', 'nvm_soc_population'], 0, 'LHB'], [['nvm_cnt_obc_chg', 'msr_tb_9', 'chg_abnormal_code'], 0, 'LHB'], [['nvm_cnt_qcs_chg', 'rec_soc_reset.cnt', 'chg_charging_now'], 0, 'LHB'], [['fault_code', 'nvm_temp_max', 'can_chg.obc_ac_detect'], 0, 'LHB'], [['msr_data.t_inlet', 'nvm_dtemp_max', 'nvm_batt_misd1_flt_cellno'], 0, 'LHB'], [['msr_data.t_inlet2', 'cell_01', 'nvm_batt_misd2_flt_cellno'], 0, 'LHB'], [['nvm_batt_misd1_flt_mod_no', 'cell_02', 'nvm_temp_population'], 0, 'LHB'], [['nvm_batt_misd1_flt_mod_no_h', 'cell_03'], 1, 'LHB'], [['nvm_batt_misd2_flt_mod_no', 'cell_04'], 1, 'LHB'], [['nvm_batt_misd2_flt_mod_no_h', 'cell_05'], 1, 'LHB'], [['nvm_sw_version', 'cell_06'], 1, 'LHB'], [['nvm_isol_impediance_min', 'cell_07'], 1, 'LHB'], [['cell_08', 'cell_09', 'cell_10'], 1, 'HHHB'], [['cell_11', 'cell_12', 'cell_13'], 1, 'HHHB'], [['cell_14', 'cell_15', 'cell_16'], 1, 'HHHB'], [['cell_17', 'cell_18', 'cell_19'], 1, 'HHHB'], [['cell_20', 'cell_21', 'cell_22'], 1, 'HHHB'], [['cell_23', 'cell_24', 'cell_25'], 1, 'HHHB'], [['cell_26', 'cell_27', 'cell_28'], 1, 'HHHB'], [['cell_29', 'cell_30', 'cell_31'], 1, 'HHHB'], [['cell_32', 'cell_33', 'cell_34'], 1, 'HHHB'], [['cell_35', 'cell_36', 'cell_37'], 1, 'HHHB'], [['cell_38', 'cell_39', 'cell_40'], 1, 'HHHB'], [['cell_41', 'cell_42', 'cell_43'], 1, 'HHHB'], [['cell_44', 'cell_45', 'cell_46'], 1, 'HHHB'], [['cell_47', 'cell_48', 'cell_49'], 1, 'HHHB'], [['cell_50', 'cell_51', 'cell_52'], 1, 'HHHB'], [['cell_53', 'cell_54', 'cell_55'], 1, 'HHHB'], [['cell_56', 'cell_57', 'cell_58'], 1, 'HHHB'], [['cell_59', 'cell_60', 'cell_61'], 1, 'HHHB'], [['cell_62', 'cell_63', 'cell_64'], 1, 'HHHB'], [['cell_65', 'cell_66', 'cell_67'], 1, 'HHHB'], [['cell_68', 'cell_69', 'cell_70'], 1, 'HHHB'], [['cell_71', 'cell_72', 'cell_73'], 1, 'HHHB'], [['cell_74', 'cell_75', 'cell_76'], 1, 'HHHB'], [['cell_77', 'cell_78', 'cell_79'], 1, 'HHHB'], [['cell_80', 'cell_81', 'cell_82'], 1, 'HHHB'], [['cell_83', 'cell_84', 'cell_85'], 1, 'HHHB'], [['cell_86', 'cell_87', 'cell_88'], 1, 'HHHB'], [['cell_89', 'cell_90'], 3, 'HHBBB'], [[], 7, 'BBBBBBB'], [[], 7, 'BBBBBBB'], [[], 7, 'BBBBBBB']]
datfile = "D:/projects/from_hyuncar/ccp_source/0525/HREV_N19-08-728_VM-21C-0016_BASE_2574-1_CCP_20230424074628_146119.dat"
ccpRaw = CCPRAW(datfile, None) result = processSingleFile(ccpRaw, odt_map) print(result)
#
#
#
#
#
#
<?xml version="1.0" encoding="UTF-8"?>
''
''
test