// Copyright (C) 2026 Fredrik Öhrström (gpl-3.0-or-later)
driver {
    name           = hydroclimav2
    meter_type     = HeatCostAllocationMeter
    default_fields = name,id,status,consumption_hca,average_ambient_temperature_c,timestamp
    manufacturer   = BMeters
    detect {
        mvt = BMP,53,08
        mvt = BMP,85,08
    }
    library {
        use = consumption_hca
        use = target_hca
        use = target_date
    }
    fields {
        field {
            name       = status
            quantity   = Text
            info       = 'Status and error flags'
            attributes = STATUS,INCLUDE_TPL_STATUS
        }
        field {
            name     = average_ambient_temperature
            quantity = Temperature
            match {
                measurement_type = Instantaneous
                vif_range        = ExternalTemperature
            }
        }
        field {
            name     = max_ambient_temperature
            quantity = Temperature
            match {
                measurement_type = Maximum
                vif_range        = ExternalTemperature
            }
        }
        field {
            name     = average_heater_temperature
            quantity = Temperature
            match {
                measurement_type = Instantaneous
                vif_range        = FlowTemperature
            }
        }
        field {
            name     = average_ambient_temperature_last_month
            quantity = Temperature
            match {
                measurement_type = Instantaneous
                vif_range        = ExternalTemperature
                storage_nr       = 1
            }
        }
        field {
            name     = average_heater_temperature_last_month
            quantity = Temperature
            match {
                measurement_type = Instantaneous
                vif_range        = FlowTemperature
                storage_nr       = 1
            }
        }
        field {
            name     = consumption_at_set_date_1
            quantity = HCA
            match {
                measurement_type = Instantaneous
                vif_range        = HeatCostAllocation
                storage_nr       = 2
            }
        }
        field {
            name     = consumption_at_set_date_2
            quantity = HCA
            match {
                measurement_type = Instantaneous
                vif_range        = HeatCostAllocation
                storage_nr       = 3
            }
        }
        field {
            name     = consumption_at_set_date_3
            quantity = HCA
            match {
                measurement_type = Instantaneous
                vif_range        = HeatCostAllocation
                storage_nr       = 4
            }
        }
        field {
            name     = consumption_at_set_date_4
            quantity = HCA
            match {
                measurement_type = Instantaneous
                vif_range        = HeatCostAllocation
                storage_nr       = 5
            }
        }
        field {
            name       = ambient_temperature_at_set_date_1
            quantity   = Temperature
            null_value = -327.68
            match {
                measurement_type = Instantaneous
                vif_range        = ExternalTemperature
                storage_nr       = 2
            }
        }
        field {
            name       = ambient_temperature_at_set_date_2
            quantity   = Temperature
            null_value = -327.68
            match {
                measurement_type = Instantaneous
                vif_range        = ExternalTemperature
                storage_nr       = 3
            }
        }
        field {
            name       = ambient_temperature_at_set_date_3
            quantity   = Temperature
            null_value = -327.68
            match {
                measurement_type = Instantaneous
                vif_range        = ExternalTemperature
                storage_nr       = 4
            }
        }
        field {
            name     = total_consumption
            quantity = HCA
            match {
                measurement_type = Instantaneous
                vif_range        = HeatCostAllocation
                storage_nr       = 10
            }
        }
        field {
            name       = mfct_specific_data
            quantity   = Text
            attributes = HIDE
            match {
                difvifkey = 0F
            }
            // An IXML grammar for decoding hydroclima telegrams.
            ixml = "decode = frame_v10 | frame_v11.
                    frame_v10 = '10',
                             StatusWord,
                             Time,
                             Date,
                             AverageAmbient,
                             MaxAmbient,
                             MaxAmbientDate,
                             NumMeasurements,
                             AverageAmbientPrev,
                             AverageHeaterPrev,
                             IU,
                             TotalIU.
                    frame_v11 = '11',
                             StatusWord, { STS Status word }
                             Time, { TIM Current time }
                             Date, { DAT Current date }
                             OpenDate, { DOP Housing open event date }
                             AverageHeater, { TKA Average heater temperature (current period) }
                             AverageAmbient, { TOA Average ambient temperature (current period) }
                             MaxAmbient, { TMH1 Max temperature (previous period) }
                             MaxAmbientDate, { TMHD1 Date of max temperature }
                             AverageHeaterPrev, { TKA1 Average heater temperature (previous period) }
                             AverageAmbientPrev, { TOA1 Average ambient temperature (previous period) }
                             CNI1, { CNI1 Consumption history LIFO 0 }
                             CNI2, { CNI2 Consumption history LIFO 1 }
                             CNI3, { CNI3 Consumption history LIFO 2 }
                             CNI4, { CNI4 Consumption history LIFO 3 }
                             TONI1, { TONI1 Ambient temp history LIFO 0 }
                             TONI2, { TONI2 Ambient temp history LIFO 1 }
                             TONI3, { TONI3 Ambient temp history LIFO 2 }
                             TempCounters, { TK Temperature bin counters }
                             TotalU. { U Total consumption all periods }
                    StatusWord = word.
                    Time = word.
                    Date = word.
                    OpenDate = word.
                    AverageHeater = word, @DV_flow_temp.
                    AverageAmbient = word, @DV_ext_temp.
                    MaxAmbient = word, @DV_max_ext_temp.
                    MaxAmbientDate = word.
                    AverageHeaterPrev = word, @DV_flow_temp_s1.
                    AverageAmbientPrev = word, @DV_ext_temp_s1.
                    CNI1 = word, @DV_hca_s2.
                    CNI2 = word, @DV_hca_s3.
                    CNI3 = word, @DV_hca_s4.
                    CNI4 = word, @DV_hca_s5.
                    TONI1 = word, @DV_ext_temp_s2.
                    TONI2 = word, @DV_ext_temp_s3.
                    TONI3 = word, @DV_ext_temp_s4.
                    TempCounters = triplet, triplet, triplet.
                    TotalU = triplet, @DV_hca_total.
                    IU = word.
                    TotalIU = triplet, @DV_hca_total.
                    NumMeasurements = word.
                    -hex  = ['A'-'F';'0'-'9'].
                    -byte = hex, hex.
                    -word = byte, byte.
                    -triplet = byte, byte, byte.
                    -quad = byte, byte, byte, byte.

                    DV_ext_temp>dvk = +'0265'. { int16 External temperature 10⁻² °C }
                    DV_flow_temp>dvk = +'0259'. { int16 Flow temperature 10⁻² °C }
                    DV_max_ext_temp>dvk = +'1265'. { max int16 External temperature 10⁻² °C }
                    DV_ext_temp_s1>dvk = +'4265'. { storage 1 int16 External temperature 10⁻² °C }
                    DV_flow_temp_s1>dvk = +'4259'. { storage 1 int16 Flow temperature 10⁻² °C }
                    DV_hca_s2>dvk = +'82016E'. { storage 2 int16 HCA }
                    DV_hca_s3>dvk = +'C2016E'. { storage 3 int16 HCA }
                    DV_hca_s4>dvk = +'82026E'. { storage 4 int16 HCA }
                    DV_hca_s5>dvk = +'C2026E'. { storage 5 int16 HCA }
                    DV_ext_temp_s2>dvk = +'820165'. { storage 2 int16 External temperature 10⁻² °C }
                    DV_ext_temp_s3>dvk = +'C20165'. { storage 3 int16 External temperature 10⁻² °C }
                    DV_ext_temp_s4>dvk = +'820265'. { storage 4 int16 External temperature 10⁻² °C }
                    DV_hca_total>dvk = +'83056E'. { storage 10 int24 HCA total }"
        }
    }
    tests {
        test {
            comment  = 'Version 0x53 frame_v10 NOKEY'
            args     = 'HCA hydroclimav2 68036198 NOKEY'
            telegram = 2e44b0099861036853087a000020002F2F036E0000000F100043106A7D2C4A078F12202CB1242A06D3062100210000
            json     = '{"_":"telegram","media":"heat cost allocation","meter":"hydroclimav2","name":"HCA","id":"68036198","average_ambient_temperature_c":18.66,"average_ambient_temperature_last_month_c":15.78,"average_heater_temperature_last_month_c":17.47,"consumption_hca":0,"max_ambient_temperature_c":47.51,"total_consumption_hca":33,"status":"OK","timestamp":"1111-11-11T11:11:11Z"}'
            fields   = 'HCA;68036198;OK;0;18.66;1111-11-11 11:11.11'
        }
        test {
            comment  = 'Version 0x85 frame_v11 encrypted'
            args     = 'HC1 hydroclimav2 93000952 NOKEY'
            telegram = 5144B0095209009385088C20807A800040252F2F_036E540200436ED90800426C3F3C0F1100009924293400003713DF08BC163633960E8208D401D90879076006DA080809DA08E537000A3500DF1201830900
            json     = '{"_":"telegram","media":"heat cost allocation","meter":"hydroclimav2","name":"HC1","id":"93000952","ambient_temperature_at_set_date_1_c":22.66,"ambient_temperature_at_set_date_2_c":23.12,"ambient_temperature_at_set_date_3_c":22.66,"average_ambient_temperature_c":22.71,"average_ambient_temperature_last_month_c":21.78,"average_heater_temperature_c":49.19,"average_heater_temperature_last_month_c":37.34,"consumption_at_set_date_1_hca":468,"consumption_at_set_date_2_hca":2265,"consumption_at_set_date_3_hca":1913,"consumption_at_set_date_4_hca":1632,"consumption_hca":596,"max_ambient_temperature_c":58.2,"target_date":"2025-12-31","target_hca":2265,"total_consumption_hca":2435,"status":"OK","timestamp":"1111-11-11T11:11:11Z"}'
            fields   = 'HC1;93000952;OK;596;22.71;1111-11-11 11:11.11'
        }
        test {
            comment  = 'Version 0x85 frame_v11 with TONI null sentinel 0x8000'
            args     = 'HC3 hydroclimav2 93001021 NOKEY'
            telegram = 5144b0092110009385088c20fb7afb4040252F2F_036E000000436E000000426C3F350F110001B9604734CE2E2708FD071B088832940766070000000000000000C407260800802DD400000000000000220000
            json     = '{"_":"telegram","media":"heat cost allocation","meter":"hydroclimav2","name":"HC3","id":"93001021","ambient_temperature_at_set_date_1_c":19.88,"ambient_temperature_at_set_date_2_c":20.86,"ambient_temperature_at_set_date_3_c":null,"average_ambient_temperature_c":20.45,"average_ambient_temperature_last_month_c":18.94,"average_heater_temperature_c":20.87,"average_heater_temperature_last_month_c":19.4,"consumption_at_set_date_1_hca":0,"consumption_at_set_date_2_hca":0,"consumption_at_set_date_3_hca":0,"consumption_at_set_date_4_hca":0,"consumption_hca":0,"max_ambient_temperature_c":20.75,"target_date":"2025-05-31","target_hca":0,"total_consumption_hca":34,"status":"UNKNOWN_40","timestamp":"1111-11-11T11:11:11Z"}'
            fields   = 'HC3;93001021;UNKNOWN_40;0;20.45;1111-11-11 11:11.11'
        }
    }
}