'##############
'Heizungs-Script
'##############

'Simuliert Wagenheizung, Zusatzheizung (evtl. auch gleich den Kühlkreislauf mit...)

'(c) 20.02.2009 Rüdiger Hülsmann

'Script Version: 1.1
'Omsi release: 1.0

'Needs:
'cockpit (für Taster und Regler)
'engine (for cooling circuit)
'door (for door opening status)

'Revision History:
'- Rüdiger Hülsmann	17.02.2009	File created
'- Rüdiger Hülsmann	20.02.2009	Batterietrennschalter eingefügt (v1.1)
'- Marcel Kuhnt		10.08.2009	Added Revision History
'- Marcel & Rüdiger	23.09.2010	Parking Heater, room temperature
'- RÜdiger Hülsmann	16.11.2010	Front heater
'- Rüdiger Hülsmann	18.11.2010	Improved front heater
'- Rüdiger Hülsmann	20.11.2010	Cabin heater, values adjusted
'- Rüdiger Hülsmann	22.11.2010	Auxheat Schmitt-triggered, engine coolable by fan heaters
'- Rüdiger Hülsmann	10.01.2011	Driver window airflow
'- Ñåðãåé Wizard	17.11.2013	Analog Conditioner for o530 Citaro
'- Marcos Zane		03.06.2018  Variable target temp for Air Conditioning
'- Marcos Zane      07.02.2020  Simulation of air flow for many windows
'- Marcos Zane		XX.05.2021	Simulation of A/C failure
'------------------------------------------------------------------------------------------
'
{trigger:cp_klima_temp_increase}
	(L.L.elec_busbar_main)
	{if}
		(L.L.cabinair_target_temp) 30 <
		{if}
			(L.L.cabinair_target_temp) 1 + (S.L.cabinair_target_temp)
		{endif}
		(T.L.ev_VDV_on)
        1 (S.L.heizung_blink_display)
	{endif}
{end}


{trigger:cp_klima_temp_decrease}
	(L.L.elec_busbar_main)
	{if}
		(L.L.cabinair_target_temp) 15 >
		{if}
			(L.L.cabinair_target_temp) 1 - (S.L.cabinair_target_temp)
		{endif}
		(T.L.ev_VDV_on)
        1 (S.L.heizung_blink_display)
	{endif}
{end}

'   Ventilacao AC
{trigger:taster_internal_air}
	(L.L.elec_busbar_main)
	{if}
		(L.L.cp_taster_internal_air) ! (S.L.cp_taster_internal_air) s1

		(T.L.ev_VDV_on)
	{endif}
{end}

{trigger:taster_heat_or_frost}

	(L.L.cp_taster_heat_or_frost) ! (S.L.cp_taster_heat_or_frost) s0

	(M.L.kippschaltersound)
{end}

{trigger:taster_klima}
	(L.L.elec_busbar_main)
	{if}
		(L.L.cp_taster_klima) ! (S.L.cp_taster_klima)
		(T.L.ev_VDV_on)
	{endif}
{end}

{trigger:cp_heizregler_temp_drag}

	(L.S.mouse_y) -150 / (L.L.cockpit_heizregler_temp) + 0 max 1 min (S.L.cockpit_heizregler_temp)

{end}

'----------------------
'	Init
'----------------------
{macro:heizung_init}
	(L.S.Weather_Temperature) (S.L.Cabinair_Temp)
	(L.S.Weather_AbsHum) (S.L.Cabinair_absHum)
	22 (S.L.cabinair_target_temp)
    (C.L.Fehlertoleranz) (L.L.wearlifespan) * random (S.L.AC_Error_Dist)
{end}


{macro:heizung_frame}

	(M.L.standheizung_frame)	
	(M.L.cabinair_frame)

    (L.L.elec_busbar_main)
    {if}
        (M.L.heizungdisplay_frame)
    {else}
        0 (S.L.heizung_display)
    {endif}
{end}

