package com.tsi.comm.consumer.kafka;

import com.tsi.common.utils.SysUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.listener.MessageListener;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;

@Slf4j
@AllArgsConstructor
public class KafkaConsumerWorker implements MessageListener<String, byte[]> {

    private final String topic;
    private final HashSet<String> keyValues;

    @Override
    public void onMessage(ConsumerRecord<String, byte[]> record) {
        if (!this.keyValues.contains(record.key())) {
            return;
        }

        log.info("onMessage: Topic: {}, Key: {}, {} Bytes. {}",
                this.topic, record.key(), record.value().length, SysUtils.byteArrayToHex(record.value()));

        byte cpuVersion = 0x00;
        byte[] buffer = record.value();
        int idx = 0;
        int tail = 0;
        if ("cvim-raw".equals(this.topic)) {
            //"cvim"
            idx = 27 + 6;
            tail = -2;
            int stx1    = buffer[27];
            int stx2    = buffer[28];
            int length  = ((buffer[29] & 0xFF) << 8) | (buffer[30] & 0xFF);
            int opCode  = buffer[31];
            cpuVersion = buffer[32];
        }
        else if ("topic-for-ssd-test".equals(this.topic)) {
            //"test"
            int stx1    = buffer[idx++];
            int stx2    = buffer[idx++];
            int length  = ((buffer[idx++] & 0xFF) << 8) | (buffer[idx++] & 0xFF);
            int opCode  = buffer[idx++];
            cpuVersion = buffer[idx++];
            log.info("STX1: {}, STX2: {}, Length: {}, OpCode: {}, Version: {}, Idx: {}",
                    stx1, stx2, length, opCode, cpuVersion, idx);
            //idx = 6;
            tail = -2;
        }
        displayPacket(record.key(), record.value(), idx, tail, cpuVersion);
    }

