Vehicle Spy VSB file Spec
File Specification
Text Identifier |
6 |
single byte char array with text "icsbin"used to identify file type. |
File Version |
4 |
single byte char array indicate version. |
Version Section |
Variable (see below) |
This data structure is determinant the File Version |
Version Specification
Version 0x101
This format is no longer created. Click to see Network ID's
Length of Vs3 File |
4 |
int value indicating the length of the next section (the vs3 file). A zero indicates no vs3 file is present. |
Vs3 file |
variable (see above) |
vs3 file used to save this binary file. This vs3 file is later used to decode the binary data into usable information. |
Length of text comment |
4 |
int indicating the length of the text header comment of the saved file. SINCE THE COMMENT IS UNICODE THEREFORE HIS IS THE LENGTH IN CHARACTERS - NOT BYTES. |
Text comment |
2 bytes per character (see above for number of characters) |
Unicode text comment. |
Size of Buffer of Messages |
4 |
sizeof(VSBSpyMessage) multiplied by Number of messages saved to the file |
Current Buffer Pointer |
4 |
int value which is the pointer to the most recent buffer item +1. (only needed if Number of All time messages > Original buffer size) |
Original Buffer Size |
4 |
int value which is the size of the buffer memory originally allocated by this buffer |
Number of All time messages |
4 |
this indicates how many messages were received by this buffer (this number will indicate overflows) |
Buffer of Messages |
variable (see Size of Buffer of Messages) |
VSBSpyMessage structures |
Start Time of Collection |
struct icsspyMsgTime |
this is a comparison value between the system time stamp and the neoVI time stamp. |
Version 0x102
This format is created by the extractor. Click to see Network ID's
Length of EDP Section |
4 |
int value indicating the length of the next section (the EDP). A zero indicates no EDP section file is present. |
EDP Section |
variable (see above) |
used to save the extra data bytes for networks such as Ethernet, Flexray, and CANFD |
Buffer of Messages |
variable (see Size of Buffer of Messages) |
VSBSpyMessage structures |
Start Time of Collection |
struct icsspyMsgTime |
this is a comparison value between the system time stamp and the neoVI time stamp. |
Version 0x103
This format is created using VSpy. Click to see Network ID's
Length of EDP Section |
4 |
int value indicating the length of the next section (the EDP). A zero indicates no EDP section is present. |
EDP Section |
variable (see above) |
used to save the extra data bytes for networks such as Ethernet, Flexray, and CANFD |
Length of text comment |
4 |
int indicating the length of the text header comment of the saved file. SINCE THE COMMENT IS UNICODE THEREFORE HIS IS THE LENGTH IN CHARACTERS - NOT BYTES. |
Text comment |
2 bytes per character (see above for number of characters) |
Unicode text comment. |
Size of Buffer of Messages |
4 |
sizeof(VSBSpyMessage) multiplied by Number of messages saved to the file |
Current Buffer Pointer |
4 |
int value which is the pointer to the most recent buffer item +1. (only needed if Number of All time messages > Original buffer size) |
Original Buffer Size |
4 |
int value which is the size of the buffer memory originally allocated by this buffer |
Number of All time messages |
4 |
this indicates how many messages were received by this buffer (this number will indicate overflows) |
Buffer of Messages |
variable (see Size of Buffer of Messages) |
VSBSpyMessage structures |
Start Time of Collection |
struct icsspyMsgTime |
this is a comparison value between the system time stamp and the neoVI time stamp. |
EDP section
Used by version 0x102 and 0x103. The ExtraDataPtr -1 of each message is a index to the EDP in EDP section. Click to see Network ID's
Text identifier |
12 |
single byte char array with text "EDP_SECTION" used to identify file type. please note the null terminator at the end |
EDP Size |
4 |
int indicating the length of the EDP |
EDP |
variable (see above) |
used to save the extra data bytes for networks such as Ethernet, Flexray, and CANFD |
...... |
variable (see above) |
EDP Size and EDP continue to repeat until Length of EDP Section is met. |
Version 0x104
This format is created by the Loggers and VSpy Stream to Disk.
Buffer of Messages |
VSBSpyMessage structures |
VSBSpyMessage structures |
EDP |
variable (see previous message's ExtraDataPtr) |
used to save the extra data bytes for networks such as Ethernet, Flexray, and CANFD |
...... |
variable |
Buffer of Message and EDP continue to repeat until Start Time of Collection. If you are reading the VSB file, simple continue to read until Buffer of Message size read not equal sizeof(VSBSpyMessage) |
Start Time of Collection |
struct icsspyMsgTime |
this is a comparison value between the system time stamp and the neoVI time stamp. |
NetWork ID
version 0x101
HSCAN |
0 |
MSCAN |
1 |
SWCAN |
2 |
LSFTCAN |
5 |
DEVICE |
8 |
HSCAN2 |
9 |
HSCAN3 |
10 |
LIN2 |
11 |
LIN3 |
12 |
LIN4 |
13 |
version 0x102 , 0x103, 0x104
DEVICE |
0 |
HSCAN |
1 |
MSCAN |
2 |
SWCAN |
3 |
LSFTCAN |
4 |
J1708 |
6 |
JVPW |
8 |
ISO |
9 |
ISO2 |
14 |
LIN |
16 |
ISO3 |
41 |
HSCAN2 |
42 |
HSCAN3 |
44 |
ISO4 |
47 |
LIN2 |
48 |
LIN3 |
49 |
LIN4 |
50 |
LIN5 |
84 |
MOST |
51 |
CGI |
53 |
HSCAN4 |
61 |
HSCAN5 |
62 |
SWCAN2 |
68 |
ETHERNET_DAQ |
69 |
FLEXRAY1A |
80 |
FLEXRAY1B |
81 |
FLEXRAY2A |
82 |
FLEXRAY2B |
83 |
FLEXRAY |
85 |
MOST25 |
90 |
MOST50 |
91 |
ETHERNET |
93 |
GMFSA |
94 |
TCP |
95 |
HSCAN6 |
96 |
HSCAN7 |
97 |
LIN6 |
98 |
LSFTCAN2 |
99 |
OP_ETHERNET1 |
17 |
OP_ETHERNET2 |
18 |
OP_ETHERNET3 |
19 |
OP_ETHERNET4 |
45 |
OP_ETHERNET5 |
46 |
OP_ETHERNET6 |
73 |
OP_ETHERNET7 |
75 |
OP_ETHERNET8 |
76 |
OP_ETHERNET9 |
77 |
OP_ETHERNET10 |
78 |
OP_ETHERNET11 |
79 |
OP_ETHERNET12 |
87 |
Example
Below is a C++ example of how to open a .vsb file (v102 & v103 & 104) and display the network messages (Ethernet, CANFD, and CAN) with some other useful information You can view the full C++ code or Download the full project from the links provided.
Reading File Specification
bool Messages::Read(char * sFileName)
{
unsigned long numEDP = 0;
m_pFile = fopen(sFileName, "rb");
if (m_pFile)
{
fSead( 0, SEEK_END);
int length = ftell(m_pFile); fSead( 0, SEEK_SET);
char id[6];
if (!fRead((char * )&id, 6) || memcmp(id, "icsbin", 6) != 0) {
printf("Invalid VSB file\n");
return false;
}
unsigned int fileversion;
if (!fRead((char *)&fileversion, 4)){ printf("Read Error\n");
return false;
}
else if (fileversion == 0x102) {
int EDPSize = ReadEDPSelction(); if (EDPSize == 0)
fSead( VSB_HEADERSIZE, SEEK_SET);
unsigned long numofmessages = ((length - (EDPSize + SIZEOFEDPSIZE)) - VSB_HEADERSIZE) / sizeof(icsSpyMessage); m_nMessages = numofmessages; if (numofmessages){
if(!ReadMessage(numofmessages, fileversion)){ printf("file was not read correctly \n");
return false;
}
}
else if (fileversion == 0x103) {
ReadEDPSelction(); unsigned long numofmessages = Read103Header(); m_nMessages = numofmessages; if (numofmessages){
if(!ReadMessage(numofmessages, fileversion)){ printf("file was not read correctly \n");
return false;
}
}
}
else if (fileversion == 0x104){ if(!Read104()){ printf("file was not read correctly \n");
return false;
}
}
else{
printf("%s is an unsupported VSB version!\n", sFileName);
return false;
}
fclose(m_pFile);
}
else
{
printf("Could not open %s to read!\n", sFileName);
return false;
}
return true;
}
Reading EDP Section
int Messages::ReadEDPSelction()
{
unsigned long edpsize;
bool bFixTimeStamp = false;
if (fRead((char *)&edpsize, SIZEOFEDPSIZE) && edpsize > 0) {
unsigned long tempEDPSize = edpsize;
static const char* EDP_SECTION = "EDP_SECTION";
char obItem [EDPSECTIONSTRINGSIZE]; if (fRead(obItem, EDPSECTIONSTRINGSIZE) && tempEDPSize >= EDPSECTIONSTRINGSIZE && strcmp(obItem, EDP_SECTION) == 0) {
tempEDPSize -= EDPSECTIONSTRINGSIZE;
m_pEDPSection = new char[tempEDPSize];
if (!fRead(m_pEDPSection, tempEDPSize)){ printf("invalid file read\n");
return 0;
}
char * edpPtr = m_pEDPSection;
while (tempEDPSize > 0) {
int edpLen = *(int*)edpPtr;
m_edps.push_back(std::pair<char*, int>(edpPtr + sizeof(int), edpLen)); tempEDPSize -= sizeof(int);
edpPtr += edpLen +sizeof(edpLen);
tempEDPSize -= edpLen;
}
return edpsize;
}
}
return 0;
}
Reading 0x103 File Info
unsigned long Messages::Read103Header()
{
unsigned long theNumOfMsgs;
size_t msgslength, currbuffptr, numalltime, commentlength, origbuffsize;
fRead((char *)&commentlength, 4); if (commentlength > 0)
fSead( (long)commentlength * 2, SEEK_CUR); fRead((char *)&msgslength, 4); fRead((char *)&origbuffsize, 4); fRead((char *)&currbuffptr, 4); fRead((char *)&numalltime, 4);
theNumOfMsgs = msgslength / sizeof(VSBSpyMessage);
return theNumOfMsgs;
}
Reading 0x102 and 0x103 Messages
bool Messages::ReadMessage(unsigned long theNumOfMsgs, unsigned int fileversion)
{
VSBSpyMessage * pMessageRead = new VSBSpyMessage();
m_pMessages = new icsSpyMessage[theNumOfMsgs];
bool firstMsg = true;
SpyMsgTime timeStampRead;
SpyMsgTime FirstMsgTime;
for(unsigned int i = 0; i < theNumOfMsgs; i++){ if(!fRead((char *)pMessageRead, sizeof(VSBSpyMessage))){ delete pMessageRead;
delete m_pMessages;
m_pMessages = NULL;
theNumOfMsgs = 0;
return false;
}
if (firstMsg) { FirstMsgTime.HardwareTimeStampID = m_pMessages[0].TimeStampHardwareID;
FirstMsgTime.HardwareTime1 = m_pMessages[0].TimeHardware;
FirstMsgTime.HardwareTime2 = m_pMessages[0].TimeHardware2;
FirstMsgTime.SystemTimeStampID = m_pMessages[0].TimeStampSystemID;
FirstMsgTime.SystemTime1 = m_pMessages[0].TimeSystem;
FirstMsgTime.SystemTime2 = m_pMessages[0].TimeSystem2;
firstMsg = false;
}
VSBMessageToNormal(&m_pMessages[i], pMessageRead);
bool clear = true;
if (pMessageRead->ExtraDataPtrEnabled && pMessageRead->iExtraDataPtr) {
if (pMessageRead->iExtraDataPtr >= 1 && pMessageRead->iExtraDataPtr <= m_edps.size())
{
int iEDPIndex = pMessageRead->iExtraDataPtr - 1; int payloadLength = m_edps[iEDPIndex].second;
m_pMessages[i].pExtraDataPtr = new pExtraDataPtrHandler(); ((pExtraDataPtrHandler *)(m_pMessages[i].pExtraDataPtr))->pExtraDataPtr = m_edps[iEDPIndex].first;
((pExtraDataPtrHandler *)(m_pMessages[i].pExtraDataPtr))->length = payloadLength;
clear = false;
}
}
if (clear)
{
m_pMessages[i].ColorID = 0; m_pMessages[i].pExtraDataPtr = 0; }
if (fileversion == 0x102) m_pMessages[i].TimeStampHardwareID |= 0x80;
}
if (!fRead((char *)&timeStampRead, sizeof(timeStampRead))) timeStampRead = FirstMsgTime; m_startTimeStamp = timeStampRead;
delete pMessageRead;
return true;
}
Reading 0x104
bool Messages::Read104(){
unsigned long EDPLength = 0, Edpsize = 0, numOfMessages = 0;
bool firstMsg = true;
SpyMsgTime timeStampRead;
SpyMsgTime FirstMsgTime;
VSBSpyMessage *pMessage = new VSBSpyMessage();
while (fRead((char *)pMessage, sizeof(VSBSpyMessage))) {
numOfMessages++;
if (pMessage->ExtraDataPtrEnabled && pMessage->iExtraDataPtr > 0) {
Edpsize += pMessage->iExtraDataPtr; fSead((unsigned int)pMessage->iExtraDataPtr, SEEK_CUR);
}
}
fSead( VSB_HEADERSIZE, SEEK_SET);
m_pMessages = new icsSpyMessage[numOfMessages];
for (unsigned int i = 0; i < numOfMessages; i++)
{
if (!fRead((char *)pMessage, sizeof(VSBSpyMessage)))
break;
if (firstMsg) {
FirstMsgTime.HardwareTimeStampID = pMessage[0].TimeStampHardwareID;
FirstMsgTime.HardwareTime1 = pMessage[0].TimeHardware;
FirstMsgTime.HardwareTime2 = pMessage[0].TimeHardware2;
FirstMsgTime.SystemTimeStampID = pMessage[0].TimeStampSystemID;
FirstMsgTime.SystemTime1 = pMessage[0].TimeSystem;
FirstMsgTime.SystemTime2 = pMessage[0].TimeSystem2;
firstMsg = false;
}
bool clear = true;
VSBMessageToNormal(&m_pMessages[i], pMessage);
if (pMessage->ExtraDataPtrEnabled && pMessage->iExtraDataPtr >= 1 ) {
EDPLength = pMessage->iExtraDataPtr;
char * pEDP = new char[EDPLength];
if(!fRead(pEDP, EDPLength))
return false; m_pMessages[i].pExtraDataPtr = new pExtraDataPtrHandler();
((pExtraDataPtrHandler *)(m_pMessages[i].pExtraDataPtr))->pExtraDataPtr = (void *)pEDP;
((pExtraDataPtrHandler *)(m_pMessages[i].pExtraDataPtr))->length = EDPLength;
clear = false;
}
if (clear) {
EDPLength = 0;
m_pMessages[i].ColorID = 0;
m_pMessages[i].pExtraDataPtr = 0;
}
}
if (!fRead((char *)&timeStampRead, sizeof(timeStampRead)))
timeStampRead = FirstMsgTime;
m_startTimeStamp = timeStampRead;
m_nMessages = numOfMessages;
return true;
}