{macro:heizungdisplay_frame}

    (L.L.AC_error_type) 0 >
    {if}
        (L.L.heizung_timer) 8 <
        {if}
            (L.L.heizung_timer) (L.S.Timegap) + (S.L.heizung_timer)
        {endif}
        
        (L.L.heizung_timer) 4 >
        {if}
            2 (S.L.heizung_blink_display)
        {endif}

        (L.L.heizung_timer) 7 >
        {if}
            0 (S.L.heizung_timer) (S.L.heizung_blink_display)
        {endif}
    {endif}



    (L.L.heizung_blink_display) 0 >
    {if}
        (L.L.heizung_blink_display) 1 =
        {if}
            (L.L.heizung_timer2) 3 <
            {if}
                (L.L.heizung_timer2) (L.S.Timegap) + (S.L.heizung_timer2)
                (M.L.heizung_blink)
            {else}
                0 (S.L.heizung_timer2) (S.L.heizung_blink_display)
            {endif}
        {else}
            (M.L.heizung_blink)
        {endif}
    {else}
        1 (S.L.heizung_display)
    {endif}


    (L.L.AC_error_type) 0 >
    (L.L.heizung_blink_display) 2 = &&
    {if}
        (L.L.AC_error_type) 1 =
        {if}
            " HA"
        {endif}
        (L.L.AC_error_type) 2 =
        {if}
            " OP"
        {endif}
    {else}
        (L.L.cabinair_target_temp) s0 trunc " 3" $IntToStrEnh
    {endif}
	(S.$.cockpit_target_temperatur)

{end}


{macro:cabinair_frame}



    (L.L.cabinair_Vrate_cabinaircondition) 0 >
    (L.L.cabinair_Vrate_cabinheater) 0 > ||
    {if}
        (L.L.AC_Error_dist) (L.L.velocity) 3600 / (L.S.Timegap) * + (S.L.AC_Error_dist)
        (C.L.Fehlertoleranz) (L.L.wearlifespan) * >
        {if}
            2999 random 1000 / trunc s1
            l1 2 <
            {if}
'               Falha HA - falha no compressor
                1 (S.L.AC_error_type)
            {else}
'               Falha OP - termostato com falha
                2 (S.L.AC_error_type)
            {endif}
        {endif}
    {endif}

    (L.L.engine_n) (F.L.ac_compressor_curve) (S.L.ac_compressor_n)

'Frontheizgerät:
	(L.L.elec_busbar_main) 0 >
	(L.L.engine_n) 400 > &&
	{if}
		(L.L.cp_klimator_sw) s1
	{else}
		0 s1
	{endif}

'Anlauf oder Auslauf?
	l1 100 * (L.L.cp_klimator_RPM) > 
	{if}
		1.5 s0
	{else}
		0.5 s0
	{endif}

' Berechnung der Luefterbeschleunigung:

'Sollwert:
	l1 100 * 
'Istwert:
	(L.L.cp_klimator_RPM)
'Beschleunigung:
	- s0 * (L.S.Timegap) *
'Addition zum Istwert:
	(L.L.cp_klimator_RPM) + (S.L.cp_klimator_RPM)



'	Berechnung der Raten:
	(L.L.Cabinair_Temp) (L.S.Weather_Temperature) - (C.L.cabinair_Qrate_envir_factor) * (S.L.cabinair_Qrate_envir)

'	Direkte Ableitung der Motorwärme in den Fahrgastraum
	(L.L.engine_temperature_envir) (L.L.Cabinair_Temp) - (C.L.cabinair_Qrate_engine_factor) * (S.L.cabinair_Qrate_engine)

'Fahrerheizung

'(L.L.cp_dummy_sw01) !
'(L.L.cp_taster_internal_air) &&
'{if}
'	(L.L.Cabinair_Temp) (L.L.engine_temperature) (L.L.Cabinair_Temp) - (L.L.cockpit_heizregler_temp) * (C.L.heat_exchanger_effectivity) * + (S.L.fanheater_t_target)
'{endif}
'
'(L.L.cp_dummy_sw01) !
'(L.L.cp_taster_internal_air) ! &&
'{if}
'	(L.S.Weather_Temperature) (L.L.engine_temperature) (L.S.Weather_Temperature) - (L.L.cockpit_heizregler_temp) * (C.L.heat_exchanger_effectivity) * + (S.L.fanheater_t_target)
'{endif}

