⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trouble_code_reader.c

📁 国外一个非常经典的OBD2车辆检测的实例源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "globals.h"
#include "serial.h"
#include "options.h"
#include "custom_gui.h"
#include "error_handlers.h"
#include "trouble_code_reader.h"

#define MSG_READ_CODES    MSG_USER
#define MSG_CLEAR_CODES   MSG_USER+1
#define MSG_READY         MSG_USER+2

#define CRQ_NONE       0
#define NUM_OF_CODES   1
#define READ_CODES     2
#define READ_PENDING   3
#define CLEAR_CODES    4

#define FIELD_DELIMITER     '\t'
#define RECORD_DELIMITER    0xA

#define SIM_CODES_STRING   "43012507360455\n43114301960234\n43044302990357\n43C001C101C106"

#define NUM_OF_RETRIES   3

#define CLEAR_CODES_WARNING \
"This will reset the MIL and clear all emission-related diagnostic information, including:\n\n\
   - Diagnostic trouble codes\n\
   - Freeze frame data\n\
   - Oxygen sensor test data\n\
   - Status of system monitoring tests\n\
   - On-board monitoring tests results\n\
   - Distance travelled while MIL activated\n\
   - Number of warm-ups since DTCs cleared\n\
   - Distance travelled since DTCs cleared\n\
   - Engine run time while MIL activated\n\
   - Time since DTCs cleared\n\n\
Other manufacturer-specific \"clearing/resetting\" actions may occur. The loss of data may cause \
the vehicle to run poorly for a short period of time while the ECU recalibrates itself."

typedef struct TROUBLE_CODE
{
   char code[7];
   char *description;
   char *solution;
   int pending;
   struct TROUBLE_CODE *next;
} TROUBLE_CODE;

static char mfr_code_description[] = "Manufacturer-specific code.  Please refer to your vehicle's service manual for more information";
static char mfr_pending_code_description[] = "[Pending]\nManufacturer-specific code.  Please refer to your vehicle's service manual for more information";
static char code_no_description[] = "";
static char pending_code_no_description[] = "[Pending]";

static int num_of_codes_reported = 0;
static int current_code_index;
static int simulate = FALSE;
static int mil_is_on; // MIL is ON or OFF

static TROUBLE_CODE *trouble_codes = NULL;

static void add_trouble_code(const TROUBLE_CODE *);
static TROUBLE_CODE *get_trouble_code(int index);
static int get_number_of_codes();
static void clear_trouble_codes();

// procedure definitions:
static int tr_code_proc(int msg, DIALOG *d, int c);
static int mil_status_proc(int msg, DIALOG *d, int c);
static int mil_text_proc(int msg, DIALOG *d, int c);
static int simulate_proc(int msg, DIALOG *d, int c);
static int is_mfr_code(const char *code);
static int num_of_codes_proc(int msg, DIALOG *d, int c);
static int code_list_proc(int msg, DIALOG *d, int c);
static char *code_list_getter(int index, int *list_size);
static int read_tr_codes_proc(int msg, DIALOG *d, int c);
static int clear_codes_proc(int msg, DIALOG *d, int c);
static int tr_description_proc(int msg, DIALOG *d, int c);
static int tr_solution_proc(int msg, DIALOG *d, int c);
static int current_code_proc(int msg, DIALOG *d, int c);

// function definitions:
static void read_codes();
static void trouble_codes_simulator(int show);
static int handle_num_of_codes(char *);
static int handle_read_codes(char *, int);
static void populate_trouble_codes_list();
static void swap_codes(TROUBLE_CODE *, TROUBLE_CODE *);
static void handle_errors(int error, int operation);
static PACKFILE *file_handle(char code_letter);

