<?xml version="1.0" encoding="utf-8"?>
<Templates format="2" protocolVersion="83">
  <Template id="9ae5ac2b-0053-4643-84b1-ae350d11b6b8" revision="1.0">
    <SuggestedCCUParameters>
      <TcpPort>502</TcpPort>
      <ReadWriteTimeout>1000</ReadWriteTimeout>
    </SuggestedCCUParameters>
    <RevisionHistory>
      <Revision id="1.0">Initial version</Revision>
    </RevisionHistory>
    <Name>solvimus MBUS-GEM – M-Bus heat meter</Name>
    <CcuModel>ModbusTcpCCU</CcuModel>
    <Producer>solvimus</Producer>
    <Model>MBUS-GEM</Model>
    <Description/>
    <Category>2</Category>
    <ImportParameters>
      <Parameter>
        <Id>IpAddress</Id>
        <Name>${ipAddress}</Name>
        <Value>192.168.1.100</Value>
      </Parameter>
      <Parameter>
        <Id>SlaveId</Id>
        <Name>Modbus slave address of the meter (with Modbus multi slave: the number in the Register column of the meter row; without it: 255)</Name>
        <Value>1</Value>
      </Parameter>
    </ImportParameters>
    <Module>
      <Name>solvimus MBUS-GEM – heat meter</Name>
      <Id>-1</Id>
      <Model>ModbusModule</Model>
      <DeviceProperties>
        <IpAddress>$[IpAddress]</IpAddress>
        <Port>502</Port>
        <SlaveId>$[SlaveId]</SlaveId>
        <MaxPrefetchGroupSize>100</MaxPrefetchGroupSize>
        <PrefetchModeId>0</PrefetchModeId>
        <ModuleVariables>[{&quot;Name&quot;:&quot;RegMeter&quot;,&quot;ValueTypeId&quot;:1,&quot;NumericValue&quot;:10},{&quot;Name&quot;:&quot;RegEnergy&quot;,&quot;ValueTypeId&quot;:1,&quot;NumericValue&quot;:20},{&quot;Name&quot;:&quot;RegVolume&quot;,&quot;ValueTypeId&quot;:1,&quot;NumericValue&quot;:30},{&quot;Name&quot;:&quot;RegPower&quot;,&quot;ValueTypeId&quot;:1,&quot;NumericValue&quot;:40},{&quot;Name&quot;:&quot;RegFlow&quot;,&quot;ValueTypeId&quot;:1,&quot;NumericValue&quot;:50},{&quot;Name&quot;:&quot;RegFlowTemp&quot;,&quot;ValueTypeId&quot;:1,&quot;NumericValue&quot;:60},{&quot;Name&quot;:&quot;RegReturnTemp&quot;,&quot;ValueTypeId&quot;:1,&quot;NumericValue&quot;:70}]</ModuleVariables>
      </DeviceProperties>
      <Devices>
        <Device>
          <Name>Heat energy</Name>
          <Id>-2</Id>
          <Model>ModbusVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>15000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <PrefetchModeId>0</PrefetchModeId>
            <ReadState>VAR info := MODBUSR(H, RegEnergy+7, UInt16);
VAR unit := GETBITS(info, 0, 8);
VAR factor := SWITCH(unit, 5, 1000, 6, 3600000, 0);
IF GETBITS(info, 8, 8) != 0 OR factor = 0
    ADDERROR(1, &quot;RegEnergy does not point to an energy value (entry type &quot; + TOSTRING(GETBITS(info, 8, 8)) + &quot;, unit code &quot; + TOSTRING(unit) + &quot;) – copy the Register number of this value from the gateway Meter tab&quot;);
    RETURN(NaN);
END
RETURN(ROUND(MODBUSR(H, RegEnergy+4, Float) / factor * 10) / 10);</ReadState>
            <ReadScript>VAR meterInfo := MODBUSR(H, RegMeter+7, UInt16);
VAR medium := 0;
VAR flags := 0;
IF GETBITS(meterInfo, 8, 8) != 2
    ADDERROR(1, &quot;RegMeter does not point to a meter entry (entry type &quot; + TOSTRING(GETBITS(meterInfo, 8, 8)) + &quot;) – set RegMeter to the start of the meter entry (10 with Modbus multi slave, otherwise the Register number of the meter row in the gateway Meter tab)&quot;);
ELSE
    medium := GETBITS(MODBUSR(H, RegMeter+3, UInt16), 0, 8);
    IF medium != 4 AND medium != 10 AND medium != 11 AND medium != 12 AND medium != 13
        ADDWARNING(2, &quot;RegMeter points to a meter with medium code &quot; + TOSTRING(medium) + &quot;, which is not a heat meter – check that RegMeter and SlaveId belong to the heat meter&quot;);
    END
    flags := MODBUSR(H, RegMeter+8, UInt16);
    IF GETBIT(flags, 0)
        ADDERROR(3, &quot;The gateway could not read the meter in its last readout – check the M-Bus wiring, the meter address and the meter list of the gateway&quot;);
    ELSEIF GETBIT(flags, 1)
        ADDWARNING(4, &quot;Not all meter values were updated in the last gateway readout&quot;);
    END
