<?xml version="1.0" encoding="utf-8"?>
<Templates format="2" protocolVersion="83">
  <Template id="a3f7c2e1-84b0-4d6a-9c15-2f8e3a01b5d7" revision="1.1">
    <RevisionHistory>
      <Revision id="1.1">Template description added (shown in the TapHome app).</Revision>
    </RevisionHistory>
    <Name>EMS-ESP Gas Boiler (Bosch / Buderus / Junkers / Nefit)</Name>
    <CcuModel>PacketParserCCU</CcuModel>
    <Producer>EMS-ESP</Producer>
    <Model>EMS-ESP 3.8.6 Gas Boiler</Model>
    <Description>EMS bus gas boiler gateway via EMS-ESP 3.8.6 REST API. Supports Bosch, Buderus, Junkers, Nefit and Worcester gas boilers on EMS/EMS+/Heatronic 3 with RC310/HMC310/Rego/BC400 controller.</Description>
    <Category>1</Category>
    <ImportParameters>
      <Parameter>
        <Id>IpAddress</Id>
        <Name>Gateway IP Address</Name>
        <Value/>
      </Parameter>
      <Parameter>
        <Id>AccessToken</Id>
        <Name>EMS-ESP Access Token (admin user)</Name>
        <Value/>
      </Parameter>
    </ImportParameters>
    <Module>
      <Name>EMS-ESP Gateway</Name>
      <Id>-1</Id>
      <Model>PacketParserModuleHttp</Model>
      <DeviceProperties>
        <IpAddress>$[IpAddress]</IpAddress>
        <Port>80</Port>
        <UseHttps>False</UseHttps>
        <HttpAuthentification>0</HttpAuthentification>
        <InternalPollInterval>60000</InternalPollInterval>
        <CustomVariables>[{&quot;Name&quot;:&quot;AccessToken&quot;,&quot;ValueTypeId&quot;:2,&quot;NumericValue&quot;:0,&quot;StringValue&quot;:&quot;$[AccessToken]&quot;}]</CustomVariables>
        <ReadScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/system/info&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/system/info&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;system/info: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
ELSE
    VAR fahrenheit := PARSEJSON(r.Content, &quot;settings.fahrenheit&quot;, true);
    IF fahrenheit
        ADDERROR(&quot;EMS-ESP reports \u00b0F \u2014 switch Fahrenheit off in EMS-ESP Settings \u2192 Application&quot;);
    END
    VAR version := PARSEJSON(r.Content, &quot;system.version&quot;, true);
    IF !ISNULL(version)
        IF INDEXOF(TOSTRING(version), &quot;3.8.&quot;) != 0
            ADDWARNING(&quot;Template written for EMS-ESP 3.8.6, gateway reports &quot; + version);
        END
    END
END</ReadScriptPacketParser>
      </DeviceProperties>
      <Devices>
        <Device>
          <Name>Heating Circuit 1 Mode</Name>
          <Id>-2</Id>
          <Model>PacketParserMultiValueSwitch</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <ReadSwitchStateScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/mode&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/mode&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;hc1.mode: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR enumList := PARSEJSON(r.Content, &quot;enum&quot;, true);
