OVMS3/OVMS.V3/components/vehicle_kiasoulev/src/ks_incoming_c_can.cpp

326 lines
8.3 KiB
C++

/*
; Project: Open Vehicle Monitor System
; Date: 29th December 2017
;
; (C) 2017 Geir Øyvind Vælidalo <geir@validalo.net>
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in
; all copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
; THE SOFTWARE.
*/
#include "vehicle_kiasoulev.h"
static const char *TAG = "v-kiasoulev";
/**
* Handles incoming CAN-frames on bus 1, the C-bus
*/
void OvmsVehicleKiaSoulEv::IncomingFrameCan1(CAN_frame_t* p_frame)
{
uint8_t *d = p_frame->data.u8;
//ESP_LOGW(TAG, "%03x 8 %02x %02x %02x %02x %02x %02x %02x %02x",
// p_frame->MsgID, d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]);
switch (p_frame->MsgID)
{
case 0x018:
{
// Doors status Byte 0, 4 & 5:
StdMetrics.ms_v_door_chargeport->SetValue((d[0] & 0x01) > 0); //Byte 0 - Bit 0
StdMetrics.ms_v_door_fl->SetValue((d[0] & 0x10) > 0); //Byte 0 - Bit 4
StdMetrics.ms_v_door_fr->SetValue((d[0] & 0x80) > 0); //Byte 0 - Bit 7
StdMetrics.ms_v_door_rl->SetValue((d[4] & 0x08) > 0); //Byte 4 - Bit 3
StdMetrics.ms_v_door_rr->SetValue((d[4] & 0x02) > 0); //Byte 4 - Bit 1
StdMetrics.ms_v_door_trunk->SetValue((d[5] & 0x80) > 0); //Byte 5 - Bit 7
if(StdMetrics.ms_v_door_fl->AsBool() || StdMetrics.ms_v_door_fr->AsBool() ||
StdMetrics.ms_v_door_rl->AsBool() || StdMetrics.ms_v_door_rr->AsBool() ||
StdMetrics.ms_v_door_trunk->AsBool() )
{
StdMetrics.ms_v_env_locked->SetValue(false);
}
// Light status Byte 2,4 & 5
m_v_env_lowbeam->SetValue((d[2] & 0x01) > 0); //Byte 2 - Bit 0 - Low beam
m_v_env_highbeam->SetValue((d[2] & 0x02) > 0); //Byte 2 - Bit 1 - High beam
StdMetrics.ms_v_env_headlights->SetValue((d[4] & 0x01) > 0);//Byte 4 - Bit 0 - Day lights
//byte 5 - Bit 6 - Left indicator light
//byte 5 - Bit 5 - Right indicator light
uint8_t indLights = (d[5] & 0x60)>>5;
if( !m_v_emergency_lights->AsBool() && indLights==3)
{
//ks_check_door_lock = true;
m_v_emergency_lights->SetValue(true);
}
else if( m_v_emergency_lights->AsBool() && (indLights==1 || indLights==2))
m_v_emergency_lights->SetValue(false);
// Seat belt status Byte 7
m_v_seat_belt_driver->SetValue(!(d[7] & 0x10));
m_v_seat_belt_passenger->SetValue(!(d[7] & 0x40));
}
break;
case 0x110:
{
// Seat belt status Byte 7
m_v_seat_belt_back_right->SetValue((d[7] & 0x80));
m_v_seat_belt_back_middle->SetValue((d[7] & 0x20));
m_v_seat_belt_back_left->SetValue((d[7] & 0x08));
}
break;
case 0x120: //Locks
{
if (d[2] & 0x10)
{
//ks_check_door_lock=true;
if( d[1] & 0x08) StdMetrics.ms_v_env_locked->SetValue(false);
if( d[1] & 0x01) StdMetrics.ms_v_env_locked->SetValue(true);
}
if (d[3] & 0x20)
{
//ks_check_door_lock=true;
StdMetrics.ms_v_env_locked->SetValue(false);
if(ks_key_fob_open_charge_port && StdMetrics.ms_v_env_on->AsBool()) kia_lockDoors = true;
}
else if (d[3] & 0x10)
{
//ks_check_door_lock=true;
StdMetrics.ms_v_env_locked->SetValue(true);
if(ks_key_fob_open_charge_port && StdMetrics.ms_v_env_on->AsBool()) kia_unlockDoors = true;
}
if (d[3] & 0x40 && ks_key_fob_open_charge_port)
{
ks_openChargePort = true;
}
}
break;
case 0x1f1:
{
m_v_traction_control->SetValue(!(d[0] & 0x4));
}
break;
case 0x200:
{
// Estimated range:
float extraRange = StdMetrics.ms_v_env_hvac->AsBool() ? 0 : d[0]/10.0; //Extra range when heating is off.
uint16_t estRange = d[2] + ((d[1] & 1) << 9);
if (estRange > 0)
{
StdMetrics.ms_v_bat_range_est->SetValue((float) (estRange << 1) + extraRange, Kilometers);
}
}
break;
case 0x202:
{
m_v_power_usage->SetValue(
(float) (((int16_t) d[1] << 8) | d[2]), Watts);
}
break;
case 0x433:
{
// Parking brake status
StdMetrics.ms_v_env_handbrake->SetValue((d[2] & 0x10) > 0); //Why did I have 0x10 here??
}
break;
case 0x4b0:
{
// Motor RPM based on wheel rotation
int rpm = (d[0]+(d[1]<<8)) * 8.206;
StdMetrics.ms_v_mot_rpm->SetValue( rpm );
}
break;
case 0x4f0:
{
// Odometer:
if( d[7]+d[6]+d[5]>0)
{
StdMetrics.ms_v_pos_odometer->SetValue(
(float) ((d[7] << 16) + (d[6] << 8) + d[5]) / 10.0, Kilometers);
}
}
break;
case 0x4f2:
{
// Speed:
StdMetrics.ms_v_pos_speed->SetValue((float)d[1] /2.0, Kph); // kph
// 4f2 is one of the few can-messages that are sent while car is both on and off.
// Byte 2 and 7 are some sort of counters which runs while the car is on.
if (d[2] > 0 || d[7] > 0)
{
vehicle_kiasoulev_car_on(true);
}
else if (d[2] == 0 && d[7] == 0
&& StdMetrics.ms_v_pos_speed->AsFloat(Kph) == 0
/*&& StdMetrics.ms_v_env_handbrake->AsBool()*/)
{
// Both 2 and 7 and speed is 0, so we assumes the car is off.
vehicle_kiasoulev_car_on(false);
}
}
break;
case 0x534:
{
ESP_LOGI(TAG, "%03x 8 %02x %02x %02x %02x %02x %02x %02x %02x",
p_frame->MsgID, d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]);
if( (d[1] & 0x3) == 0 )
{
m_v_steering_mode->SetValue("Normal");
}
else if( (d[1] & 0x3) == 1 )
{
m_v_steering_mode->SetValue("Sport");
}
else
{
m_v_steering_mode->SetValue("Comfort");
}
}
break;
case 0x542:
{
// SOC:
if (d[0] > 0)
StdMetrics.ms_v_bat_soc->SetValue((float)d[0]/2.0);
}
break;
case 0x567:
{
// Clock:
if (d[1] > 0 || d[2] > 0 || d[3] > 0)
ks_clock=(((d[1]*60) + d[2])*60) + d[3];
}
break;
case 0x579: //Preheat timer 1 and 2
{
m_v_preheat_timer1_enabled->SetValue( d[0] & 0x1 );
m_v_preheat_timer2_enabled->SetValue( d[3] & 0x1 );
}
break;
case 0x57A: //Charge timer
{
m_obc_timer_enabled->SetValue( d[3] & 0x1 );
//Set the charge start time as seconds since midnight UTC.
StdMetrics.ms_v_charge_timerstart->SetValue(
(((d[4] & 0x1F)*60 + ((d[4]>>5) & 0x7)*10) + ks_utc_diff) * 60
);
}
break;
case 0x57B: //Charge timer
{
ks_charge_timer_off = d[2] & 0x8;
m_v_preheating->SetValue( d[4] & 0x1 ); //TODO Same bit for timer1 and timer2?
}
break;
case 0x581:
{
//m_v_power_usage->SetValue(
// (float) (((uint16_t) d[0] << 8) | d[1]) / 1000.0, kW);
// Car is CHARGING:
if( d[7]>0 && d[6]>0 )
{
StdMetrics.ms_v_bat_power->SetValue(
(float) (((uint16_t) d[7] << 8) | d[6]) / 256.0, kW);
}
}
break;
case 0x592:
{
m_v_cruise_control->SetValue( d[4] & 0x4 );
}
break;
case 0x594:
{
// BMS SOC:
uint16_t val = (uint16_t) d[5] * 5 + d[6];
if (val > 0)
{
m_b_bms_soc->SetValue( val / 10.0 , Percentage);
}
}
break;
case 0x597:
{
// Remaining charge time:
//uint16_t val = (uint16_t) ((d[2]<<8) + d[1]);
}
break;
case 0x653:
{
// Ambient temperature
StdMetrics.ms_v_env_temp->SetValue(TO_CELCIUS(d[5]/2.0), Celcius);
}
break;
case 0x654:
{
// Inside temperature
StdMetrics.ms_v_env_cabintemp->SetValue(TO_CELCIUS(d[7]/2.0), Celcius);
}
break;
case 0x779:
{
//ESP_LOGW(TAG, "%03x 8 %02x %02x %02x %02x %02x %02x %02x %02x",
// p_frame->MsgID, d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]);
}
break;
}
// Check if response is from synchronous can message
if (kia_send_can.status == 0xff && p_frame->MsgID == (kia_send_can.id + 0x08))
{
//Store message bytes so that the async method can continue
kia_send_can.status = 3;
kia_send_can.byte[0] = d[0];
kia_send_can.byte[1] = d[1];
kia_send_can.byte[2] = d[2];
kia_send_can.byte[3] = d[3];
kia_send_can.byte[4] = d[4];
kia_send_can.byte[5] = d[5];
kia_send_can.byte[6] = d[6];
kia_send_can.byte[7] = d[7];
}
}