'Fahrerklima

'(L.L.cp_dummy_sw01)
'(L.L.cp_taster_internal_air)
'(L.L.engine_n) 300 > &&
'{if}
'	(L.L.Cabinair_Temp) 16 (L.L.Cabinair_Temp) - 1 (L.L.cockpit_heizregler_temp) - * + 16 max (S.L.fanheater_t_target)
'{endif}

'   Air exhaust target temperature
(L.L.cp_dummy_sw01)
'(L.L.cp_taster_internal_air) ! &&
(L.L.engine_n) 300 > &&
{if}
	(L.S.Weather_Temperature) 3 + (S.L.fanheater_t_target)
{endif}


'Calculation of the effective total air exchange area:
'   Door calculations
	(L.L.door_0) (L.L.door_1) (L.L.door_2) (L.L.door_3) (L.L.door_4) (L.L.door_5) (L.L.door_6) (L.L.door_7) (L.L.door_8) (L.L.door_9) (L.L.door_10) (L.L.door_11) + + + + + + + + + + + (C.L.cabinair_A_perdoor) *

'   Small windows calculations
	(L.L.cp_klappfenster_OR1) (L.L.cp_klappfenster_OR2) (L.L.cp_klappfenster_OR3) (L.L.cp_klappfenster_OR4) + + +
	(L.L.cp_klappfenster_OL1) (L.L.cp_klappfenster_OL2) (L.L.cp_klappfenster_OL3) (L.L.cp_klappfenster_OL4) + + + +
	(L.L.cp_klappfenster_UR1) (L.L.cp_klappfenster_UR2) (L.L.cp_klappfenster_UR3) (L.L.cp_klappfenster_UR4) + + + +
	(L.L.cp_klappfenster_UL2) + (C.L.cabinair_A_perwindow_sm) * +

'   Roof tamp calculations
    (L.L.cp_dachluke_1) (L.L.cp_dachluke_2) (L.L.cp_dachluke_3) + + (C.L.cabinair_A_perdachluke) * +

'   Normal windows calculations
    (L.L.cp_fortochka_pass_anim_4_pos) 
    (L.L.cp_fortochka_pass_anim_5_pos) (L.L.cp_fortochka_pass_anim_6_pos) (L.L.cp_fortochka_pass_anim_7_pos) (L.L.cp_fortochka_pass_anim_8_pos) + + + +
    (L.L.cp_fortochka_pass_anim_9_pos) (L.L.cp_fortochka_pass_anim_10_pos) (L.L.cp_fortochka_pass_anim_11_pos) (L.L.cp_fortochka_pass_anim_12_pos) + + + +
    (L.L.cp_fortochka_pass_anim_13_pos) (L.L.cp_fortochka_pass_anim_14_pos) (L.L.cp_fortochka_pass_anim_15_pos) (L.L.cp_fortochka_pass_anim_16_pos) + + + +
    (L.L.cp_fortochka_pass_anim_17_pos) (L.L.cp_fortochka_pass_anim_18_pos) (L.L.cp_fortochka_pass_anim_19_pos) (L.L.cp_fortochka_pass_anim_20_pos) + + + +
    (L.L.cp_fortochka_pass_anim_21_pos) (L.L.cp_fortochka_pass_anim_22_pos) (L.L.cp_fortochka_pass_anim_23_pos) (L.L.cp_fortochka_pass_anim_24_pos) + + + +
    (L.L.cp_fortochka_pass_anim_25_pos) (L.L.cp_fortochka_pass_anim_26_pos) (L.L.cp_fortochka_pass_anim_27_pos) (L.L.cp_fortochka_pass_anim_28_pos) + + + +
    (L.L.cp_fortochka_pass_anim_29_pos) (L.L.cp_fortochka_pass_anim_30_pos) (L.L.cp_fortochka_pass_anim_31_pos) (L.L.cp_fortochka_pass_anim_32_pos) + + + +
    (L.L.cp_fortochka_pass_anim_33_pos) (L.L.cp_fortochka_pass_anim_34_pos) (L.L.cp_fortochka_pass_anim_35_pos) (L.L.cp_fortochka_pass_anim_36_pos) + + + +
    (L.L.cp_fortochka_pass_anim_37_pos) (L.L.cp_fortochka_pass_anim_38_pos) (L.L.cp_fortochka_pass_anim_39_pos) (L.L.cp_fortochka_pass_anim_40_pos) + + + +
    (L.L.cp_fortochka_pass_anim_41_pos) (L.L.cp_fortochka_pass_anim_42_pos) (L.L.cp_fortochka_pass_anim_43_pos) (L.L.cp_fortochka_pass_anim_44_pos) + + + +