VAR idx := PARSEJSON(r.Content, &quot;index&quot;, true);
IF ISNULL(enumList) OR ISNULL(idx)
    ADDERROR(&quot;hc1.mode: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
VAR text := PARSEJSON(r.Content, &quot;$.enum[&quot; + TOSTRING(idx) + &quot;]&quot;, true);
IF ISNULL(text)
    ADDERROR(&quot;hc1.mode: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
IF text = &quot;off&quot;
    RETURN(0);
ELSEIF text = &quot;manual&quot;
    RETURN(1);
ELSEIF text = &quot;auto&quot;
    RETURN(2);
ELSE
    ADDERROR(&quot;hc1.mode reports &apos;&quot; + text + &quot;&apos;: this template supports controllers with off / manual / auto and needs EMS-ESP Language = English (Settings \u2192 Application)&quot;);
    RETURN(NaN);
END</ReadSwitchStateScriptPacketParser>
            <WriteSwitchStateScriptPacketParser>VAR modeName := IF(Mu = 0, &quot;off&quot;, IF(Mu = 1, &quot;manual&quot;, &quot;auto&quot;));
VAR body := &quot;{\&quot;value\&quot;:\&quot;&quot; + modeName + &quot;\&quot;}&quot;;
VAR r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/mode&quot;, &quot;POST&quot;, body, &quot;Content-Type: application/json&quot;, &quot;Authorization: Bearer &quot; + AccessToken);
IF r.IsSuccess = false
    IF r.StatusCode = 401
        ADDERROR(&quot;hc1.mode write: access token missing or wrong (EMS-ESP Settings \u2192 Security \u2192 Manage Users \u2192 key icon of an admin user)&quot;);
    ELSE
        ADDERROR(&quot;hc1.mode write: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    END
END</WriteSwitchStateScriptPacketParser>
            <Value0>0</Value0>
            <Value0Index>0</Value0Index>
            <Value0Name>Off</Value0Name>
            <Value0IconId>4</Value0IconId>
            <Value1>1</Value1>
            <Value1Index>1</Value1Index>
            <Value1Name>Manual</Value1Name>
            <Value1IconId>1</Value1IconId>
            <Value2>2</Value2>
            <Value2Index>2</Value2Index>
            <Value2Name>Auto</Value2Name>
            <Value2IconId>3</Value2IconId>
            <Value3Index>67</Value3Index>
            <Value4Index>68</Value4Index>
            <Value5Index>69</Value5Index>
            <Value6Index>70</Value6Index>
            <Value7Index>71</Value7Index>
            <Value8Index>72</Value8Index>
            <Value9Index>73</Value9Index>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Room Thermostat HC1</Name>
          <Id>-3</Id>
          <Model>PacketParserThermostat</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <MinTemperature>0</MinTemperature>
            <MaxTemperature>30</MaxTemperature>
            <ShouldDoPeriodicWrite>False</ShouldDoPeriodicWrite>
            <ReadCurrentTemperatureScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/currtemp&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/currtemp&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;hc1.currtemp: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;hc1.currtemp: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadCurrentTemperatureScriptPacketParser>
            <ReadTemperatureSetPointScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/seltemp&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/seltemp&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;hc1.seltemp: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;hc1.seltemp: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadTemperatureSetPointScriptPacketParser>
            <WriteTemperatureSetPointScriptPacketParser>VAR body := &quot;{\&quot;value\&quot;:&quot; + Se + &quot;}&quot;;
VAR r := SENDHTTPREQUEST(&quot;/api/thermostat/hc1/seltemp&quot;, &quot;POST&quot;, body, &quot;Content-Type: application/json&quot;, &quot;Authorization: Bearer &quot; + AccessToken);
IF r.IsSuccess = false
    IF r.StatusCode = 401
        ADDERROR(&quot;hc1.seltemp write: access token missing or wrong (EMS-ESP Settings \u2192 Security \u2192 Manage Users \u2192 key icon of an admin user)&quot;);
    ELSE
        ADDERROR(&quot;hc1.seltemp write: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    END
END</WriteTemperatureSetPointScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Heating Active</Name>
          <Id>-4</Id>
          <Model>PacketParserReedContact</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <OnStateIconId>87</OnStateIconId>
            <OffStateIconId>88</OffStateIconId>
            <OnStateName>Active</OnStateName>
            <OffStateName>Inactive</OffStateName>
            <ReadStateScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/heatingactive&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/heatingactive&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;heatingactive: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;bool&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;heatingactive: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadStateScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Tap Water Heating Active</Name>
          <Id>-5</Id>
          <Model>PacketParserReedContact</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <OnStateIconId>87</OnStateIconId>
            <OffStateIconId>88</OffStateIconId>
            <OnStateName>Active</OnStateName>
            <OffStateName>Inactive</OffStateName>
            <ReadStateScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/tapwateractive&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/tapwateractive&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;tapwateractive: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;bool&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;tapwateractive: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadStateScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Flow Temperature</Name>
          <Id>-6</Id>
          <Model>PacketParserTemperatureSensor</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <ReadTemperatureScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/curflowtemp&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/curflowtemp&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;curflowtemp: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;curflowtemp: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadTemperatureScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Flow Temperature Target</Name>
          <Id>-7</Id>
          <Model>PacketParserVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <ReadStateScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/selflowtemp&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/selflowtemp&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;selflowtemp: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;selflowtemp: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadStateScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Burner Power</Name>
          <Id>-8</Id>
          <Model>PacketParserVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <ReadScriptPacketParser>SLEEP(60);
VAR rlc := SENDHTTPREQUEST(&quot;/api/boiler/lastcode&quot;);
IF rlc.StatusCode = 429
    SLEEP(200);
    rlc := SENDHTTPREQUEST(&quot;/api/boiler/lastcode&quot;);
END
IF rlc.IsSuccess = false
    ADDWARNING(1, &quot;lastcode: HTTP &quot; + rlc.StatusCode + IF(ISNULL(PARSEJSON(rlc.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(rlc.Content, &quot;message&quot;, true)));
ELSE
    VAR lc := PARSEJSON(rlc.Content, &quot;value&quot;, true);
    IF !ISNULL(lc)
        ADDINFO(1, &quot;Last error code (stored by the boiler): &quot; + lc);
    END
END</ReadScriptPacketParser>
            <ReadStateScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/curburnpow&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/curburnpow&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;curburnpow: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;curburnpow: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadStateScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>System Pressure</Name>
          <Id>-9</Id>
          <Model>PacketParserVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>60000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <ReadStateScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/syspress&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/syspress&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;syspress: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;syspress: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadStateScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Burner Starts</Name>
          <Id>-10</Id>
          <Model>PacketParserVariable</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>300000</InternalPollInterval>
            <IsReadOnly>True</IsReadOnly>
            <ReadStateScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/burnstarts&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/burnstarts&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;burnstarts: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;burnstarts: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadStateScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Domestic Hot Water</Name>
          <Id>-11</Id>
          <Model>PacketParserThermostat</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>30000</InternalPollInterval>
            <MinTemperature>10</MinTemperature>
            <MaxTemperature>70</MaxTemperature>
            <ShouldDoPeriodicWrite>False</ShouldDoPeriodicWrite>
            <ReadCurrentTemperatureScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/dhw/curtemp&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/dhw/curtemp&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;dhw.curtemp: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;dhw.curtemp: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadCurrentTemperatureScriptPacketParser>
            <ReadTemperatureSetPointScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/dhw/seltemp&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/dhw/seltemp&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;dhw.seltemp: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;dhw.seltemp: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadTemperatureSetPointScriptPacketParser>
            <WriteTemperatureSetPointScriptPacketParser>VAR body := &quot;{\&quot;value\&quot;:&quot; + ROUND(Se) + &quot;}&quot;;
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/dhw/seltemp&quot;, &quot;POST&quot;, body, &quot;Content-Type: application/json&quot;, &quot;Authorization: Bearer &quot; + AccessToken);
IF r.IsSuccess = false
    IF r.StatusCode = 401
        ADDERROR(&quot;dhw.seltemp write: access token missing or wrong (EMS-ESP Settings \u2192 Security \u2192 Manage Users \u2192 key icon of an admin user)&quot;);
    ELSE
        ADDERROR(&quot;dhw.seltemp write: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    END
END</WriteTemperatureSetPointScriptPacketParser>
          </DeviceProperties>
        </Device>
        <Device>
          <Name>Outdoor Temperature</Name>
          <Id>-12</Id>
          <Model>PacketParserTemperatureSensor</Model>
          <DeviceProperties>
            <DeviceType>0</DeviceType>
            <InternalPollInterval>60000</InternalPollInterval>
            <ReadTemperatureScriptPacketParser>SLEEP(60);
VAR r := SENDHTTPREQUEST(&quot;/api/boiler/outdoortemp&quot;);
IF r.StatusCode = 429
    SLEEP(200);
    r := SENDHTTPREQUEST(&quot;/api/boiler/outdoortemp&quot;);
END
IF r.IsSuccess = false
    ADDERROR(&quot;outdoortemp: HTTP &quot; + r.StatusCode + IF(ISNULL(PARSEJSON(r.Content, &quot;message&quot;, true)), &quot;&quot;, &quot;: &quot; + PARSEJSON(r.Content, &quot;message&quot;, true)));
    RETURN(NaN);
END
VAR v := PARSEJSON(r.Content, &quot;value&quot;, true);
IF ISNULL(v)
    ADDERROR(&quot;outdoortemp: no value from the gateway \u2014 this controller or unit does not report it; delete this device&quot;);
    RETURN(NaN);
END
RETURN(v);</ReadTemperatureScriptPacketParser>
          </DeviceProperties>
        </Device>
      </Devices>
    </Module>
  </Template>
</Templates>
