/* This program will test the new code widget
** Test
Test
*/
#import datetime
#import "example.t"
#import testing code
#import kvDevice
#import extern IoEvent kvmlib
variables {
const int id = 0; //CAN Channel ID
}
void MyFunc() {
printf("Channel ID is %d", id);
break;
}
on start {
MyFunc();
}
import datetime
import testing code
import kvDevice
import extern IoEvent kvmlib
variables {
const int id = 0; //CAN Channel ID
}
on start {
printf("Channel ID is %d", id);
}
#include "kwp2000.inc"
variables {
// Start "addresses" for the various operations
const int CONNECT = 0x100;
const int PROGRAMMING = 0x200;
const int READ_DTC = 0x300;
const int DISCONNECT = 0x400;
const int IDLE = 0x000; // Not executing
// From host
char xml_file_name[13];
char FingerPrintSerial[16];
char FingerPrintDate[8];
// From XML file
char VIN[32];
char SpeedLimit[16];
char SpeedLimit2[16];
// Execution engine
int pc = IDLE;
int dpc = 0;
char error_text[80];
}
envvar {
// Outgoing
char text[4095];
// Incoming
int connect;
char programming[32];
char xmlfilename[13];
int readDTC;
int disconnect;
}
void Report(const char msg[]);
int HandleError(int result, const char text[]);
void ReportECUInfo(const byte data[]);
void DTCsToText(char outbuf[], const byte data[]);
int ReadValuesFromXMLFile(void);
void HaltExecution (void)
{
pc = IDLE;
}
// qqq If we can find a nice way to break out the four modes into separate
// functions, that would likely be better.
// Continue execution of current communication operation.
// Called when the last sub-operation was successfully completed.
//
void Execute (const byte data[])
{
static char buf[4096];
static int estab_length, lstab_length;
switch (pc++) {
// ************* Connect ***************
case CONNECT:
HandleError(kwp2000SendRequest(SetStandardSession),
"set session");
break;
case 1 + CONNECT:
HandleError(kwp2000SendRequest(ReadECUIdentification),
"read ECU info");
break;
case 2 + CONNECT:
ReportECUInfo(data);
HaltExecution();
break;
// ************* Program ***************
case PROGRAMMING:
if (HandleError(ReadValuesFromXMLFile(),
"read XML file") >= 0) {
// qqq Programming session didn't work, so go with adjustment instead.
HandleError(kwp2000SendRequest(SetAdjustmentSession),
"set adjustment session");
}
break;
case 1 + PROGRAMMING:
HandleError(kwp2000SendRequest(ReadECUIdentificationScalingTable),
"read ECU ID scaling table");
break;
case 2 + PROGRAMMING:
estab_length = data.count;
buf[0, estab_length] = data;
HandleError(kwp2000WriteByCommonIdBytes(COMMON_ID_SERIAL, FingerPrintSerial,
buf[0, estab_length]),
"write finger print serial");
break;
case 3 + PROGRAMMING:
HandleError(kwp2000WriteByCommonIdBytes(COMMON_ID_DATE, FingerPrintDate,
buf[0, estab_length]),
"write finger print data");
break;
case 4 + PROGRAMMING:
HandleError(kwp2000SendRequest(ReadLocalIdentifierScalingTable),
"read local ID scaling table");
break;
case 5 + PROGRAMMING:
lstab_length = data.count;
buf[estab_length, lstab_length] = data;
HandleError(kwp2000WriteByLocalIdFloat(LOCAL_ID_SPEEDLIMIT, atof(SpeedLimit),
buf[estab_length, lstab_length]),
"scale and write SpeedLimit");
break;
case 6 + PROGRAMMING:
HandleError(kwp2000WriteByLocalIdFloat(LOCAL_ID_SPEEDLIMIT2, atof(SpeedLimit2),
buf[estab_length, lstab_length]),
"scale and write SpeedLimit2");
break;
case 7 + PROGRAMMING:
HandleError(kwp2000WriteByCommonIdBytes(COMMON_ID_VIN, VIN,
buf[0, estab_length]),
"write VIN number");
break;
case 8 + PROGRAMMING:
HandleError(kwp2000SendRequest(ResetECU),
"reset ECU");
break;
case 9 + PROGRAMMING:
Report("Programming OK.\n");
HaltExecution();
break;
// ************** Read DTCs **************
case READ_DTC:
HandleError(kwp2000SendRequest(ReadDTCs),
"read DTCs");
break;
case 1 + READ_DTC:
strcpy(buf, "DTCs set before EraseDTC: ");
DTCsToText(buf, data);
// qqq What about ClearDiagnosticInformation?
HandleError(kwp2000SendRequest(ClearDTCs),
"clear DTCs");
break;
case 2 + READ_DTC:
HandleError(kwp2000SendRequest(ReadDTCs),
"reread DTCs");
break;
case 3 + READ_DTC:
strcat(buf, "DTCs set after EraseDTC: ");
DTCsToText(buf, data);
Report(buf);
HaltExecution();
break;
// ************** Disconnect **************
case DISCONNECT:
HandleError(kwp2000SendRequest(ResetECU),
"reset ECU");
break;
case 1 + DISCONNECT:
Report("Disconnected.\n");
HaltExecution();
break;
// ************** Idle **************
case IDLE:
// This should never happen!
HaltExecution();
}
}
void StartOperation (int operation)
{
// If we can't switch mode now, defer for later.
if (pc != IDLE) {
dpc = operation;
return;
}
pc = operation;
Execute("");
}
int HandleError (int result, const char text[])
{
if (result < 0) {
char buf[80];
sprintf(buf, "Failed to %s (%d).\n", text, result);
Report(buf);
HaltExecution();
} else {
// Remember for use at callback failure.
error_text = text;
}
return result;
}
// Called on completed receive from the kwp2000 library.
void kwp2000CallbackHandleResponse (int response, const byte data[])
{
char buf[200];
switch (response) {
case RESPONSE_POSITIVE:
Execute(data);
break;
// ************* Error reporting ***************
case RESPONSE_NEGATIVE:
sprintf(buf, "Operation \"%s\" failed. Service 0x%02x: ",
error_text, data[1]);
kwp2000AppendNegativeResponseText(buf, data[2]);
strcat(buf, "\n");
Report(buf);
HaltExecution();
break;
case RESPONSE_TIMEOUT:
sprintf(buf, "Operation \"%s\" failed. No response from ECU.\n", error_text);
Report(buf);
HaltExecution();
break;
case RESPONSE_BAD:
sprintf(buf, "Operation \"%s\" failed. Bad response from ECU.\n", error_text);
Report(buf);
HaltExecution();
break;
}
if ((pc == IDLE) && dpc) {
StartOperation(dpc);
dpc = 0;
}
}
on start {
canSetBitrate(0, canBITRATE_250K);
canSetBusOutputControl(0, canDRIVER_NORMAL);
canBusOn(0);
if (kwp2000Init(0x11, 0xF1) < 0) {
// qqq Stop script?
Report("Failed to initialize kwp2000 library.\n");
}
}
on exception {
Report("**Exception**\n");
}
on stop {
kwp2000ShutDown();
canBusOff(0);
}
// Commands from the host
on envvar connect {
StartOperation(CONNECT);
}
on envvar programming {
char finger_print[32];
envvarGetValue(programming, finger_print);
FingerPrintDate = finger_print[0, 6];
FingerPrintSerial = finger_print[6, 10];
envvarGetValue(xmlfilename, xml_file_name);
StartOperation(PROGRAMMING);
}
on envvar readDTC {
StartOperation(READ_DTC);
}
on envvar disconnect {
StartOperation(DISCONNECT);
}
int ReadValuesFromXMLFile (void)
{
XmlHandle xi;
if (xmlOpen(xi, xml_file_name) < 0) {
return -1;
}
int ret = 0;
if (xmlGet(xi, SpeedLimit, "VehicleData", "Parameters", "SpeedLimit") < 0) {
ret--;
}
if (xmlGet(xi, SpeedLimit2, "VehicleData", "Parameters", "SpeedLimit2") < 0) {
ret--;
}
if (xmlGet(xi, VIN, "VehicleData", "VehicleID", "VINnumber") < 0) {
ret--;
}
xmlClose(xi);
return ret;
}
void Report (const char msg[])
{
envvarSetValue(text, msg);
printf("---------------\n%s---------------\n", msg);
}
void DTCsToText (char outbuf[], const byte data[])
{
int count = data[0];
if (count == 0) {
strcat(outbuf, "none\n");
return;
}
sprintf(outbuf + strlen(outbuf), "%d\n", count);
for(int i = 0; i < count; i++) {
kwp2000AppendDTCDescription(outbuf, data[1 + i * 3, 3]);
strcat(outbuf, " ");
}
strcat(outbuf, "\n");
}
void ReportECUInfo (const byte data[])
{
char buf[4096];
strcpy(buf, "ECUSparePartNumber: ");
strcat(buf, data[0, 12]);
strcat(buf, "\nECUSoftwareNumber: ");
strcat(buf, data[12, 12]);
strcat(buf, "\nECUVersionNumber: ");
strcat(buf, data[24, 9]);
strcat(buf, "\nECUManufacturer: ");
strcat(buf, data[33, 32]);
strcat(buf, "\nECUManufacturingDate: ");
strcat(buf, data[65, 6]);
strcat(buf, "\nVIN: ");
strcat(buf, data[71, 17]);
strcat(buf, "\nECUHardwareNumber: ");
strcat(buf, data[88, 12]);
strcat(buf, "\nSystemName: ");
strcat(buf, data[100, 4]);
strcat(buf, "\nTesterSerialNumber: ");
strcat(buf, data[104, 10]);
strcat(buf, "\nProgrammingDate: ");
strcat(buf, data[114, 6]);
strcat(buf, "\nScaniaECUBootProgramNumber: ");
strcat(buf, data[120, 7]);
strcat(buf, "\nScaniaECUHardwareWithoutBootNumber: ");
strcat(buf, data[127, 12]);
strcat(buf, "\nServiceToolECUDiagnosticNumber: ");
strcat(buf, data[139, 6]);
strcat(buf, "\nApplicationInfoString: ");
strcat(buf, data[145, 6]);
strcat(buf, "\n");
Report(buf);
}
// ********* Remove these later
on key 'c' {
StartOperation(CONNECT);
}
on key 'f' {
FileHandle f;
fileOpen(f, "xmlfile");
filePuts(f, "<VehicleData>\n");
filePuts(f, " <VehicleID>\n");
filePuts(f, " <VINnumber>YS2P4X20001234567</VINnumber>\n");
filePuts(f, " </VehicleID>\n");
filePuts(f, " <Parameters>\n");
filePuts(f, " <SpeedLimit>72.8</SpeedLimit>\n");
filePuts(f, " <SpeedLimit2>25</SpeedLimit2>\n");
filePuts(f, " </Parameters>\n");
filePuts(f, "</VehicleData>\n");
fileClose(f);
}
on key 'p' {
strcpy(FingerPrintSerial, "0123456789");
strcpy(FingerPrintDate, "080908");
strcpy(xml_file_name, "xmlfile");
StartOperation(PROGRAMMING);
}
on key 't' {
StartOperation(READ_DTC);
}
on key 'd' {
StartOperation(DISCONNECT);
}
on key 'o' {
byte data[4] = {0x01, 0x17, 0xFF, 0xFF};
kwp2000SendRequest(data);
}
// qqq This is for testing
on key 's' { // Read SpeedLimit
byte buf[3] = {1, SERVICE_READ_DATA_BY_LOCAL_ID, LOCAL_ID_SPEEDLIMIT};
kwp2000SendRequest(buf);
}
on key 'S' { // Read SpeedLimit2
byte buf[3] = {1, SERVICE_READ_DATA_BY_LOCAL_ID, LOCAL_ID_SPEEDLIMIT2};
kwp2000SendRequest(buf);
}