    public static void displayPacket(String topicKey, byte[] buffer, int start, int tail, byte cpuVersion) {
        int idx = start;
//        int stx1    = buffer[idx++];
//        int stx2    = buffer[idx++];
//        int length  = ((buffer[idx++] & 0xFF) << 8) | (buffer[idx++] & 0xFF);
//        int opCode  = buffer[idx++];
//        int version = buffer[idx++];
        long nodeId = ((long) (buffer[idx++] & 0xFF) << 24) | ((buffer[idx++] & 0xFF) << 16) | ((buffer[idx++] & 0xFF) << 8) | (buffer[idx++] & 0xFF);
//        log.info("STX1: {}, STX2: {}, LENTH: {}, OpCode: {}, Version: {}, NodeId: {}", stx1, stx2, length, opCode, version, nodeId);

        log.info("NodeId: {}, {}", topicKey, nodeId);

        int status  = buffer[idx++];
        int error   = buffer[idx++];
        int counter = (int)(buffer[idx++] & 0xFF);                //주기 카운터, 초
        int stts    = buffer[idx++];
        long localTime = ((long) (buffer[idx++] & 0xFF) << 24) | ((buffer[idx++] & 0xFF) << 16) | ((buffer[idx++] & 0xFF) << 8) | (buffer[idx++] & 0xFF);

        int manual  = ((status     ) & 0x01);       //수동, 1: 이상, 0: 정상
        int blink   = ((status >> 1) & 0x01);       //점멸, 1: 점멸, 0: 정상
        int turnOff = ((status >> 2) & 0x01);       //소등, 1: 소등, 0: 정상
        int sensing = ((status >> 3) & 0x01);       //감응, 1: 감응, 0: 정상
        int trans   = ((status >> 4) & 0x01);       //전이, 1: 전이중, 0: 전이완료
        int ppc     = ((status >> 5) & 0x01);       //우선신호(PPC): 1: 서비스 중(In Service), 0: Not in Service ==> R28
        int hold    = ((status >> 6) & 0x01);       //현시유지: 1: 유지, 0: 정상 ==> R28

        int conflict   = ((error     ) & 0x01);     //모순 이상,      1 : 이상, 0 : 정상
        int centerComm = ((error >> 1) & 0x01);     //센터 통신 이상, 1: 센터 통신이상, 0 : 정상
        int scuComm    = ((error >> 2) & 0x01);     //SCU 통신 이상,  1: MCU <--> SCU 통신 이상, 0: 정상

        int statusCount = ((stts)      & 0x7F);     //총 신호상태정보의 개수, N 개
        int splitFlag   = ((stts >> 7) & 0x01);     //데이터를 분할하여 전송할 경우 마지막 정보임을 나타내는 플래그(분할 패킷의 처음과 중간:0, 단일 또는 마지막 패킷:1)

        Date date = new java.util.Date(localTime * 1000L);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
        String signalTime = sdf.format(date);

        log.info("   LocalTime: ({})", signalTime);
        log.info("  SystemTime: ({})", SysUtils.getSysTimeStr());
        log.info("      STATUS: 전이({}), 감응({}), 소등({}), 점멸({}), 수동({}), PPC({}), HOLD({}) - (1:전이중, 0:전이완료... 1:상태, 0:정상)",
                trans, sensing, turnOff, blink, manual, ppc, hold);
        log.info("       ERROR: SCU통신({}), 센터통신({}), 모순({}) - (1: 이상, 0: 정상)",
                scuComm, centerComm, conflict);
        log.info("CycleCounter: {} sec.", counter);
        log.info("     Signals: {} EA, DataSplit({}) - (0:First/Middle, 1:Single/Last)", statusCount, splitFlag);

//typedef struct _tsc_cvim_hdr_s
//{
//    uint8_t manual      : 1;    /* 수동, 1: 이상, 0: 정상 */
//    uint8_t blink       : 1;    /* 점멸, 1: 점멸, 0: 정상 */
//    uint8_t turnOff     : 1;    /* 소등, 1: 소등, 0: 정상 */
//    uint8_t response    : 1;    /* 감응, 1: 감응, 0: 정상 */
//    uint8_t trans       : 1;    /* 전이, 1: 전이중, 0: 전이완료 */
//    uint8_t byte1Res0   : 3;    /* 예약, bit 7 ~ 5 */
//
//    uint8_t conflict    : 1;    /* 모순 이상, 1 : 이상, 0 : 정상 */
//    uint8_t centerComm  : 1;    /* 센터 통신 이상, 1: 센터 통신이상, 0 : 정상 */
//    uint8_t scuComm     : 1;    /* SCU 통신 이상,  1: MCU <--> SCU 통신 이상, 0: 정상 */
//    uint8_t byte2Res0   : 5;    /* 예약, bit 7 ~ 3 */
//
//    uint8_t cycleCounter;       /* 주기 카운터, 초 */
//
//    uint8_t sttsCount   : 7;    /* 총 신호상태정보의 개수, N 개 */
//    uint8_t splitFlag   : 1;    /* 데이터를 분할하여 전송할 경우 마지막 정보임을 나타내는 플래그(분할 패킷의 처음과 중간:0, 단일 또는 마지막 패킷:1) */
//
//    uint8_t currTime[4];        /* 현재시간, time_t형, Big Endian */
//} tsc_cvim_hdr_t, *ptsc_cvim_hdr_t;

        final int SIGNAL_STATUS_SIZE = 5;
        boolean isR28 = false;
        int remainLength = buffer.length - idx + tail;
        if (statusCount * SIGNAL_STATUS_SIZE != remainLength) {
            if ((statusCount * SIGNAL_STATUS_SIZE != remainLength-1)) {
                log.error("Signal Status Data length error: {} EA, {}, {}", statusCount, statusCount * SIGNAL_STATUS_SIZE, remainLength);
                return;
            }
            else {
                isR28 = true;
            }
        }
        if (isR28) {
            byte cpuComp = buffer[buffer.length - 1 + tail];   // CRC 2 Bytes
            if (tail == 0) {
                // Topic 이 node 인경우 패킷 헤더 정보가 없다.
                log.info(" CPU Company: {}.", String.format("0x%02X", cpuComp));
            }
            else {
                log.info(" CPU Company: {}. Version: {}", String.format("0x%02X", cpuComp), String.format("R%d", cpuVersion));
            }
        }

        log.info("SEQ\t신호등정보\t방향\t시간정보신뢰성\t보행자   \t보행/감응\t비보호신호\t신호등상태\t표출\t잔여\t방향코드");
        for (int ii = 0; ii < statusCount; ii++) {
            int dirInfo   = buffer[idx++] & 0xFF;
            int sttsInfo  = buffer[idx++] & 0xFF;
            int displayTm = buffer[idx++] & 0xFF;
            int remainTm  = buffer[idx++] & 0xFF;
            int dirCode   = buffer[idx++] & 0xFF;

            int dirAdd     = ((dirInfo) & 0x0F);        //3 ~ 0, 방향추가정보, 해당 방향에 연등지 없음(0), 해당 방향의 첫번째 연등지(1), 해당 방향의 두번째 연등지(2)
            int lightsType = ((dirInfo >> 4) & 0x0F);   //7 ~ 4, 신호등 정보, ■ 미지정(0), 직진(1), 좌회전(2), 보행자(3), 자전거(4), 우회전(5), 버스(6), 유턴(7)

            int lighting   = ((sttsInfo     ) & 0x07);  //2 ~ 0, 신호등 상태, ■ 소등(0), 적색점등(1), 황색점등(2), 녹색점등(3), 적색점멸(4), 황색점멸(5), 녹색점멸(6)
            int unprotect  = ((sttsInfo >> 3) & 0x01);  //3, 비보호 상태, ■ 신호등 정보 유턴/좌회전에 대한 비보호 여부, ■ 비보호 아님(0), 비보호(1)
            int walkerExt  = ((sttsInfo >> 5) & 0x01);  //5, 보행연장/차량감응제어(0: 없음, 1: 보행신호-연장중 또는 차량신호-감응제어중
            int walkerPush = ((sttsInfo >> 6) & 0x01);  //6, 보행자(푸쉬 또는 자동검지), ■ 없음(0), 버튼 눌림 or 자동검지(1)
            int timeFlag   = ((sttsInfo >> 7) & 0x01);  //7, 시간 정보 신뢰성, ■ 고정신호시간(0), 가변신호시간(1)

            String plightInfo;
            switch (lightsType)
            {
                case 0: plightInfo = "미지정(0)"; break;
                case 1: plightInfo = "직진(1)  "; break;
                case 2: plightInfo = "좌회전(2)"; break;
                case 3: plightInfo = "보행자(3)"; break;
                case 4: plightInfo = "자전거(4)"; break;
                case 5: plightInfo = "우회전(5)"; break;
                case 6: plightInfo = "버스(6)  "; break;
                case 7: plightInfo = "유턴(7)  "; break;
                default: plightInfo = "XXX(" + lightsType + ")"; break;
            }
            String ptimeFlag;
            switch (timeFlag)
            {
                case 0: ptimeFlag = "고정신호(0)"; break;
                case 1: ptimeFlag = "가변신호(1)"; break;
                default: ptimeFlag = "XXX(" + timeFlag + ")"; break;
            }
            String pwalkerExt;
            switch (walkerExt)
            {
                case 0: pwalkerExt = "없음(0)    "; break;
                case 1: pwalkerExt = "연장/감응(1)"; break;
                default: pwalkerExt = "XXX(" + walkerExt + ")"; break;
            }
            String pwalkerPush;
            switch (walkerPush)
            {
                case 0: pwalkerPush = "없음(0)    "; break;
                case 1: pwalkerPush = "자동검지(1)"; break;
                default: pwalkerPush = "XXX(" + walkerPush + ")"; break;
            }
            String punprotect;
            switch (unprotect)
            {
                case 0: punprotect = "아님(0)  "; break;
                case 1: punprotect = "비보호(1)"; break;
                default: punprotect = "XXX(" + unprotect + ")"; break;
            }
            String plighting;
            switch (lighting)
            {
                case 0: plighting = "소등(0)    "; break;
                case 1: plighting = "적색점등(1)"; break;
                case 2: plighting = "황색점등(2)"; break;
                case 3: plighting = "녹색점등(3)"; break;
                case 4: plighting = "적색점멸(4)"; break;
                case 5: plighting = "황색점멸(5)"; break;
                case 6: plighting = "녹색점멸(6)"; break;
                default: plighting = "XXX(" + lighting + ")"; break;
            }
            log.info("{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
                    String.format("%3d", ii),
                    plightInfo,
                    dirAdd,
                    ptimeFlag,
                    pwalkerPush,
                    pwalkerExt,
                    punprotect,
                    plighting,
                    displayTm,
                    remainTm,
                    dirCode);
        }
//        typedef struct _tsc_cvim_stts_s
//        {
//            uint8_t dirAdd      : 4;    /* 3 ~ 0, 방향추가정보, 해당 방향에 연등지 없음(0), 해당 방향의 첫번째 연등지(1), 해당 방향의 두번째 연등지(2) */
//            uint8_t lightInfo   : 4;    /* 7 ~ 4, 신호등 정보, ■ 미지정(0), 직진(1), 좌회전(2), 보행자(3), 자전거(4), 우회전(5), 버스(6), 유턴(7) */
//
//            uint8_t lighting    : 3;    /* 2 ~ 0, 신호등 상태, ■ 소등(0), 적색점등(1), 황색점등(2), 녹색점등(3), 적색점멸(4), 황색점멸(5), 녹색점멸(6) */
//            uint8_t unprotect   : 1;    /* 3, 비보호 상태, ■ 신호등 정보 유턴/좌회전에 대한 비보호 여부, ■ 비보호 아님(0), 비보호(1) */
//            uint8_t Reserved0   : 2;    /* 5 ~ 4, 예비, ■ 예비 */
//            uint8_t walkerPush  : 1;    /* 6, 보행자(푸쉬 또는 자동검지), ■ 없음(0), 버튼 눌림 or 자동검지(1) */
//            uint8_t timeFlag    : 1;    /* 7, 시간 정보 신뢰성, ■ 고정신호시간(0), 가변신호시간(1) */
//
//            uint8_t displayTm;          /* 표출 시간, ■ 초 */
//            uint8_t remainTm;           /* 잔여 시간, ■ 초 */
//            uint8_t dirCode;            /* 방향 코드, ■ 출력지정 테이블에 지정된 방향코드 */
//        } tsc_cvim_stts_t, *ptsc_cvim_stts_t;

    }

//    public static void displayPacket(String topicKey, byte[] buffer, int start) {
//        int idx = start;
////        int stx1    = buffer[idx++];
////        int stx2    = buffer[idx++];
////        int length  = ((buffer[idx++] & 0xFF) << 8) | (buffer[idx++] & 0xFF);
////        int opCode  = buffer[idx++];
////        int version = buffer[idx++];
//        long nodeId = ((long) (buffer[idx++] & 0xFF) << 24) | ((buffer[idx++] & 0xFF) << 16) | ((buffer[idx++] & 0xFF) << 8) | (buffer[idx++] & 0xFF);
////        log.info("STX1: {}, STX2: {}, LENTH: {}, OpCode: {}, Version: {}, NodeId: {}", stx1, stx2, length, opCode, version, nodeId);
//
//        log.info("NodeId: {}, {}", topicKey, nodeId);
//
//        int status  = buffer[idx++];
//        int error   = buffer[idx++];
//        int counter = buffer[idx++];                //주기 카운터, 초
//        int stts    = buffer[idx++];
//        long localTime = ((long) (buffer[idx++] & 0xFF) << 24) | ((buffer[idx++] & 0xFF) << 16) | ((buffer[idx++] & 0xFF) << 8) | (buffer[idx++] & 0xFF);
//
//        int manual  = ((status     ) & 0x01);       //수동, 1: 이상, 0: 정상
//        int blink   = ((status >> 1) & 0x01);       //점멸, 1: 점멸, 0: 정상
//        int turnOff = ((status >> 2) & 0x01);       //소등, 1: 소등, 0: 정상
//        int sensing = ((status >> 3) & 0x01);       //감응, 1: 감응, 0: 정상
//        int trans   = ((status >> 4) & 0x01);       //전이, 1: 전이중, 0: 전이완료
//
//        int conflict   = ((error     ) & 0x01);     //모순 이상,      1 : 이상, 0 : 정상
//        int centerComm = ((error >> 1) & 0x01);     //센터 통신 이상, 1: 센터 통신이상, 0 : 정상
//        int scuComm    = ((error >> 2) & 0x01);     //SCU 통신 이상,  1: MCU <--> SCU 통신 이상, 0: 정상
//
//        int statusCount = ((stts)      & 0x7F);     //총 신호상태정보의 개수, N 개
//        int splitFlag   = ((stts >> 7) & 0x01);     //데이터를 분할하여 전송할 경우 마지막 정보임을 나타내는 플래그(분할 패킷의 처음과 중간:0, 단일 또는 마지막 패킷:1)
//
//        Date date = new java.util.Date(localTime * 1000L);
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
//        String signalTime = sdf.format(date);
//
//        log.info("   LocalTime: ({})", signalTime);
//        log.info("  SystemTime: ({})", SysUtils.getSysTimeStr());
//        log.info("      STATUS: 전이({}), 감응({}), 소등({}), 점멸({}), 수동({}) - (1:전이중, 0:전이완료... 1:상태, 0:정상)",
//                trans, sensing, turnOff, blink, manual);
//        log.info("       ERROR: SCU통신({}), 센터통신({}), 모순({}) - (1: 이상, 0: 정상)",
//                scuComm, centerComm, conflict);
//        log.info("CycleCounter: {} sec.", counter);
//        log.info("     Signals: {} EA, DataSplit({}) - (0:First/Middle, 1:Single/Last)", statusCount, splitFlag);
//
////typedef struct _tsc_cvim_hdr_s
////{
////    uint8_t manual      : 1;    /* 수동, 1: 이상, 0: 정상 */
////    uint8_t blink       : 1;    /* 점멸, 1: 점멸, 0: 정상 */
////    uint8_t turnOff     : 1;    /* 소등, 1: 소등, 0: 정상 */
////    uint8_t response    : 1;    /* 감응, 1: 감응, 0: 정상 */
////    uint8_t trans       : 1;    /* 전이, 1: 전이중, 0: 전이완료 */
////    uint8_t byte1Res0   : 3;    /* 예약, bit 7 ~ 5 */
////
////    uint8_t conflict    : 1;    /* 모순 이상, 1 : 이상, 0 : 정상 */
////    uint8_t centerComm  : 1;    /* 센터 통신 이상, 1: 센터 통신이상, 0 : 정상 */
////    uint8_t scuComm     : 1;    /* SCU 통신 이상,  1: MCU <--> SCU 통신 이상, 0: 정상 */
////    uint8_t byte2Res0   : 5;    /* 예약, bit 7 ~ 3 */
////
////    uint8_t cycleCounter;       /* 주기 카운터, 초 */
////
////    uint8_t sttsCount   : 7;    /* 총 신호상태정보의 개수, N 개 */
////    uint8_t splitFlag   : 1;    /* 데이터를 분할하여 전송할 경우 마지막 정보임을 나타내는 플래그(분할 패킷의 처음과 중간:0, 단일 또는 마지막 패킷:1) */
////
////    uint8_t currTime[4];        /* 현재시간, time_t형, Big Endian */
////} tsc_cvim_hdr_t, *ptsc_cvim_hdr_t;
//
//        final int SIGNAL_STATUS_SIZE = 5;
//        int remainLength = buffer.length - idx;
//        if (statusCount * SIGNAL_STATUS_SIZE != remainLength) {
//            log.error("Signal Status Data length error: {} EA, {}, {}", statusCount, statusCount * SIGNAL_STATUS_SIZE, remainLength);
//            return;
//        }
//
//        log.info("SEQ\t신호등정보\t방향\t시간정보신뢰성\t보행자   \t비보호신호\t신호등상태\t표출\t잔여\t방향코드");
//        for (int ii = 0; ii < statusCount; ii++) {
//            int dirInfo = buffer[idx++] & 0xFF;
//            int sttsInfo = buffer[idx++] & 0xFF;
//            int displayTm = buffer[idx++] & 0xFF;
//            int remainTm = buffer[idx++] & 0xFF;
//            int dirCode = buffer[idx++] & 0xFF;
//
//            int dirAdd     = ((dirInfo) & 0x0F);        //3 ~ 0, 방향추가정보, 해당 방향에 연등지 없음(0), 해당 방향의 첫번째 연등지(1), 해당 방향의 두번째 연등지(2)
//            int lightsType = ((dirInfo >> 4) & 0x0F);   //7 ~ 4, 신호등 정보, ■ 미지정(0), 직진(1), 좌회전(2), 보행자(3), 자전거(4), 우회전(5), 버스(6), 유턴(7)
//
//            int lighting   = ((sttsInfo     ) & 0x07);  //2 ~ 0, 신호등 상태, ■ 소등(0), 적색점등(1), 황색점등(2), 녹색점등(3), 적색점멸(4), 황색점멸(5), 녹색점멸(6)
//            int unprotect  = ((sttsInfo >> 3) & 0x01);  //3, 비보호 상태, ■ 신호등 정보 유턴/좌회전에 대한 비보호 여부, ■ 비보호 아님(0), 비보호(1)
//            int walkerPush = ((sttsInfo >> 6) & 0x01);  //6, 보행자(푸쉬 또는 자동검지), ■ 없음(0), 버튼 눌림 or 자동검지(1)
//            int timeFlag   = ((sttsInfo >> 7) & 0x01);  //7, 시간 정보 신뢰성, ■ 고정신호시간(0), 가변신호시간(1)
//
//            String plightInfo;
//            switch (lightsType)
//            {
//                case 0: plightInfo = "미지정(0)"; break;
//                case 1: plightInfo = "직진(1)  "; break;
//                case 2: plightInfo = "좌회전(2)"; break;
//                case 3: plightInfo = "보행자(3)"; break;
//                case 4: plightInfo = "자전거(4)"; break;
//                case 5: plightInfo = "우회전(5)"; break;
//                case 6: plightInfo = "버스(6)  "; break;
//                case 7: plightInfo = "유턴(7)  "; break;
//                default: plightInfo = "XXX(" + lightsType + ")"; break;
//            }
//            String ptimeFlag;
//            switch (timeFlag)
//            {
//                case 0: ptimeFlag = "고정신호(0)"; break;
//                case 1: ptimeFlag = "가변신호(1)"; break;
//                default: ptimeFlag = "XXX(" + timeFlag + ")"; break;
//            }
//            String pwalkerPush;
//            switch (walkerPush)
//            {
//                case 0: pwalkerPush = "없음(0)    "; break;
//                case 1: pwalkerPush = "자동검지(1)"; break;
//                default: pwalkerPush = "XXX(" + walkerPush + ")"; break;
//            }
//            String punprotect;
//            switch (unprotect)
//            {
//                case 0: punprotect = "아님(0)  "; break;
//                case 1: punprotect = "비보호(1)"; break;
//                default: punprotect = "XXX(" + unprotect + ")"; break;
//            }
//            String plighting;
//            switch (lighting)
//            {
//                case 0: plighting = "소등(0)    "; break;
//                case 1: plighting = "적색점등(1)"; break;
//                case 2: plighting = "황색점등(2)"; break;
//                case 3: plighting = "녹색점등(3)"; break;
//                case 4: plighting = "적색점멸(4)"; break;
//                case 5: plighting = "황색점멸(5)"; break;
//                case 6: plighting = "녹색점멸(6)"; break;
//                default: plighting = "XXX(" + lighting + ")"; break;
//            }
//            log.info("{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
//                    String.format("%3d", ii),
//                    plightInfo,
//                    dirAdd,
//                    ptimeFlag,
//                    pwalkerPush,
//                    punprotect,
//                    plighting,
//                    displayTm,
//                    remainTm,
//                    dirCode);
//        }
////        typedef struct _tsc_cvim_stts_s
////        {
////            uint8_t dirAdd      : 4;    /* 3 ~ 0, 방향추가정보, 해당 방향에 연등지 없음(0), 해당 방향의 첫번째 연등지(1), 해당 방향의 두번째 연등지(2) */
////            uint8_t lightInfo   : 4;    /* 7 ~ 4, 신호등 정보, ■ 미지정(0), 직진(1), 좌회전(2), 보행자(3), 자전거(4), 우회전(5), 버스(6), 유턴(7) */
////
////            uint8_t lighting    : 3;    /* 2 ~ 0, 신호등 상태, ■ 소등(0), 적색점등(1), 황색점등(2), 녹색점등(3), 적색점멸(4), 황색점멸(5), 녹색점멸(6) */
////            uint8_t unprotect   : 1;    /* 3, 비보호 상태, ■ 신호등 정보 유턴/좌회전에 대한 비보호 여부, ■ 비보호 아님(0), 비보호(1) */
////            uint8_t Reserved0   : 2;    /* 5 ~ 4, 예비, ■ 예비 */
////            uint8_t walkerPush  : 1;    /* 6, 보행자(푸쉬 또는 자동검지), ■ 없음(0), 버튼 눌림 or 자동검지(1) */
////            uint8_t timeFlag    : 1;    /* 7, 시간 정보 신뢰성, ■ 고정신호시간(0), 가변신호시간(1) */
////
////            uint8_t displayTm;          /* 표출 시간, ■ 초 */
////            uint8_t remainTm;           /* 잔여 시간, ■ 초 */
////            uint8_t dirCode;            /* 방향 코드, ■ 출력지정 테이블에 지정된 방향코드 */
////        } tsc_cvim_stts_t, *ptsc_cvim_stts_t;
//
//    }
}
