// uds_zlgcan_wrap_test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <memory>
#include <thread>
#include "../uds_zlgcan_wrap/uds_zlgcan_wrap.h"

int _tmain(int argc, _TCHAR* argv[])
{
    DEVICE_HANDLE hDev = ZCAN_OpenDevice(ZCAN_CANFDNET_TCP, 0, 0);
    if (INVALID_DEVICE_HANDLE == hDev) {
        printf("Open device failed! \n");
        return 0;
    }

    ZCAN_CHANNEL_INIT_CONFIG cfg;
    memset(&cfg, 0, sizeof(cfg));
    cfg.can_type = TYPE_CANFD;
    cfg.can.mode = 0;
    CHANNEL_HANDLE hChannel = ZCAN_InitCAN(hDev, 0, &cfg);
    if (INVALID_CHANNEL_HANDLE == hChannel) {
        printf("Init can failed! \n");
        return 0;
    }

    // TCP客户端
    ZCAN_SetValue(hDev, "0/work_mode", "0");
    ZCAN_SetValue(hDev, "0/ip", "127.0.0.1");
    ZCAN_SetValue(hDev, "0/work_port", "4001");

    if (ZCAN_StartCAN(hChannel) != STATUS_OK) {
        printf("Start can failed! \n");
        return 0;
    }

    ZUDS_HANDLE hUds = ZUDS_WRAP_Init(hChannel, 1);
    if (hUds == ZUDS_INVALID_HANDLE) {
        printf("ZUDS_WRAP_Init failed! \n");
        ZCAN_CloseDevice(hDev);
        return 0;
    }

    ZUDS_ISO15765_PARAM tp;
    tp.block_size = 0;
    tp.fill_byte = 0x00;
    tp.local_st_min = 0;
    tp.is_modify_ecu_st_min = 0;
    tp.remote_st_min = 0;
    tp.frame_type = 0;
    tp.version = VERSION_1;
    tp.max_data_len = VERSION_0 == tp.version ? 8 : 64; 
    ZUDS_WRAP_SetParam(hUds, PARAM_TYPE_ISO15765, &tp);
    ZUDS_SESSION_PARAM sparam;
    sparam.enhanced_timeout = 3000;
    sparam.timeout = 3000;
    ZUDS_WRAP_SetParam(hUds, PARAM_TYPE_SESSION, &sparam);

#if 0
    ZUDS_TESTER_PRESENT_PARAM heartParam;
    heartParam.addr = 0x700;
    heartParam.cycle = 1000;
    heartParam.suppress_response = 1;
    ZUDS_WRAP_SetTesterPresent(hUds, true, &heartParam);
#endif

    bool stopRecv = false;
    auto thd = std::thread([&stopRecv, &hChannel, &hUds](){
        ZUDS_FRAME frame;
        ZCAN_Receive_Data can_data[100];
        ZCAN_ReceiveFD_Data canfd_data[100];
        bool hasData = false;
        int len = 0;

        while (!stopRecv) {
            hasData = false;
            len = 0;
            len = ZCAN_Receive(hChannel, can_data, _countof(can_data), 0);
            if (len > 0)
            {
                hasData = true;
                ZUDS_WRAP_OnReceiveCAN(hUds, can_data, len);
                printf("recv %d can frame \n", len);
            }
            len = 0;
            len = ZCAN_ReceiveFD(hChannel, canfd_data, _countof(canfd_data), 0);
            if (len > 0)
            {
                hasData = true;
                ZUDS_WRAP_OnReceiveCANFD(hUds, canfd_data, len);
                printf("recv %d canfd frame \n", len);
            }
            if (!hasData)
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(1));
            }
        }
    });

    ZUDS_WRAP_REQUEST_PAR req;
    memset(&req, 0, sizeof(req));
    req.src_addr = 0x700;
    req.dst_addr = 0x748;
    req.suppress_response = 0;

    uint8 reqData[128];
    reqData[0] = 0x19;
    reqData[1] = 0x0A;

    ZUDS_WRAP_RESPONSE_PAR resp;
    uint8 respData[1024];
    memset(respData, 0, sizeof(respData));

    printf("发送UDS请求\n");
    uint32 respDataLen = ZUDS_WRAP_Request(hUds, &req, reqData, 2, &resp, respData, sizeof(respData));

    switch (resp.status)
    {
    case ZUDS_ERROR_OK:
        if (RT_POSITIVE == resp.type) // 积极响应
        {
            printf("积极响应: ");
            for (uint32 i = 0; i < respDataLen; ++i)
            {
                printf("%02X ", respData[i]);
            }
            printf("\n");
        }
        else // 消极响应
        {
            printf("消极响应:");
            for (uint32 i = 0; i < respDataLen; ++i)
            {
                printf("%02X ", respData[i]);
            }
            printf("\n");
        }
        break;
    case ZUDS_ERROR_TIMEOUT:
        printf("响应超时 \n");
        break;
    case ZUDS_ERROR_TRANSPORT:
        printf("发送帧数据失败 \n");
        break;
    case ZUDS_ERROR_CANCEL:
        printf("请求中止 \n");
        break;
    case ZUDS_ERROR_SUPPRESS_RESPONSE:
        printf("抑制响应 \n");
        break;
    default:
        printf("其他错误 \n");
        break;
    }

    stopRecv = true;
    thd.join();

    ZUDS_WRAP_Release(hUds);
    ZCAN_CloseDevice(hDev);

    system("pause");
	return 0;
}