'    (L.L.cp_fortochka_pass_anim_45_pos) +
    (C.L.cabinair_A_perwindow_nm) * +

'   Driver window calculation
	(C.L.cabinair_A_driverwindow) (L.L.cp_fahrerfenster_1_pos) * +
    (C.L.cabinair_A_driverwindow) (L.L.cp_fahrerfenster_2_pos) * +

'Berechnung des Gesamtvolumenstroms in die Außenwelt und umgekehrt (V zählt je Richtung, d.h. insgesamt wird 2*V bewegt)
	(L.L.velocity) 20 / abs (C.L.cabinair_windowdoor_minkmh) + (C.L.cabinair_windowdoor_effectivity) * 3.6 / * (S.L.cabinair_Vrate_doorwindow)

'Temp change rate for air exhaust
'	(L.L.cockpit_heizregler_ventilation_mode) 1 =
'	{if}
'		(C.L.cabinair_A_frontheater) (L.L.velocity) 20 / abs (C.L.cabinair_windowdoor_minkmh) + (C.L.cabinair_windowdoor_effectivity) * 3.6 / * (S.L.cabinair_Vrate_fanheater)
'	{else}
		(C.L.cabinair_A_frontheater) (L.L.cp_klimator_RPM) 100 / * (S.L.cabinair_Vrate_fanheater)
'	{endif}

'Calculation of the offset temperatures for heating/air conditioning
	(L.L.cabinair_target_temp) s2

	l2 (C.L.cabinair_target_temp_offset) + (S.L.cabinair_highoffset_ACtemp)
	l2 (C.L.cabinair_target_temp_offset) - (S.L.cabinair_lowoffset_ACtemp)

	l2 (C.L.cabinair_target_temp_offset) 2 - - (S.L.cabinair_lowoffset_temp)

'Calculation of the volume flow through the room heaters
	(L.L.cp_heizluefter_sw)
	(L.L.cabinair_temp) (L.L.cabinair_lowoffset_temp) < &&
	(L.L.cp_taster_heat_or_frost) ||
	(L.L.engine_n) 400 > &&
	(L.L.elec_busbar_main) &&
    (L.L.AC_error_type) 1 = ! &&
	{if}
		(C.L.cabinair_A_cabinheater) (S.L.cabinair_Vrate_cabinheater)
	{endif}

	(L.L.cp_heizluefter_sw) !
	(L.L.cabinair_temp) (L.L.cabinair_target_temp) > ||
	(L.L.cp_taster_heat_or_frost) ! &&
    (L.L.AC_error_type) 2 = ! &&
	(L.L.engine_n) 400 < ||
	(L.L.elec_busbar_main) ! ||
	{if}
		0 (S.L.cabinair_Vrate_cabinheater)
	{endif}