static DIALOG read_codes_dialog[] =
{
   /* (proc)              (x)  (y)  (w)  (h)  (fg)    (bg)           (key) (flags) (d1) (d2) (dp)                                   (dp2) (dp3) */
   { d_clear_proc,        0,   0,   0,   0,   0,       C_WHITE,       0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { d_box_proc,          25,  25,  112, 24,  C_BLACK, C_DARK_GRAY,   0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { code_list_proc,      25,  96,  112, 208, C_BLACK, C_LIGHT_GRAY,  0,    0,      0,   0,   code_list_getter,                      NULL, NULL },
   { caption_proc,        81,  28,  54,  19,  C_WHITE, C_TRANSP,      0,    0,      0,   0,   "Current DTC",                         NULL, NULL },
   { d_box_proc,          25,  49,  112, 40,  C_BLACK, C_LIGHT_GRAY,  0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { current_code_proc,   81,  57,  54,  24,  C_BLACK, C_LIGHT_GRAY,  0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { d_box_proc,          25,  311, 112, 64,  C_BLACK, C_WHITE,       0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { num_of_codes_proc,   81,  319, 54,  24,  C_BLACK, C_WHITE,       0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { st_ctext_proc,       80,  351, 55,  20,  C_BLACK, C_TRANSP,      0,    0,      0,   0,   "DTCs",                                NULL, NULL },
   { d_box_proc,          25,  383, 112, 72,  C_BLACK, C_WHITE,       0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { mil_status_proc,     56,  390, 50,  30,  0,       0,             0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { mil_text_proc,       81,  430, 54,  23,  C_BLACK, C_WHITE,       0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { d_box_proc,          152, 25,  463, 24,  C_BLACK, C_DARK_GRAY,   0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { caption_proc,        383, 28,  230, 19,  C_WHITE, C_TRANSP,      0,    0,      0,   0,   "Diagnostic Trouble Code Definition",  NULL, NULL },
   { tr_description_proc, 152, 49,  463, 100, C_BLACK, C_LIGHT_GRAY,  0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { d_box_proc,          152, 164, 463, 25,  C_BLACK, C_DARK_GRAY,   0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { caption_proc,        383, 167, 230, 20,  C_WHITE, C_TRANSP,      0,    0,      0,   0,   "Possible Causes And Known Solutions", NULL, NULL },
   { tr_solution_proc,    152, 189, 463, 185, C_BLACK, C_LIGHT_GRAY,  0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { simulate_proc,       152, 408, 88,  16,  C_BLACK, C_WHITE,       0,    0,      1,   0,   "Simulate",                            NULL, NULL },
   { read_tr_codes_proc,  256, 408, 110, 48,  C_BLACK, C_GREEN,       'r',  D_EXIT, 0,   0,   "&Read",                               NULL, NULL },
   { clear_codes_proc,    381, 408, 110, 48,  C_BLACK, C_DARK_YELLOW, 'c',  D_EXIT, 0,   0,   "&Clear",                              NULL, NULL },
   { d_button_proc,       506, 408, 110, 48,  C_BLACK, C_GREEN,       'm',  D_EXIT, 0,   0,   "Main &Menu",                          NULL, NULL },
   { tr_code_proc,        0,   0,   0,   0,   0,     0,               0,    0,      0,   0,   NULL,                                  NULL, NULL },
   { NULL,                0,   0,   0,   0,   0,     0,               0,    0,      0,   0,   NULL,                                  NULL, NULL }
};

static DIALOG confirm_clear_dialog[] =
{
   /* (proc)             (x)  (y)  (w)  (h)  (fg)     (bg)           (key) (flags) (d1) (d2) (dp)                                 (dp2) (dp3) */
   { d_shadow_box_proc,  0,   0,   440, 460, C_BLACK, C_WHITE,       0,    0,      0,   0,   NULL,                                NULL, NULL },
   { d_shadow_box_proc,  0,   0,   440, 24,  C_BLACK, C_DARK_GRAY,   0,    0,      0,   0,   NULL,                                NULL, NULL },
   { caption_proc,       220, 2,   218, 19,  C_WHITE, C_TRANSP,      0,    0,      0,   0,   "Clear Trouble Codes",               NULL, NULL },
   { super_textbox_proc, 16,  32,  408, 332, C_BLACK, C_WHITE,       0,    0,      0,   0,   CLEAR_CODES_WARNING,                 NULL, NULL },
   { caption_proc,       220, 372, 204, 24,  C_RED,   C_TRANSP,      0,    0,      0,   0,   "Are you sure you want to do this?", NULL, NULL },
   { d_button_proc,      72,  408, 140, 35,  C_BLACK, C_GREEN,       'y',  D_EXIT, 0,   0,   "&Yes, I am sure",                   NULL, NULL },
   { d_button_proc,      228, 408, 140, 35,  C_BLACK, C_DARK_YELLOW, 'n',  D_EXIT, 0,   0,   "&No, cancel",                       NULL, NULL },
   { NULL,               0,   0,   0,   0,   0,       0,             0,    0,      0,   0,   NULL,                                NULL, NULL }
}; 


int display_trouble_codes()
{
   int ret;

   mil_is_on = FALSE; // reset MIL status
   num_of_codes_reported = 0;
   clear_trouble_codes();
   
   centre_dialog(confirm_clear_dialog);  // center the popup dialog

   if (comport.status == USER_IGNORED)
      comport.status = NOT_OPEN;

   ret = do_dialog(read_codes_dialog, -1);
   
   if (get_number_of_codes() > 0)    // if the structure is not empty,
      clear_trouble_codes();
      
   return ret;
}


void trouble_codes_simulator(int show)
{
   char buf[128];
   
   if (show)
   {
      strcpy(buf, SIM_CODES_STRING);
      process_response(NULL, buf);
      clear_trouble_codes();
      num_of_codes_reported = handle_read_codes(buf, FALSE);
      populate_trouble_codes_list();
      mil_is_on = TRUE;
   }
   else
   {
      clear_trouble_codes();
      num_of_codes_reported = 0;
      mil_is_on = FALSE;
   }

   broadcast_dialog_message(MSG_READY, 0);
}
      

int current_code_proc(int msg, DIALOG *d, int c)
{
   switch (msg)
   {
      case MSG_START:
         d->dp2 = datafile[ARIAL18_FONT].dat;
         d->dp = empty_string;
         break;

      case MSG_READY:
         if (get_number_of_codes() == 0)
            d->dp = empty_string;
         else
            d->dp = get_trouble_code(current_code_index)->code;

         return D_REDRAWME;
      
      case MSG_DRAW:
         rectfill(screen, d->x-d->w, d->y, d->x+d->w-1, d->y+d->h-1, d->bg);  // clear the element
         break;
   }
      
   return st_ctext_proc(msg, d, c);
}


int tr_description_proc(int msg, DIALOG *d, int c)   // procedure which displays a textbox
{
   TROUBLE_CODE *dtc;

   switch (msg)
   {
      case MSG_START:
         d->dp = empty_string;
         break;

      case MSG_READY:
         if (get_number_of_codes() == 0)
            d->dp = empty_string;
         else
         {
            if (!(dtc = get_trouble_code(current_code_index)))
               d->dp = empty_string;
            else
            {
               if (!(d->dp = dtc->description))
               {
                  if (is_mfr_code(dtc->code))
                     d->dp = (dtc->pending) ? mfr_pending_code_description : mfr_code_description;
                  else
                     d->dp = (dtc->pending) ? pending_code_no_description : code_no_description;
               }
            }
         }
         return D_REDRAWME;
   }
      
   return d_textbox_proc(msg, d, c);
}


int tr_solution_proc(int msg, DIALOG *d, int c)   // procedure which displays a textbox
{
   switch (msg)
   {
      case MSG_START:
         d->dp = empty_string;
         break;
      
      case MSG_READY:
         if (get_number_of_codes() == 0)
            d->dp = empty_string;
         else if(!(d->dp = get_trouble_code(current_code_index)->solution))
            d->dp = empty_string;
         return D_REDRAWME;
   }

   return d_textbox_proc(msg, d, c);
}


int num_of_codes_proc(int msg, DIALOG *d, int c)
{
   switch (msg)
   {
      case MSG_START:
         d->dp2 = datafile[ARIAL18_FONT].dat;
         if (!(d->dp = calloc(8, sizeof(char))))
            fatal_error("Could not allocate enough memory for num_of_codes_proc buffer");
         strcpy(d->dp, "0");
         break;

      case MSG_END:
         free(d->dp);
         break;
         
      case MSG_DRAW:
         rectfill(screen, d->x-d->w, d->y, d->x+d->w-1, d->y+d->h-1, d->bg);  // clear the element
         break;

      case MSG_READY:
         sprintf(d->dp, "%i", num_of_codes_reported);
         return D_REDRAWME;
   }
   
   return st_ctext_proc(msg, d, c);
}


int mil_status_proc(int msg, DIALOG *d, int c)
{
   switch (msg)
   {
      case MSG_START:
         d->dp = datafile[MIL_OFF_BMP].dat;
         break;

      case MSG_READY:
         if (mil_is_on)
            d->dp = datafile[MIL_ON_BMP].dat;
         else
            d->dp = datafile[MIL_OFF_BMP].dat;
            
         return D_REDRAWME;
   }
   
   return d_bitmap_proc(msg, d, c);
}


int mil_text_proc(int msg, DIALOG *d, int c)
{
   switch (msg)
   {
      case MSG_START:
         if (!(d->dp = calloc(16, sizeof(char))))
            fatal_error("Could not allocate enough memory for mil_text_proc buffer");
         strcpy(d->dp, "MIL is OFF");
         break;
         
      case MSG_END:
         free(d->dp);
         break;
         
      case MSG_DRAW:
         rectfill(screen, d->x-d->w, d->y, d->x+d->w-1, d->y+d->h-1, d->bg);  // clear the element
         break;
         
      case MSG_READY:
         if (mil_is_on)
            strcpy(d->dp, "MIL is ON");
         else
            strcpy(d->dp, "MIL is OFF");
      
         return D_REDRAWME;
   }
   
   return st_ctext_proc(msg, d, c);
}


int simulate_proc(int msg, DIALOG *d, int c)
{
   int ret;

   switch (msg)
   {
      case MSG_READ_CODES: case MSG_CLEAR_CODES:
         // if we are currently reading or clearing codes, and the button is enabled,
         if (!(d->flags & D_DISABLED))
         {
            d->flags |= D_DISABLED;     // disable the button
            return D_REDRAWME;
         }
         break;

      case MSG_READY:
         // if we're not reading or clearing codes, and the button is disabled,
         if (d->flags & D_DISABLED)
         {
            d->flags &= ~D_DISABLED;   // enable it
            return D_REDRAWME;
         }
         break;
   }
   
   ret = d_check_proc(msg, d, c);

   if ((d->flags & D_SELECTED) && (d->d2 == 0))
   {
      d->d2 = 1;
      simulate = TRUE;
      trouble_codes_simulator(TRUE);
   }
   else if (!(d->flags & D_SELECTED) && (d->d2 == 1))
   {
      d->d2 = 0;
      simulate = FALSE;
      trouble_codes_simulator(FALSE);
   }

   return ret;
}   


void read_codes()
{
   while (comport.status != READY)
   {
      if (alert("Port is not ready.", "Please check that you specified the correct port", "and that no other application is using it", "Configure &Port", "&Cancel", 'p', 'c') == 1)
         display_options(); // let the user choose correct settings
      else
         return;
   }

   clear_trouble_codes();
   num_of_codes_reported = 0;
   mil_is_on = FALSE;
   broadcast_dialog_message(MSG_READY, 0);
   broadcast_dialog_message(MSG_READ_CODES, 0);
}


int read_tr_codes_proc(int msg, DIALOG *d, int c)
{
   int ret;
   
   switch (msg)
   {
      case MSG_READ_CODES: case MSG_CLEAR_CODES:
         // if we are currently reading or clearing codes, and the button is enabled,
         if (!(d->flags & D_DISABLED))
         {
            d->flags |= D_DISABLED;     // disable the button
            return D_REDRAWME;
         }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -