Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement some of the 0x23 register #37

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ The following topics are published:
| phev/door/boot | State of doors. *closed* or *open* |
| phev/lights/parking | Parking lights. *on* or *off* |
| phev/lights/head | Head lights. *on* or *off* |
| phev/lights/hazard | Hazard lights. *on* or *off* |
| phev/lights/interior | Interior lights. *on* or *off* |
| phev/vin | Discovered VIN of the car |
| phev/registrations | Number of wifi clients registered to the car |

Expand Down
3 changes: 3 additions & 0 deletions cmd/mqtt.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,9 @@ func (m *mqttClient) publishRegister(msg *protocol.PhevMessage) {
case *protocol.RegisterBatteryLevel:
m.publish("/battery/level", fmt.Sprintf("%d", reg.Level))
m.publish("/lights/parking", boolOnOff[reg.ParkingLights])
case *protocol.RegisterLightStatus:
m.publish("/lights/interior", boolOnOff[reg.Interior])
m.publish("/lights/hazard", boolOnOff[reg.Hazard])
case *protocol.RegisterChargePlug:
if reg.Connected {
m.publish("/charge/plug", "connected")
Expand Down
47 changes: 26 additions & 21 deletions protocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ There seem to be two types of register layout (A/B).
|0x20 | ?? | 10 | 146 | [2,2,2,2,2] | |
|0x21 | ?? | 1 | 156 | [1] | |
|0x22 | ?? | 6 | 157 | [2,2,2] | |
|0x23 | ?? | 5 | 163 | [1,1,1,1,1] | Maybe AC related |
|0x23 | Interior/Hazard Lights + AC? | 5 | 163 | [1,1,1,1,1] | |
|0x24 | Door Lock Status | 10 | 168 | [1,1,1,1,1,1,1,1,1,1] | |
|0x25 | ?? | 3 | 178 | [1,1,1] | |
|0x26 | ?? | 1 | 181 | [1] | |
Expand Down Expand Up @@ -393,7 +393,12 @@ Single byte.
|0 | Charge status [0=not charging 1=charging]|
| 1-2 | Charge time remaining |

### 0x23 - Something AC?
### 0x23 - Interior/Hazard lights + Something AC?

Interior lights ON: `0000000201`
Interior lights OFF: `0000000202`
Hazard lights ON: `0000000102`
Hazard lights OFF: `0000000202`

AC timer sniff:

Expand Down Expand Up @@ -522,35 +527,35 @@ AC data sniff.

Windscreen for 10 mins:

INFO[0000] out [a1] REGISTER SET (reg 0x1b data 02030000)
INFO[0000] in [a1] REGISTER NTFY (reg 0x10 data 02b00b)
INFO[0000] in [55] REGISTER NTFY (reg 0x1a data 0001000000)
INFO[0000] in [70] REGISTER NTFY (reg 0x1c data 03)
INFO[0000] out [a1] REGISTER SET (reg 0x1b data 02030000)
INFO[0000] in [a1] REGISTER NTFY (reg 0x10 data 02b00b)
INFO[0000] in [55] REGISTER NTFY (reg 0x1a data 0001000000)
INFO[0000] in [70] REGISTER NTFY (reg 0x1c data 03)

Heat in 5 mins for 10 mins:

INFO[0000] out [70] REGISTER SET (reg 0x1b data 02020001)
INFO[0000] in [01] REGISTER NTFY (reg 0x1a data 0000000101)
INFO[0000] in [86] REGISTER NTFY (reg 0x1c data 02)
INFO[0000] out [70] REGISTER SET (reg 0x1b data 02020001)
INFO[0000] in [01] REGISTER NTFY (reg 0x1a data 0000000101)
INFO[0000] in [86] REGISTER NTFY (reg 0x1c data 02)

Heat in 0 mins for 10 mins:

INFO[0000] out [73] REGISTER SET (reg 0x1b data 02020000)
INFO[0000] in [73] REGISTER NTFY (reg 0x10 data 02b020)
INFO[0000] in [22] REGISTER NTFY (reg 0x1a data 0001000000)
INFO[0000] in [50] REGISTER NTFY (reg 0x1c data 02)
INFO[0000] out [73] REGISTER SET (reg 0x1b data 02020000)
INFO[0000] in [73] REGISTER NTFY (reg 0x10 data 02b020)
INFO[0000] in [22] REGISTER NTFY (reg 0x1a data 0001000000)
INFO[0000] in [50] REGISTER NTFY (reg 0x1c data 02)

Heat in 0 mins for 20 mins
INFO[0000] out [4e] REGISTER SET (reg 0x1b data 02020100)
INFO[0000] in [1c] REGISTER NTFY (reg 0x10 data 02b034)
INFO[0000] in [e7] REGISTER NTFY (reg 0x1a data 0001010000)
INFO[0000] in [c6] REGISTER NTFY (reg 0x1c data 02)
INFO[0000] out [4e] REGISTER SET (reg 0x1b data 02020100)
INFO[0000] in [1c] REGISTER NTFY (reg 0x10 data 02b034)
INFO[0000] in [e7] REGISTER NTFY (reg 0x1a data 0001010000)
INFO[0000] in [c6] REGISTER NTFY (reg 0x1c data 02)

Cool 0 mins for 10 mins
INFO[0170] out [5f] REGISTER SET (reg 0x1b data 02010000)
INFO[0170] in [5b] REGISTER NTFY (reg 0x10 data 02b139)
INFO[0171] in [18] REGISTER NTFY (reg 0x1a data 0001000000)
INFO[0171] in [95] REGISTER NTFY (reg 0x1c data 01)
INFO[0170] out [5f] REGISTER SET (reg 0x1b data 02010000)
INFO[0170] in [5b] REGISTER NTFY (reg 0x10 data 02b139)
INFO[0171] in [18] REGISTER NTFY (reg 0x1a data 0001000000)
INFO[0171] in [95] REGISTER NTFY (reg 0x1c data 01)

Cool 10 mins for 10 mins
SETREG 0x1b: -> 02010002
Expand Down
47 changes: 40 additions & 7 deletions protocol/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ func (p *PhevMessage) DecodeFromBytes(data []byte, key *SecurityKey) error {
p.Reg = new(RegisterACOperStatus)
case ACModeRegister:
p.Reg = new(RegisterACMode)
case LightStatusRegister:
p.Reg = new(RegisterLightStatus)
default:
p.Reg = new(RegisterGeneric)
}
Expand Down Expand Up @@ -234,18 +236,19 @@ func NewFromBytes(data []byte, key *SecurityKey) []*PhevMessage {
}

const (
VINRegister = 0x15
ECUVersionRegister = 0xc0
BatteryLevelRegister = 0x1d
BatteryWarningRegister = 0x02
DoorStatusRegister = 0x24
ChargeStatusRegister = 0x1f
ACOperStatusRegister = 0x1a
SetACEnabledRegisterMY14 = 0x04
SetACModeRegisterMY14 = 0x02
SetACEnabledRegisterMY14 = 0x04
VINRegister = 0x15
ACOperStatusRegister = 0x1a
SetACModeRegisterMY18 = 0x1b
ACModeRegister = 0x1c
BatteryLevelRegister = 0x1d
ChargePlugRegister = 0x1e
ChargeStatusRegister = 0x1f
LightStatusRegister = 0x23
DoorStatusRegister = 0x24
ECUVersionRegister = 0xc0
)

type Register interface {
Expand Down Expand Up @@ -577,3 +580,33 @@ func (r *RegisterChargePlug) String() string {
func (r *RegisterChargePlug) Register() byte {
return ChargePlugRegister
}


type RegisterLightStatus struct {
Interior bool
Hazard bool
raw []byte
}


func (r *RegisterLightStatus) Decode(m *PhevMessage) {
if len(m.Data) != 5 {
return
}
// Switches between 2 for Off and 1 for On.
r.Interior = m.Data[4] & 0b11 == 1;
r.Hazard = m.Data[3] & 0b11 == 1;
r.raw = m.Data
}

func (r *RegisterLightStatus) Raw() string {
return hex.EncodeToString(r.raw)
}

func (r *RegisterLightStatus) String() string {
return fmt.Sprintf("Hazard lights: %t; Interior lights: %t.", r.Hazard, r.Interior)
}

func (r *RegisterLightStatus) Register() byte {
return LightStatusRegister
}