'Calculation of the volume flow through the air conditioning
	(L.L.cp_taster_klima)
	(L.L.cabinair_temp) (L.L.cabinair_highoffset_ACtemp) > &&
	(L.L.cp_taster_heat_or_frost) ||
	(L.L.engine_n) 400 > &&
	(L.L.elec_busbar_main) &&
    (L.L.AC_error_type) 1 = ! &&
	{if}
		(C.L.cabinair_A_cabinheater) (S.L.cabinair_Vrate_cabinaircondition) 
        1 (S.L.ac_compressor)
	{endif}

	(L.L.cp_taster_klima) !
	(L.L.cabinair_temp) (L.L.cabinair_lowoffset_ACtemp) < ||
	(L.L.cp_taster_heat_or_frost) ! &&
    (L.L.AC_error_type) 2 = ! &&
	(L.L.engine_n) 400 < ||
	(L.L.elec_busbar_main) ! ||
	{if}
		0 (S.L.cabinair_Vrate_cabinaircondition) (S.L.ac_compressor)
	{endif}

	(L.L.cabinair_Vrate_cabinaircondition) 0 >
	{if}
		(L.L.cp_klima_RPM) (L.S.Timegap) 100 * + 100 min (S.L.cp_klima_RPM)
	{else}
		(L.L.cp_klima_RPM) (L.S.Timegap) 100 * - 0 max (S.L.cp_klima_RPM)
	{endif}

	(L.L.cabinair_Vrate_cabinheater) 0 >
	{if}
		(L.L.cp_cabinheater_RPM) (L.S.Timegap) 100 * + 100 min (S.L.cp_cabinheater_RPM)
	{else}
		(L.L.cp_cabinheater_RPM) (L.S.Timegap) 100 * - 0 max (S.L.cp_cabinheater_RPM)
	{endif}

'Berechnung der Temperaturrate durch Motor und Abstrahlung an die Umwelt...
	(L.L.cabinair_Qrate_engine) (L.L.cabinair_Qrate_envir) - (C.L.cabinair_cvm) /
'...und Temperaturrate durch Passagiere...
	(C.L.cabinair_T_passenger) (L.L.Cabinair_Temp) - (C.L.cabinair_V) / (C.L.cabinair_Vrate_passenger) * (L.L.humans_count) * +
'...und dieser durch die Volumenströme durch Fenster und Türen:
	(L.S.Weather_Temperature) (L.L.Cabinair_Temp) - (C.L.cabinair_V) / (L.L.cabinair_Vrate_doorwindow) * +
'...und des Frontheizgerätes...
	(L.L.fanheater_t_target) (L.L.Cabinair_Temp) - (C.L.cabinair_V) / (L.L.cabinair_Vrate_fanheater) * +
'...und der Raumheizgeräte...
	(L.L.engine_temperature) (C.L.heat_exchanger_effectivity) * (L.L.Cabinair_Temp) - (C.L.cabinair_V) / (L.L.cabinair_Vrate_cabinheater) * +
'...und der Klimaanlage...
	16 (L.L.Cabinair_Temp) - (C.L.cabinair_V) / 3 * (L.L.cabinair_Vrate_cabinaircondition) * +
'...aufintegrieren:
	(L.S.Timegap) * (L.L.Cabinair_Temp) + (S.L.Cabinair_Temp)

'Calculation of the engine cooling rate by the heat exchangers in the heaters:

	(L.L.fanheater_t_target) (L.L.Cabinair_Temp) - 0 max (C.L.cabinair_V) / (L.L.cabinair_Vrate_fanheater) * 
	(L.L.engine_temperature) (C.L.heat_exchanger_effectivity) * (L.L.Cabinair_Temp) max (L.L.Cabinair_Temp) - (C.L.cabinair_V) / (L.L.cabinair_Vrate_cabinheater) * +
	(C.L.cabinair_cvm) * 8 * (S.L.cabinair_Qrate_engine_fanheatcooling)



'Calculation of the moisture rate by volumetric flows with the passengers:
	(C.L.cabinair_absHum_passenger) (L.L.Cabinair_absHum) - (C.L.cabinair_V) / (C.L.cabinair_Vrate_passenger) * (L.L.humans_count) *
'Berechnung der Feuchtigkeitsrate durch Volumenströme mit der Außenwelt:
	(L.S.Weather_AbsHum) (L.L.Cabinair_absHum) - (C.L.cabinair_V) / (L.L.cabinair_Vrate_doorwindow) * +
'Berechnung der Feuchtigkeitsrate durch Frontheizgerät
	(L.S.Weather_AbsHum) (L.L.Cabinair_absHum) - (C.L.cabinair_V) / (L.L.cabinair_Vrate_fanheater) * (L.L.cockpit_heizregler_ventilation_mode) 1 >= * + (S.L.cabinair_test)
'... aufintegrieren:
	(L.S.Timegap) * (L.L.Cabinair_absHum) + (S.L.Cabinair_absHum)



