node-red-contrib-tado-client
Version:
Tado web API client node for Node Red
572 lines (527 loc) • 29 kB
HTML
<script type="text/x-red" data-template-name="tadox-token">
<div class="form-row">
<label for="node-input-configName"><i class="fa fa-server"></i> <span data-i18n="tado.label.config-name"></span></label>
<input type="text" id="node-input-configName">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('tadox-token', {
category: 'heating',
color: "rgb(255, 255, 255)",
defaults: {
configName: { type: "tadox-config", required: true },
},
inputs: 0,
outputs: 1,
icon: "tado.png",
});
</script>
<script type="text/x-red" data-template-name="tadox-config">
<div class="form-row">
<p>Please note that Tado no longer use the username/password authentication mechanism.</p>
<p>You must now use the device Oauth flow. Details of this can be found in the <a href="https://github.com/mattdavis90/node-red-contrib-tado-client?tab=readme-ov-file#getting-started">README</a></p>
</div>
<div class="form-row">
<label for="node-config-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-config-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('tadox-config', {
category: 'config',
color: "rgb(218, 196, 180)",
defaults: {
name: { value: "" }
},
label: function () {
return this.name || "TadoX Config";
}
});
</script>
<script type="text/x-red" data-template-name="tadox">
<div class="form-row">
<label for="node-input-configName"><i class="fa fa-server"></i> <span data-i18n="tado.label.config-name"></span></label>
<input type="text" id="node-input-configName">
</div>
<div class="form-row">
<label for="node-input-apiCall"><i class="fa fa-bolt"></i> <span data-i18n="tado.label.api-call"></span></label>
<select id="node-input-apiCall" style="width:60%; margin-right:5px;">
<optgroup data-i18n="[label]tado.optgroup.account">
<option value="authenticate" data-i18n="tado.option.authenticate"></option>
<option value="getMe" data-i18n="tado.option.get-me"></option>
<option value="getRatelimit" data-i18n="tado.option.get-ratelimit"></option>
</optgroup>
<optgroup data-i18n="[label]tado.optgroup.home">
<option value="getActionableDevices" data-i18n="tado.option.get-actionable-devices"></option>
<option value="getAirComfort" data-i18n="tado.option.get-air-comfort"></option>
<option value="getAirComfortDetailed" data-i18n="tado.option.get-air-comfort-detailed"></option>
<option value="getHeatingCircuits" data-i18n="tado.option.get-heating-circuits"></option>
<option value="getHome" data-i18n="tado.option.get-home"></option>
<option value="getHomeSummary" data-i18n="tado.option.get-home-summary"></option>
<option value="getInstallations" data-i18n="tado.option.get-installations"></option>
<option value="getState" data-i18n="tado.option.get-state"></option>
<option value="getUsers" data-i18n="tado.option.get-users"></option>
<option value="getWeather" data-i18n="tado.option.get-weather"></option>
<option value="getFeatures" data-i18n="tado.option.get-features"></option>
<option value="performQuickAction" data-i18n="tado.option.quick-action"></option>
</optgroup>
<optgroup data-i18n="[label]tado.optgroup.rooms">
<option value="getRoomsAndDevices" data-i18n="tado.option.get-rooms-and-devices"></option>
<option value="getRooms" data-i18n="tado.option.get-rooms"></option>
<option value="getRoomState" data-i18n="tado.option.get-room-state"></option>
<option value="manualControl" data-i18n="tado.option.manual-control"></option>
<option value="resumeSchedule" data-i18n="tado.option.resume-schedule"></option>
<option value="setChildlock" data-i18n="tado.option.set-child-lock"></option>
<option value="setDeviceTemperatureOffset" data-i18n="tado.option.set-device-temperature-offset"></option>
</optgroup>
<optgroup data-i18n="[label]tado.optgroup.flow-temperature-optimization">
<option value="getFlowTemperatureOptimization" data-i18n="tado.option.get-flow-temperature-optimization"></option>
<option value="enableFlowTemperatureOptimization" data-i18n="tado.option.enable-flow-temperature-optimization"></option>
<option value="disableFlowTemperatureOptimization" data-i18n="tado.option.disable-flow-temperature-optimization"></option>
<option value="setFlowTemperatureOptimization" data-i18n="tado.option.set-flow-temperature-optimization"></option>
</optgroup>
<optgroup data-i18n="[label]tado.optgroup.mobiledevice">
<option value="getMobileDevices" data-i18n="tado.option.get-mobile-devices"></option>
<option value="getMobileDevice" data-i18n="tado.option.get-mobile-device"></option>
<option value="getMobileDeviceSettings" data-i18n="tado.option.get-mobile-device-settings"></option>
<option value="setGeoTracking" data-i18n="tado.option.set-geo-tracking"></option>
</optgroup>
<optgroup data-i18n="[label]tado.optgroup.presence">
<option value="isAnyoneAtHome" data-i18n="tado.option.is-anyone-at-home"></option>
<option value="setPresence" data-i18n="tado.option.set-presence"></option>
<option value="updatePresence" data-i18n="tado.option.update-presence"></option>
</optgroup>
<optgroup data-i18n="[label]tado.optgroup.energy-iq">
<option value="getEnergyIQTariff" data-i18n="tado.option.get-energy-iq-tariff"></option>
<option value="addEnergyIQTariff" data-i18n="tado.option.add-energy-iq-tariff"></option>
<option value="updateEnergyIQTariff" data-i18n="tado.option.update-energy-iq-tariff"></option>
<option value="getEnergyIQOverview" data-i18n="tado.option.get-energy-iq-overview"></option>
<option value="getEnergyIQMeterReadings" data-i18n="tado.option.get-energy-iq-meter-readings"></option>
<option value="addEnergyIQMeterReading" data-i18n="tado.option.add-energy-iq-meter-readings"></option>
<option value="deleteEnergyIQMeterReading" data-i18n="tado.option.delete-energy-iq-meter-readings"></option>
</optgroup>
</select>
</div>
<div class="form-row" id="tadoHomeId">
<label for="node-input-homeId"><i class="fa fa-home"></i> <span data-i18n="tado.label.home-id"></span></label>
<input type="text" id="node-input-homeId" data-i18n="[placeholder]tado.label.home-id">
</div>
<div class="form-row" id="tadoDeviceId">
<label for="node-input-deviceId"><i class="fa fa-mobile"></i> <span data-i18n="tado.label.device-id"></span></label>
<input type="text" id="node-input-deviceId" data-i18n="[placeholder]tado.label.device-id">
</div>
<div class="form-row" id="tadoRoomId">
<label for="node-input-roomId"><i class="fa fa-th"></i> <span data-i18n="tado.label.room-id"></span></label>
<input type="text" id="node-input-roomId" data-i18n="[placeholder]tado.label.room-id">
</div>
<div class="form-row" id="tadoTimetableId">
<label for="node-input-timetableId"><i class="fa fa-home"></i> <span data-i18n="tado.label.timetable-id"></span></label>
<input type="text" id="node-input-timetableId" data-i18n="[placeholder]tado.label.timetable-id">
</div>
<div class="form-row" id="tadoTariffId">
<label for="node-input-tariffId"><i class="fa fa-search"></i> <span data-i18n="tado.label.tariff-id"></span></label>
<input type="text" id="node-input-tariffId" data-i18n="[placeholder]tado.label.tariff-id">
</div>
<div class="form-row" id="tadoReadingDate">
<label for="node-input-readingDate"><i class="fa fa-th"></i> <span data-i18n="tado.label.reading-date"></span></label>
<input type="text" id="node-input-readingDate" data-i18n="[placeholder]tado.label.reading-date">
</div>
<div class="form-row" id="tadoReportDate">
<label for="node-input-reportDate"><i class="fa fa-th"></i> <span data-i18n="tado.label.report-date"></span></label>
<input type="text" id="node-input-reportDate" data-i18n="[placeholder]tado.label.report-date">
</div>
<div class="form-row" id="tadoStartDate">
<label for="node-input-startDate"><i class="fa fa-th"></i> <span data-i18n="tado.label.start-date"></span></label>
<input type="text" id="node-input-startDate" data-i18n="[placeholder]tado.label.start-date">
</div>
<div class="form-row" id="tadoEndDate">
<label for="node-input-endDate"><i class="fa fa-th"></i> <span data-i18n="tado.label.end-date"></span></label>
<input type="text" id="node-input-endDate" data-i18n="[placeholder]tado.label.end-date">
</div>
<div id="tadoOverlayForm">
<div class="form-row" id="tadoPower">
<label for="node-input-power"><i class="fa fa-power-off"></i> <span data-i18n="tado.label.heating-power"></span></label>
<select id="node-input-power" style="width:60%; margin-right:5px;">
<option value="ON" data-i18n="tado.option.on"></option>
<option value="OFF" data-i18n="tado.option.off"></option>
</select>
</div>
<div id="tadoPowerForm">
<div class="form-row" id="tadoTemperature">
<label for="node-input-temperature"><i class="fa fa-thermometer-half"></i> <span data-i18n="tado.label.temperature"></span></label>
<input type="text" id="node-input-temperature" data-i18n="[placeholder]tado.label.temperature">
</div>
<div class="form-row" id="tadoTerminationType">
<label for="node-input-terminationType"><i class="fa fa-ban"></i> <span data-i18n="tado.label.termination-type"></span></label>
<select id="node-input-terminationType" style="width:60%; margin-right:5px;">
<option value="MANUAL" data-i18n="tado.option.manual"></option>
<option value="NEXT_TIME_BLOCK" data-i18n="tado.option.next-block"></option>
<option value="TIMER" data-i18n="tado.option.timer"></option>
</select>
</div>
<div class="form-row" id="tadoTerminationTimeout">
<label for="node-input-terminationTimeout"><i class="fa fa-history"></i> <span data-i18n="tado.label.termination-timeout"></span></label>
<input type="text" id="node-input-terminationTimeout" data-i18n="[placeholder]tado.label.termination-timeout">
</div>
</div>
</div>
<div class="form-row" id="tadoUnit">
<label for="node-input-unit"><i class="fa fa-credit-card"></i> <span data-i18n="tado.label.unit"></span></label>
<select id="node-input-unit" style="width:60%; margin-right:5px;">
<option value="m3" data-i18n="tado.option.unit-m3"></option>
<option value="kWh" data-i18n="tado.option.unit-kwh"></option>
</select>
</div>
<div class="form-row" id="tadoMaxTemperature">
<label for="node-input-maxTemperature"><i class="fa fa-thermometer-half"></i> <span data-i18n="tado.label.max-temperature"></span></label>
<input type="text" id="node-input-maxTemperature" data-i18n="[placeholder]tado.label.max-temperature">
</div>
<div class="form-row" id="tadoTariffInCents">
<label for="node-input-tariffInCents"><i class="fa fa-money"></i> <span data-i18n="tado.label.tariff-in-cents"></span></label>
<input type="text" id="node-input-tariffInCents" data-i18n="[placeholder]tado.label.tariff-in-cents">
</div>
<div class="form-row" id="tadoReading">
<label for="node-input-reading"><i class="fa fa-search"></i> <span data-i18n="tado.label.reading"></span></label>
<input type="text" id="node-input-reading" data-i18n="[placeholder]tado.label.reading">
</div>
<div class="form-row" id="tadoReadingId">
<label for="node-input-readingId"><i class="fa fa-search"></i> <span data-i18n="tado.label.reading-id"></span></label>
<input type="text" id="node-input-readingId" data-i18n="[placeholder]tado.label.reading-id">
</div>
<div class="form-row" id="tadoTemperatureOffset">
<label for="node-input-temperatureOffset"><i class="fa fa-thermometer-half"></i> <span data-i18n="tado.label.temperature-offset"></span></label>
<input type="text" id="node-input-temperatureOffset" data-i18n="[placeholder]tado.label.temperature-offset">
</div>
<div class="form-row" id="tadoPresence">
<label for="node-input-presence"><i class="fa fa-map-marker"></i> <span data-i18n="tado.label.presence"></span></label>
<select id="node-input-presence" style="width:60%; margin-right:5px;">
<option value="HOME" data-i18n="tado.option.home"></option>
<option value="AWAY" data-i18n="tado.option.away"></option>
<option value="AUTO" data-i18n="tado.option.auto-presence"></option>
</select>
</div>
<div class="form-row" id="tadoGeoTracking">
<label for="node-input-geoTracking"><i class="fa fa-map-marker"></i> <span data-i18n="tado.label.geo-tracking"></span></label>
<select id="node-input-geoTracking" style="width:60%; margin-right:5px;">
<option value="true" data-i18n="tado.option.enabled"></option>
<option value="false" data-i18n="tado.option.disabled"></option>
</select>
</div>
<div id="tadoQuickAction">
<div class="form-row">
<label for="node-input-quickAction"><i class="fa fa-bolt"></i> <span data-i18n="tado.label.quick-action"></span></label>
<select id="node-input-quickAction" style="width:60%; margin-right:5px;">
<option value="allOff" data-i18n="tado.option.all-off"></option>
<option value="resumeSchedule" data-i18n="tado.option.resume-schedule"></option>
<option value="boost" data-i18n="tado.option.boost"></option>
</select>
</div>
</div>
<div id="tadoChildlock">
<div class="form-row">
<label for="node-input-childlock"><i class="fa fa-windows"></i> <span data-i18n="tado.label.child-lock"></span></label>
<select id="node-input-childlock" style="width:60%; margin-right:5px;">
<option value="false" data-i18n="tado.option.unlocked"></option>
<option value="true" data-i18n="tado.option.locked"></option>
</select>
</div>
</div>
<div id="tadoDate">
<div class="form-row">
<label for="node-input-month"><span data-i18n="tado.label.month"></span></label>
<select id="node-input-month" style="width:60%; margin-right:5px;">
<option value="1" data-i18n="tado.option.january"></option>
<option value="2" data-i18n="tado.option.february"></option>
<option value="3" data-i18n="tado.option.march"></option>
<option value="4" data-i18n="tado.option.april"></option>
<option value="5" data-i18n="tado.option.may"></option>
<option value="6" data-i18n="tado.option.june"></option>
<option value="7" data-i18n="tado.option.july"></option>
<option value="8" data-i18n="tado.option.august"></option>
<option value="9" data-i18n="tado.option.september"></option>
<option value="10" data-i18n="tado.option.october"></option>
<option value="11" data-i18n="tado.option.november"></option>
<option value="12" data-i18n="tado.option.december"></option>
</select>
</div>
<div class="form-row">
<label for="node-input-year"><span data-i18n="tado.label.year"></span></label>
<input type="number" id="node-input-year" />
</div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
</script>
<script type="text/x-red" data-help-name="tadox">
<p>A Tado Web API node.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt class="optional">apiCall <span class="property-type">string</span></dt>
<dd> the API call to be made</dd>
<dt class="optional">homeId <span class="property-type">string</span></dt>
<dd> the home ID to target</dd>
<dt class="optional">deviceId <span class="property-type">string</span></dt>
<dd> the device ID to target</dd>
<dt class="optional">roomId <span class="property-type">string</span></dt>
<dd> the room ID to target</dd>
<dt class="optional">timetableId <span class="property-type">string</span></dt>
<dd> the timetable ID to target</dd>
<dt class="optional">power <span class="property-type">string</span></dt>
<dd> turn the heating system <code>"on"</code> or <code>"off"</code></dd>
<dt class="optional">reportDate <span class="property-type">string</span></dt>
<dd> the date in <code>yyyy-mm-dd</code> notation to fetch the report data from</dd>
<dt class="optional">temperature <span class="property-type">string</span></dt>
<dd> the target temperature</dd>
<dt class="optional">terminationType <span class="property-type">string</span></dt>
<dd> <code>"manual"</code>, <code>"auto"</code> or <code>"timer"</code></dd>
<dt class="optional">terminationTimeout <span class="property-type">string</span></dt>
<dd> the timeout in seconds to clear the overlay</dd>
<dt class="optional">presence <span class="property-type">string</span></dt>
<dd> <code>"home"</code>, <code>"away"</code> or <code>"auto"</code></dd>
<dt class="optional">geoTracking <span class="property-type">boolean</span></dt>
<dd> Enabled or disable Geo Tracking on a device</dd>
</dl>
<h3>Outputs</h3>
<dl class="message-properties">
<dt>topic <span class="property-type">object</span></dt>
<dd> the API call</dd>
<dt>payload <span class="property-type">object</span></dt>
<dd> the response from Tado</dd>
</dl>
<h3>Details</h3>
<p>Incoming messages trigger the API call. If the incoming message contains any of the optional fields then that node property is overwritten.</p>
<p><code>msg.topic</code> indicates the API call that generated the response. <code>msg.payload</code> is the response from Tado</p>
<p>For more information about the API responses see <a href="https://github.com/mattdavis90/node-tado-client">node-tado-client</a></p>
<h3>References</h3>
<ul>
<li><a href="http://blog.scphillips.com/posts/2017/01/the-tado-api-v2/">SCPhillips Blog</a></li>
</ul>
</script>
<script type="text/javascript">
RED.nodes.registerType('tadox', {
category: 'heating',
color: "rgb(255, 255, 255)",
defaults: {
apiCall: { value: "getMe" },
childlock: { value: false },
configName: { type: "tadox-config", required: true },
deviceId: { value: "" },
endDate: { value: "" },
geoTracking: { value: true },
homeId: { value: "" },
maxTemperature: { value: 0 },
month: { value: 1 },
name: { value: "" },
power: { value: "ON" },
presence: { value: "HOME" },
quickAction: { value: "allOf" },
reading: { value: 0 },
readingDate: { value: "" },
readingId: { value: "" },
reportDate: { value: "" },
roomId: { value: "" },
startDate: { value: "" },
tariffId: { value: "" },
tariffInCents: { value: 0, validate: function(v) { return v === undefined || RED.validators.number()(v); } },
temperature: { value: "18" },
temperatureOffset: { value: 0 },
terminationTimeout: { value: 900, validate: function(v) { return v === undefined || RED.validators.number()(v); } },
terminationType: { value: "manual" },
timetableId: { value: "" },
unit: { value: "m3" },
year: { value: 2025 },
},
inputs: 1,
outputs: 1,
icon: "tadox.png",
label: function () {
return this.name || `TadoX [${this.apiCall}]`;
},
labelStyle: function () {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function () {
$('#node-input-apiCall').change(function () {
const apiCall = $('#node-input-apiCall').val();
const action = $('#tadoQuickAction');
const childlock = $('#tadoChildlock');
const dateDiv = $('#tadoDate');
const device = $('#tadoDeviceId');
const endDate = $('#tadoEndDate');
const geoTracking = $('#tadoGeoTracking');
const home = $('#tadoHomeId');
const maxTemperature = $('#tadoMaxTemperature');
const overlay = $('#tadoOverlayForm');
const presence = $('#tadoPresence');
const reading = $('#tadoReading');
const readingDate = $('#tadoReadingDate');
const readingId = $('#tadoReadingId');
const reportDate = $('#tadoReportDate');
const startDate = $('#tadoStartDate');
const tariffId = $('#tadoTariffId');
const tariffInCents = $('#tadoTariffInCents');
const temperatureOffset = $('#tadoTemperatureOffset');
const timetable = $('#tadoTimetableId');
const unit = $('#tadoUnit');
const room = $('#tadoRoomId');
[
action,
childlock,
dateDiv,
device,
endDate,
geoTracking,
home,
maxTemperature,
overlay,
presence,
reading,
readingId,
readingDate,
reportDate,
startDate,
tariffId,
tariffInCents,
temperatureOffset,
timetable,
unit,
room,
].forEach(e => e.hide());
switch (apiCall) {
case "getMe":
break;
case "disableFlowTemperatureOptimization":
case "enableFlowTemperatureOptimization":
case "getActionableDevices":
case "getAirComfort":
case "getAirComfortDetailed":
case "getEnergyIQMeterReadings":
case "getEnergyIQTariff":
case "getFeatures":
case "getFlowTemperatureOptimization":
case "getHeatingCircuits":
case "getHome":
case "getHomeSummary":
case "getInstallations":
case "getMobileDevices":
case "getRooms":
case "getRoomsAndDevices":
case "getState":
case "getUsers":
case "getWeather":
case "isAnyoneAtHome":
case "updatePresence":
home.show();
break;
case "performQuickAction":
home.show();
action.show();
break;
case "setFlowTemperatureOptimization":
home.show();
maxTemperature.show();
break;
case "getRoomState":
case "resumeSchedule":
home.show();
room.show();
break;
case "manualControl":
home.show();
room.show();
overlay.show();
break;
case "setChildlock":
home.show();
device.show();
childlock.show();
break;
case "setDeviceTemperatureOffset":
home.show();
device.show();
temperatureOffset.show();
break;
case "getMobileDevice":
case "getMobileDeviceSettings":
home.show();
device.show();
break;
case "setGeoTracking":
home.show();
device.show();
geoTracking.show();
break;
case "setPresence":
home.show();
presence.show();
break;
case "addEnergyIQTariff":
home.show();
unit.show();
startDate.show();
endDate.show();
tariffInCents.show();
break;
case "getEnergyIQOverview":
home.show();
dateDiv.show();
break;
case "updateEnergyIQTariff":
home.show();
tariffId.show();
unit.show();
startDate.show();
endDate.show();
tariffInCents.show();
break;
case "addEnergyIQMeterReading":
home.show();
readingDate.show();
reading.show();
break;
case "deleteEnergyIQMeterReading":
home.show();
readingId.show();
break;
}
});
$('#node-input-power').change(function () {
const power = $('#node-input-power').val();
switch (power) {
case "on":
$('#tadoPowerForm').show();
break;
case "off":
$('#tadoPowerForm').hide();
break;
}
});
$('#node-input-terminationType').change(function () {
const terminationType = $('#node-input-terminationType').val();
switch (terminationType) {
case "manual":
case "auto":
$('#tadoTerminationTimeout').hide();
break;
case "timer":
$('#tadoTerminationTimeout').show();
break;
}
});
$('#node-input-defaultTerminationType').change(function () {
const terminationType = $('#node-input-defaultTerminationType').val();
switch (terminationType) {
case "MANUAL":
case "TADO_MODE":
$('#tadoDefaultTerminationTimeout').hide();
break;
case "TIMER":
$('#tadoDefaultTerminationTimeout').show();
break;
}
});
}
});
</script>