This repository has been archived by the owner on Aug 19, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
twc_protocol.h
executable file
·233 lines (206 loc) · 7.22 KB
/
twc_protocol.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
TWC Manager for ESP32
Copyright (C) 2020 Craig Peacock
Copyright (C) 2020 Jarl Nicolson
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TWC_PROTOCOL_H
#define TWC_PROTOCOL_H
#include "twc_controller.h"
#include "mqtt.h"
#include "twc_connector.h"
#define GET_SERIAL_NUMBER_OLD 0xFB19
#define GET_MODEL_NUMBER 0xFB1A
#define GET_FIRMWARE_VER 0xFB1B
#define GET_PLUG_STATE 0xFBB4
#define PRIMARY_HEARTBEAT 0xFBE0
#define PRIMARY_PRESENCE2 0xFBE2
#define GET_PWR_STATE 0xFBEB
#define GET_FIRMWARE_VER_EXT 0xFBEC
#define GET_SERIAL_NUMBER 0xFBED
#define GET_VIN_FIRST 0xFBEE
#define GET_VIN_MIDDLE 0xFBEF
#define GET_VIN_LAST 0xFBF1
// The next two commands are ** DANGEROUS ** !
// DO NOT USE THESE! They are defined so that
// they can be blocked.
#define WRITE_ID_DATE 0xFC19
#define WRITE_MODEL_NO 0xFC1A
// Commands without responses (0xFC)
#define IDLE_MESSAGE 0xFC1D
#define START_CHARGING 0xFCB1
#define STOP_CHARGING 0xFCB2
#define PRIMARY_PRESENCE 0xFCE1
// Responses (0xFD)
#define RESP_SERIAL_NUMBER_OLD 0xFD19
#define RESP_MODEL_NUMBER 0xFD1A
#define RESP_FIRMWARE_VER 0xFD1B
#define RESP_PLUG_STATE 0xFDB4
#define SECONDARY_HEARTBEAT 0xFDE0
#define SECONDARY_PRESENCE 0xFDE2 // Sent by secondary on reset
#define RESP_PWR_STATUS 0xFDEB // Sent by primary on reset
#define RESP_FIRMWARE_VER_EXT 0xFDEC
#define RESP_SERIAL_NUMBER 0xFDED
#define RESP_VIN_FIRST 0xFDEE
#define RESP_VIN_MIDDLE 0xFDEF
#define RESP_VIN_LAST 0xFDF1
// Commands are SLIP encoded on the wire - need the SLIP constants
#define SLIP_END 0xC0
#define SLIP_ESC 0xDB
#define SLIP_ESC_END 0xDC
#define SLIP_ESC_ESC 0xDD
#pragma pack(1)
typedef struct PACKET_T {
uint16_t command;
uint16_t twcid;
uint16_t secondary_twcid;
uint8_t payload[6];
uint8_t checksum;
} PACKET_T;
typedef struct RESP_PACKET_T {
uint16_t command;
uint16_t twcid;
uint8_t payload[11];
uint8_t checksum;
} RESP_PACKET_T;
typedef struct EXTENDED_RESP_PACKET_T {
uint16_t command;
uint16_t twcid;
uint8_t payload[15];
uint8_t checksum;
} EXTENDED_RESP_PACKET_T;
typedef struct S_HEARTBEAT_T {
uint16_t command;
uint16_t src_twcid;
uint16_t dst_twcid;
uint8_t state;
uint16_t max_current;
uint16_t actual_current;
uint8_t padding[4];
uint8_t checksum;
} S_HEARTBEAT_T;
typedef struct P_HEARTBEAT_T {
uint16_t command;
uint16_t src_twcid;
uint16_t dst_twcid;
uint8_t state;
uint16_t max_current;
uint8_t plug_inserted;
uint8_t padding[5];
uint8_t checksum;
} P_HEARTBEAT_T;
// Standard response packet payload
typedef struct PRESENCE_PAYLOAD_T {
uint8_t sign;
uint16_t max_allowable_current;
uint8_t padding[8];
} PRESENCE_PAYLOAD_T;
// Extended response packet payload
typedef struct POWERSTATUS_PAYLOAD_T {
uint32_t total_kwh;
uint16_t phase1_voltage;
uint16_t phase2_voltage;
uint16_t phase3_voltage;
uint8_t phase1_current;
uint8_t phase2_current;
uint8_t phase3_current;
uint8_t padding[2];
} POWERSTATUS_PAYLOAD_T;
// Extended response packet payload
typedef struct VIN_PAYLOAD_T {
uint8_t vin[7];
uint8_t padding[8];
} VIN_PAYLOAD_T;
// Extended response packet payload
typedef struct SERIAL_PAYLOAD_T {
uint8_t serial[11];
uint8_t padding[4];
} SERIAL_PAYLOAD_T;
// Standard response packet Payload
typedef struct EXT_FIRMWARE_PAYLOAD_T {
uint8_t major;
uint8_t minor;
uint8_t revision;
uint8_t extended;
uint8_t padding[7];
} EXT_FIRMWARE_PAYLOAD_T;
class TeslaController {
public:
TeslaController(HardwareSerial& serial, TeslaControllerIO& io);
void Begin();
void GetPowerStatus(uint16_t secondary_twcid);
void GetFirmware(uint16_t secondary_twcid);
void GetSerial(uint16_t secondary_twcid);
void GetFirmwareVer(uint16_t secondary_twcid);
void GetVin(uint16_t secondary_twcid);
void Handle();
void SendCommand(uint16_t command, uint16_t send_to);
void SendPresence(bool presence2 = false);
void SendPresence2();
void SendHeartbeat(uint16_t secondary_twcid);
void SendIdle();
void Startup();
void SendData(uint8_t *packet, size_t length);
void DecodePowerState(EXTENDED_RESP_PACKET_T *power_state);
void DecodePrimaryPresence(RESP_PACKET_T *presence, uint8_t num);
void DecodePrimaryHeartbeat(P_HEARTBEAT_T *heartbeat);
void DecodeSecondaryPresence(RESP_PACKET_T *presence);
void DecodeSecondaryHeartbeat(S_HEARTBEAT_T *heartbeat);
void DecodeVin(EXTENDED_RESP_PACKET_T *vin);
void DecodeExtFirmwareVerison(RESP_PACKET_T *firmware_ver);
void DecodeSerialNumber(EXTENDED_RESP_PACKET_T *serial);
void SetCurrent(uint8_t current);
void SetMaxCurrent(uint8_t maxCurrent);
void SetMinCurrent(uint8_t mincurrent);
void SetStopStartDelay(uint16_t stopstart_delay);
uint8_t ChargersConnected();
TeslaConnector * GetConnector(uint16_t twcid);
void UpdateTotalActualCurrent();
void UpdateTotalPhaseCurrent(uint8_t phase);
void UpdateTotalConnectedCars();
void StopCharging(uint16_t twcid);
void StartCharging(uint16_t twcid);
bool IsCharging();
private:
uint8_t CalculateChecksum(uint8_t *buffer, size_t length);
bool VerifyChecksum(uint8_t *buffer, size_t length);
void DecodeLinkReady();
void DecodePrimaryHeartbeat();
void DecodeSecondaryHeartbeat();
void ProcessPacket(uint8_t *packet, size_t length);
static void startupTask_(void *pvParameter);
static void offDelayCallback_(TimerHandle_t xTimer);
static void onDelayCallback_(TimerHandle_t xTimer);
void Debug(bool enabled);
void SendDataFromString(const uint8_t* dataString, size_t length);
private:
HardwareSerial* serial_;
TeslaControllerIO* controller_io_;
uint8_t num_connected_chargers_;
uint16_t twcid_;
uint8_t sign_;
uint8_t receive_buffer_[MAX_PACKET_LENGTH];
uint8_t receive_index_;
bool message_started_ = false;
uint8_t available_current_;
uint8_t max_current_;
uint8_t min_current_;
uint16_t stopstart_delay_;
bool current_changed_;
bool debug_;
uint8_t total_current_;
TeslaConnector* chargers[3];
TimerHandle_t offDelayTimer_;
TimerHandle_t onDelayTimer_;
};
#endif /* TWC_PROTOCOL_H */