{end}


{macro:standheizung_frame}


	(L.L.cp_taster_standheizung_target) (L.L.elec_busbar_avail) &&
	{if}
		(L.L.standheizung_running) !
		{if}
			0 (S.L.standheizung_volume_stufe1) (S.L.standheizung_volume_stufe2)
			1 (S.L.standheizung_running)  
			0 (S.L.standheizung_stufe1_time_elapsed)
			1 (S.L.standheizung_stufe1) 
		{endif}
		1 (S.L.standheizung_target)
	
	{else}
		0 (S.L.standheizung_target)
	{endif}
	



'	Raufrödeln der Timer:
	(L.L.standheizung_running)
	{if}
		(L.L.standheizung_stufe1_time_elapsed) (L.S.Timegap) + (S.L.standheizung_stufe1_time_elapsed)
		(L.L.standheizung_stufe2_time_elapsed) (L.S.Timegap) + (S.L.standheizung_stufe2_time_elapsed)
	{endif}

'	Einschalten der 2. Stufe:
	(L.L.standheizung_target) (L.L.standheizung_stufe1_time_elapsed) (C.L.standheizung_vorlauf) > &&
	(L.L.engine_temperature) (C.L.standheizung_brenner_t_ein) < &&
	{if}
		(L.L.standheizung_stufe2) !
		{if}
			0 (S.L.standheizung_stufe2_time_elapsed)
		{endif}
		1 (S.L.standheizung_stufe2)
	{endif}

'	Ausschalten der 2. Stufe:
	(L.L.standheizung_target) ! (L.L.standheizung_stufe2_time_elapsed) (C.L.standheizung_minlauf) > &&
	(L.L.engine_temperature) (C.L.standheizung_brenner_t_aus) > ||
	{if}
		(L.L.standheizung_stufe2)
		{if}
			0 (S.L.standheizung_stufe1_time_elapsed)
		{endif}
		0 (S.L.standheizung_stufe2) 
	{endif}

'	Ausschalten der 1. Stufe:
	(L.L.standheizung_target) ! (L.L.standheizung_stufe1_time_elapsed) (C.L.standheizung_nachlauf) > && 
	{if}
		0 (S.L.standheizung_stufe1)
	{endif}

	(L.L.standheizung_stufe1) 
	{if}
		(L.L.standheizung_volume_stufe1) (L.S.Timegap) 3 / + 1 min (S.L.standheizung_volume_stufe1)
	{else}
		(L.L.standheizung_volume_stufe1) (L.S.Timegap) 3 / - 0 max (S.L.standheizung_volume_stufe1)
		0.01 <
		{if}
			0 (S.L.standheizung_running)
		{endif}
	{endif}

	(L.L.standheizung_stufe2) 
	{if}
		(L.L.standheizung_volume_stufe2) (L.S.Timegap) 4 / + 1 min (S.L.standheizung_volume_stufe2)

'		Berechnung der Temperaturveränderung:
		(C.L.heizung_Qrate_standheizung) (L.L.cabinair_Qrate_envir) - (C.L.engine_cvm_engine) / (L.S.Timegap) * (L.L.engine_temperature) + (S.L.engine_temperature) 


	{else}
		(L.L.standheizung_volume_stufe2) (L.S.Timegap) 4 / - 0 max (S.L.standheizung_volume_stufe2)
	{endif}



{end}

{macro:heizung_blink}
'   configura o temporizador
    (L.L.heizung_display_BlinkTimer) 0.5 <
    {if}					
        (L.S.Timegap) (L.L.heizung_display_BlinkTimer) + (S.L.heizung_display_BlinkTimer) 										
    {else}
        0 (S.L.heizung_display_BlinkTimer) 	
        (L.L.heizung_display_Blink) ! (S.L.heizung_display_Blink)				
    {endif}	
'   configura a variavel se pisca ou nao a luz
    (L.L.heizung_display_Blink) ! (S.L.heizung_display)
{end}

{macro:kippschaltersound}
	l0
	{if}
		(T.L.ev_kippschalter_ein)
	{else}
		(T.L.ev_kippschalter_aus)
	{endif}	
{end}