END</ReadScript>
            <ServiceAttributesFormulas>[{&quot;AttributeDefinition&quot;:{&quot;Name&quot;:&quot;Meter serial number&quot;},&quot;ReadFormula&quot;:&quot;TOSTRING(MODBUSR(H, RegMeter+0, UInt32))&quot;},{&quot;AttributeDefinition&quot;:{&quot;Name&quot;:&quot;Last meter readout&quot;},&quot;ReadFormula&quot;:&quot;DATETIME t := NOW();\nVAR ts := MODBUSR(H, RegMeter+4, UInt32);\nIF(ts = 0, \&quot;No readout yet\&quot;, TOSTRING(ROUND((t.UNIXTIME - ts) / 60)) + \&quot; min ago\&quot;)&quot;}]</ServiceAttributesFormulas>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Heating water volume</Name>
          <Id>-3</Id>
          <Model>ModbusVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>15000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <PrefetchModeId>0</PrefetchModeId>
            <ReadState>VAR info := MODBUSR(H, RegVolume+7, UInt16);
VAR unit := GETBITS(info, 0, 8);
VAR factor := SWITCH(unit, 7, 1, 0);
IF GETBITS(info, 8, 8) != 0 OR factor = 0
    ADDERROR(1, &quot;RegVolume does not point to a volume value in m³ (entry type &quot; + TOSTRING(GETBITS(info, 8, 8)) + &quot;, unit code &quot; + TOSTRING(unit) + &quot;) – copy the Register number of this value from the gateway Meter tab&quot;);
    RETURN(NaN);
END
RETURN(ROUND(MODBUSR(H, RegVolume+4, Float) * factor * 1000) / 1000);</ReadState>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Thermal power</Name>
          <Id>-4</Id>
          <Model>ModbusVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>15000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <PrefetchModeId>0</PrefetchModeId>
            <ReadState>VAR info := MODBUSR(H, RegPower+7, UInt16);
VAR unit := GETBITS(info, 0, 8);
VAR factor := SWITCH(unit, 13, 1000, 14, 3600000, 0);
IF GETBITS(info, 8, 8) != 0 OR factor = 0
    ADDERROR(1, &quot;RegPower does not point to a power value (entry type &quot; + TOSTRING(GETBITS(info, 8, 8)) + &quot;, unit code &quot; + TOSTRING(unit) + &quot;) – copy the Register number of this value from the gateway Meter tab&quot;);
    RETURN(NaN);
END
RETURN(MODBUSR(H, RegPower+4, Float) / factor);</ReadState>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Volume flow</Name>
          <Id>-5</Id>
          <Model>ModbusVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>15000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <PrefetchModeId>0</PrefetchModeId>
            <ReadState>VAR info := MODBUSR(H, RegFlow+7, UInt16);
VAR unit := GETBITS(info, 0, 8);
VAR factor := SWITCH(unit, 15, 1, 16, 60, 17, 3600, 0);
IF GETBITS(info, 8, 8) != 0 OR factor = 0
    ADDERROR(1, &quot;RegFlow does not point to a volume flow value (entry type &quot; + TOSTRING(GETBITS(info, 8, 8)) + &quot;, unit code &quot; + TOSTRING(unit) + &quot;) – copy the Register number of this value from the gateway Meter tab&quot;);
    RETURN(NaN);
END
RETURN(MODBUSR(H, RegFlow+4, Float) * factor);</ReadState>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Flow temperature</Name>
          <Id>-6</Id>
          <Model>ModbusTemperatureSensor</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>15000</InternalPollInterval>
            <PrefetchModeId>0</PrefetchModeId>
            <TemperatureCalibration>0</TemperatureCalibration>
            <ReadTemperature>VAR info := MODBUSR(H, RegFlowTemp+7, UInt16);
VAR unit := GETBITS(info, 0, 8);
VAR factor := SWITCH(unit, 19, 1, 0);
IF GETBITS(info, 8, 8) != 0 OR factor = 0
    ADDERROR(1, &quot;RegFlowTemp does not point to a temperature value in °C (entry type &quot; + TOSTRING(GETBITS(info, 8, 8)) + &quot;, unit code &quot; + TOSTRING(unit) + &quot;) – copy the Register number of this value from the gateway Meter tab&quot;);
    RETURN(NaN);
END
RETURN(MODBUSR(H, RegFlowTemp+4, Float) * factor);</ReadTemperature>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Return temperature</Name>
          <Id>-7</Id>
          <Model>ModbusTemperatureSensor</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>15000</InternalPollInterval>
            <PrefetchModeId>0</PrefetchModeId>
            <TemperatureCalibration>0</TemperatureCalibration>
            <ReadTemperature>VAR info := MODBUSR(H, RegReturnTemp+7, UInt16);
VAR unit := GETBITS(info, 0, 8);
VAR factor := SWITCH(unit, 19, 1, 0);
IF GETBITS(info, 8, 8) != 0 OR factor = 0
    ADDERROR(1, &quot;RegReturnTemp does not point to a temperature value in °C (entry type &quot; + TOSTRING(GETBITS(info, 8, 8)) + &quot;, unit code &quot; + TOSTRING(unit) + &quot;) – copy the Register number of this value from the gateway Meter tab&quot;);
    RETURN(NaN);
END
RETURN(MODBUSR(H, RegReturnTemp+4, Float) * factor);</ReadTemperature>
          </DeviceProperties>
        </Device>
      </Devices>
    </Module>
  </Template>
</Templates>
