# GB/T + J1939 Debug Flow (CAN ExtId)

Документ для ручного дебага обмена EV <-> EVSE по CAN (J1939 TP + short PGN).

## 1) Базовая структура CAN Extended ID (29-bit)

В проекте используется формула:

- `ExtId = (priority << 26) | (PGN << 8) | (SA << 8) | DA`

Где:
- `priority` — обычно `6` или `7`
- `PGN` — Parameter Group Number
- `SA` — Source Address
- `DA` — Destination Address

Адреса в ваших прошивках:
- `EVSE (SE)` = `0x56`
- `EV` = `0xF4`

Примеры:
- `0x181056F4` -> short PGN `0x1000` (BCL), `SA=0x56`, `DA=0xF4`
- `0x1CEC56F4` -> TP.CM от `0x56` к `0xF4`
- `0x1CECF456` -> TP.CM от `0xF4` к `0x56`
- `0x1CEB56F4` -> TP.DT от `0x56` к `0xF4`


## 2) Какие PGN short, какие TP

Short (<=8 байт, один CAN кадр):
- `0x0900` BRO
- `0x0A00` CRO
- `0x1000` BCL (5 байт)
- `0x1200` CCS
- `0x1300` BSM (7 байт)
- `0x1A00` CST

Через TP (>8 байт):
- `0x0200` BRM (49 байт)
- `0x0600` BCP (13 байт)
- `0x1100` BCS (9 байт)


## 3) Нормальная последовательность (высокоуровнево)

1. Handshake/recognition:
- CHM/CRM/BRM/BCP/CML/BRO/CRO

2. Переход в заряд:
- EVSE `S8 -> S9`
- EV начинает слать BCL/BSM/BCS
- EVSE принимает BCL и переходит `S9 -> S10`

3. Во время зарядки:
- EV регулярно шлет:
  - BCL (short)
  - BSM (short)
  - BCS (TP, `PGN=0x1100`)
- EVSE регулярно шлет CCS


## 4) Нормальная TP-сессия для BCS (`PGN=0x1100`, size=9, packets=2)

### Шаг 1: RTS (originator -> responder)

ID:
- от EV к EVSE: `1CEC F4 56` (`0x1CECF456`)

Data (TP.CM_RTS):
- `byte0 = 0x10` (RTS)
- `byte1..2 = total_size` (LSB/MSB), для BCS: `0x09 0x00`
- `byte3 = total_packets`, для BCS: `0x02`
- `byte4 = max_packets_per_CTS` (часто `0x02`)
- `byte5..7 = PGN` в little-endian (`00 11 00` для `0x1100`)

### Шаг 2: CTS (responder -> originator)

ID:
- от EVSE к EV: `1CEC 56 F4` (`0x1CEC56F4`)

Data (TP.CM_CTS):
- `byte0 = 0x11` (CTS)
- `byte1 = allowed_packet_count`
- `byte2 = next_packet_number` (обычно `1` для новой сессии)
- `byte3..4 = 0xFF`
- `byte5..7 = PGN` (`00 11 00`)

### Шаг 3: DT (originator -> responder)

ID:
- `1CEB F4 56` (EV -> EVSE)

Data (TP.DT):
- `byte0 = seq` (`1`, потом `2`)
- `byte1..7 = payload chunk`

Для 9 байт:
- DT#1 несет первые 7 байт
- DT#2 несет оставшиеся 2 байта + заполнение `0xFF`

### Шаг 4: ACK (responder -> originator)

ID:
- `1CEC 56 F4` (EVSE -> EV)

Data (TP.CM_EndOfMsgACK):
- `byte0 = 0x13` (ACK)
- `byte1..2 = total_size` (`09 00`)
- `byte3 = total_packets` (`02`)
- `byte4 = 0xFF`
- `byte5..7 = PGN` (`00 11 00`)


## 5) Как понять по логу, что сессия "правильная"

Для каждого `RTS(0x1100)` должен быть полный шаблон:
- `RTS` -> `CTS` -> `DT #1` -> `DT #2` -> `ACK`

Если есть `RTS`, но нет `CTS`:
- проблема на стороне responder (EVSE) TX/фильтр/перегрузка

Если есть `CTS`, но нет `DT`:
- проблема на стороне originator (EV) RX/парсинг/состояние

Если есть `DT`, но нет `ACK`:
- проблема на стороне responder reassembly/timeout


## 6) Поля основных GB/T пакетов (payload)

### BCL (`PGN 0x1000`, short, 5 bytes)
Структура:
- `requestedVoltage` (`uint16`, 0.1V/bit)
- `requestedCurrent` (`uint16`, 0.1A/bit, в вашем коде может интерпретироваться как `4000 - value`)
- `chargingMode` (`uint8`, `0x01` CV, `0x02` CC)

### BCS (`PGN 0x1100`, TP, 9 bytes)
Структура:
- `measuredChargingVoltage` (`uint16`)
- `measuredChargingCurrent` (`uint16`)
- `highestVoltageOfBatteryCell` (`uint16`)
- `currentChargeState` (`uint8`)
- `estimatedRemainingChargingTime` (`uint16`)

### BSM (`PGN 0x1300`, short, 7 bytes)
Структура:
- max/temperature индексы и статусы:
  - `singleBatteryHighestVoltageSerNo`
  - `batteryHighestTemp`
  - `batteryHighestTempSerNo`
  - `batteryLowestTemp`
  - `batteryLowestTempSerNo`
  - `batteryCellVoltageState`
  - `batteryStatus`


## 7) Тайминги TP из J1939 (важное для дебага)

Ключевые reference значения:
- `Tr = 200 ms`
- `Th = 500 ms`
- `T1 = 750 ms`
- `T2 = 1250 ms`
- `T3 = 1250 ms`
- `T4 = 1050 ms`

Практически:
- если responder выдал CTS, originator не должен задерживать DT дольше допусков
- если originator отправил RTS/DT, responder должен ответить CTS/ACK в окне таймаутов


## 8) Мини-чеклист при "вдруг стопнулось"

1. Найти последний `RTS` по `PGN=0x1100`.
2. Проверить, был ли `CTS` на шине с тем же `PGN`.
3. Проверить наличие `DT#1/#2`.
4. Проверить `ACK`.
5. Если цепочка оборвалась:
   - зафиксировать на каком шаге;
   - сопоставить с UART логом state machine (`S9/S10`, `TP timeout`, `BCS timeout`).
