Skip to content

Commit

Permalink
Merge pull request #99 from DewGew/DewGew-patch-2
Browse files Browse the repository at this point in the history
Merge setpoint devices to device types HEATER, WATERHEATER, OVEN
  • Loading branch information
DewGew authored Feb 11, 2024
2 parents 03c6e9d + 12ce46e commit a7e576e
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 47 deletions.
15 changes: 0 additions & 15 deletions .github/workflows/stale.yml

This file was deleted.

8 changes: 5 additions & 3 deletions VERSION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
24.8
- Sync devices when saving device config
- Added more API
24.9
- Added Timer trait, a timer script is needed read in wiki
- Added temepeture control trait
- Added merge setpoint to Heater, waterheater, oven types.
- Small fixes
- Added already in state error message
- Added REST API read more in wiki
21 changes: 17 additions & 4 deletions modules/domoticz.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def getAog(device, user_id=None):
st = desc.get('devicetype', None)
if st is not None and st.lower() in config.TYPES:
aog.type = 'action.devices.types.' + st.upper()
if domain in ['Thermostat', 'Setpoint']:
if domain in ['Thermostat', 'Setpoint', 'OnOff']:
minT = desc.get('minThreehold', None)
if minT is not None:
minThreehold = minT
Expand All @@ -170,6 +170,10 @@ def getAog(device, user_id=None):
modes_idx = desc.get('selector_modes_idx', None)
if modes_idx is not None:
aog.customData['selector_modes_idx'] = modes_idx
if domain in ['OnOff']:
thermo_idx = desc.get('merge_thermo_idx', None)
if thermo_idx is not None:
aog.customData['merge_thermo_idx'] = thermo_idx
if domain in ['Doorbell', 'Camera']:
camurl = desc.get('camurl', None)
if camurl:
Expand Down Expand Up @@ -312,12 +316,12 @@ def getAog(device, user_id=None):
'queryOnlyTemperatureSetting': True,
'availableThermostatModes': ['heat', 'cool'],
}
if domain in ['Thermostat', 'Setpoint']:
if domain in ['Thermostat', 'Setpoint', 'Setpoint_Hidden']:
aog.traits.append('action.devices.traits.TemperatureSetting')
aog.attributes = {'thermostatTemperatureUnit': dbsettings.tempunit,
'thermostatTemperatureRange': {
'minThresholdCelsius': minThreehold,
'maxThresholdCelsius': maxThreehold},
'minThresholdCelsius': (minThreehold if dbsettings.tempunit == 'C' else (minThreehold-32)/1.8),
'maxThresholdCelsius': (maxThreehold if dbsettings.tempunit == 'C' else (maxThreehold-32)/1.8)},
'availableThermostatModes': ['heat', 'cool'],
}
if 'selector_modes_idx' in aog.customData:
Expand Down Expand Up @@ -351,6 +355,15 @@ def getAog(device, user_id=None):
'cameraStreamNeedAuthToken': False
}

if domain in ['OnOff'] and aog.type in ['action.devices.types.HEATER', 'action.devices.types.WATERHEATER', 'action.devices.types.KETTLE', 'action.devices.types.OVEN']:
if 'merge_thermo_idx' in aog.customData:
aog.traits.append('action.devices.traits.TemperatureControl')
aog.attributes['temperatureUnitForUX'] = dbsettings.tempunit
aog.attributes['temperatureRange'] = {
'minThresholdCelsius': (minThreehold if dbsettings.tempunit == 'C' else (minThreehold-32)/1.8),
'maxThresholdCelsius': (maxThreehold if dbsettings.tempunit == 'C' else (maxThreehold-32)/1.8)}
aog.attributes['temperatureStepCelsius'] = (5 if dbsettings.tempunit == 'C' else 2.778)

if domain in ['OnOff', 'Dimmer', 'ColorSwitch']:
aog.traits.append('action.devices.traits.Timer')
aog.attributes['maxTimerLimitSec'] = 7200
Expand Down
7 changes: 7 additions & 0 deletions modules/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def devices():
actual_temp_idx = request.form.get('actual_temp_idx')
selector_modes_idx = request.form.get('selector_modes_idx')
check_state = request.form.get('checkState')
merge_thermo_idx = request.form.get('merge_thermo_idx')

if idx not in deviceconfig.keys():
deviceconfig[idx] = {}
Expand Down Expand Up @@ -137,6 +138,12 @@ def devices():
deviceconfig[idx].update({'selector_modes_idx': selector_modes_idx})
elif idx in deviceconfig.keys() and 'selector_modes_idx' in deviceconfig[idx]:
deviceconfig[idx].pop('selector_modes_idx')

if merge_thermo_idx is not None:
if merge_thermo_idx != '':
deviceconfig[idx].update({'merge_thermo_idx': merge_thermo_idx})
elif idx in deviceconfig.keys() and 'merge_thermo_idx' in deviceconfig[idx]:
deviceconfig[idx].pop('merge_thermo_idx')

if camurl is not None:
if camurl != '':
Expand Down
34 changes: 25 additions & 9 deletions modules/trait.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ def query(custom_data, device, user_id):
if domain in ['Temp', 'TempHumidity', 'TempHumidityBaro']:
current_temp = float(state['Temp'])
response['temperatureAmbientCelsius'] = round(_tempConvert(current_temp, dbsettings.tempunit), 1)
if domain in ['OnOff'] and 'merge_thermo_idx' in custom_data:
merged_state = getDomoticzState(user_id, custom_data['merge_thermo_idx'])
current_temp = float(merged_state['Data'])
response['temperatureAmbientCelsius'] = round(_tempConvert(current_temp, dbsettings.tempunit), 1)

if 'action.devices.traits.Toggles' in device['traits']:
levelName = base64.b64decode(state.get("LevelNames")).decode('UTF-8').split("|")
Expand Down Expand Up @@ -124,12 +128,12 @@ def query(custom_data, device, user_id):
response["isArmed"] = state['Data'] != "Normal"
if response["isArmed"]:
response["currentArmLevel"] = state['Data']

if 'action.devices.traits.EnergyStorage' in device['traits']:
if state['BatteryLevel'] is not None:
battery = state['BatteryLevel']
if battery != 255:
if battery == 100:
if battery >= 100:
descriptive_capacity_remaining = "FULL"
elif 50 <= battery < 100:
descriptive_capacity_remaining = "HIGH"
Expand All @@ -139,13 +143,12 @@ def query(custom_data, device, user_id):
descriptive_capacity_remaining = "LOW"
elif 0 <= battery < 10:
descriptive_capacity_remaining = "CRITICALLY_LOW"

response['descriptiveCapacityRemaining'] = descriptive_capacity_remaining
response['capacityRemaining'] = [{
'unit': 'PERCENTAGE',
'rawValue': battery
}]


response['online'] = True
if domain not in ['Group', 'Scene'] and state['BatteryLevel'] is not None and state['BatteryLevel'] != 255:
Expand Down Expand Up @@ -178,7 +181,7 @@ def execute(device, command, params, user_id, challenge):
else:
data = state['Data']
url += 'switchlight&idx=' + idx + '&switchcmd='

if check_state:
if params['on'] is True and data == 'Off':
url += 'On'
Expand All @@ -187,15 +190,15 @@ def execute(device, command, params, user_id, challenge):
else:
raise SmartHomeError('alreadyInState',
'Unable to execute {} for {}. Already in state '.format(command, device['id']))
else:
else:
url += ('On' if params['on'] else 'Off')

response['on'] = params['on']

if command == 'action.devices.commands.LockUnlock':

url += 'switchlight&idx=' + idx + '&switchcmd='

if check_state:
if params['lock'] is True and state['Data'] == 'Unlocked':
url += ('Off' if domain in ['DoorLockInverted'] else 'On')
Expand Down Expand Up @@ -276,7 +279,7 @@ def execute(device, command, params, user_id, challenge):
else:
p = params.get('openPercent', 50)
url += 'switchlight&idx=' + idx + '&switchcmd='

if check_state:
if p == 100 and state['Data'] in ['Closed', 'Stopped']:
url += 'Open'
Expand Down Expand Up @@ -357,6 +360,19 @@ def execute(device, command, params, user_id, challenge):

url += 'customevent&event=TIMER&data={"idx":' + idx + ',"cancel":true}'

if command == 'action.devices.commands.TimerStart':

url += 'customevent&event=TIMER&data={"idx":' + idx + ',"time":' + str(params['timerTimeSec']) + ',"on":true}'

if command == 'action.devices.commands.TimerCancel':

url += 'customevent&event=TIMER&data={"idx":' + idx + ',"cancel":true}'

if command == 'action.devices.commands.SetTemperature':
if 'merge_thermo_idx' in custom_data:
url += 'setsetpoint&idx=' + custom_data['merge_thermo_idx'] + '&setpoint=' + str(
params['temperature'])

if state['Protected'] is True:
url = url + '&passcode=' + challenge.get('pin')

Expand Down
75 changes: 61 additions & 14 deletions templates/devices.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h5 class="card-title">Added devices <span>| {{ user.username }}</span></h5>
<th class="pointer" scope="row" data-bs-toggle="modal" data-bs-target="#devicesModal_{{ k }}">{{ k }}</th>

<div class="modal fade" id="devicesModal_{{ k }}" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Sync request json for {{ k }}</h5>
Expand All @@ -57,15 +57,15 @@ <h5 class="modal-title">Sync request json for {{ k }}</h5>
<div class="modal-body">
<pre id="json_{{ v['customData']['idx'] }}">
</pre>
<!-- <div class="modal-footer">
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div> -->
<!-- <button type="button" class="btn btn-primary">Save changes</button> -->
</div>
</div>
</div>
</div><!-- End Vertically centered Modal-->

<td>{{ v['name']['name'] }}</td>
<td>{{ v['name']['name'] }} <small class="form-text">{% if v['customData']['merge_thermo_idx'] %}(Merged with idx:{{ v['customData']['merge_thermo_idx'] }}){% elif v['customData']['actual_temp_idx']%}(Merged with idx:{{ v['customData']['actual_temp_idx'] }}){% endif %}</small></td>
<td class="text-primary pointer" data-bs-toggle="modal" data-bs-target="#descriptionModal_{{ k }}" >{{ v['customData']['domain'] }}</td>
<div class="modal fade" id="descriptionModal_{{ k }}" tabindex="-1">
<div class="modal-dialog modal-lg">
Expand Down Expand Up @@ -234,17 +234,26 @@ <h5 class="card-title">Description <span>| {{ v['name']['name'] }}</span></h5>
</select>
</div>
</div>
{% if (v['customData']['domain'] in ['Thermostat', 'Setpoint']) %}
{% endif %}
{% if (v['customData']['domain'] in ['Thermostat', 'Setpoint', 'Setpoint_Hidden']) %}
<div class="row mb-3">
<label for="inputText" class="col-sm-3 col-form-label">Min Threehold</label>
<label for="inputText" class="col-sm-3 col-form-label">Min Threehold {{ dbsettings.tempunit }}&#176;</label>
<div class="col-sm-2">
{% if dbsettings.tempunit == 'F'%}
<input type="number" class="form-control" name="minThreehold" value="{{ ((v['attributes']['thermostatTemperatureRange']['minThresholdCelsius']*1.8)+32)|round|int }}">
{% else %}
<input type="number" class="form-control" name="minThreehold" value="{{ v['attributes']['thermostatTemperatureRange']['minThresholdCelsius'] }}">
{% endif %}
</div>
</div>
<div class="row mb-3">
<label for="inputText" class="col-sm-3 col-form-label">Max Threehold</label>
<label for="inputText" class="col-sm-3 col-form-label">Max Threehold {{ dbsettings.tempunit }}&#176;</label>
<div class="col-sm-2">
{% if dbsettings.tempunit == 'F'%}
<input type="number" class="form-control" name="maxThreehold" value="{{ ((v['attributes']['thermostatTemperatureRange']['maxThresholdCelsius']*1.8)+32)|round|int }}">
{% else %}
<input type="number" class="form-control" name="maxThreehold" value="{{ v['attributes']['thermostatTemperatureRange']['maxThresholdCelsius'] }}">
{% endif %}
</div>
</div>
{% endif %}
Expand All @@ -256,7 +265,45 @@ <h5 class="card-title">Description <span>| {{ v['name']['name'] }}</span></h5>
</div>
</div>
{% endif %}
{% if v['customData']['domain'] in ['Thermostat', 'Setpoint'] %}
{% if v['customData']['domain'] in ['OnOff'] and v['type'] in ['action.devices.types.HEATER', 'action.devices.types.WATERHEATER', 'action.devices.types.KETTLE', 'action.devices.types.OVEN'] %}
{% if v['customData']['merge_thermo_idx'] %}
<div class="row mb-3">
<label for="inputText" class="col-sm-3 col-form-label">Min Threehold {{ dbsettings.tempunit }}&#176;</label>
<div class="col-sm-2">
{% if dbsettings.tempunit == 'F'%}
<input type="number" class="form-control" name="minThreehold" readonly value="{{ ((devices['Setpoint_' + v['customData']['merge_thermo_idx']]['attributes']['thermostatTemperatureRange']['minThresholdCelsius']*1.8)+32)|round|int }}">
{% else %}
<input type="number" class="form-control" name="minThreehold" readonly value="{{ devices['Setpoint_' + v['customData']['merge_thermo_idx']]['attributes']['thermostatTemperatureRange']['minThresholdCelsius']|round|int }}">
{% endif %}
</div>
</div>
<div class="row mb-3">
<label for="inputText" class="col-sm-3 col-form-label">Max Threehold {{ dbsettings.tempunit }}&#176;</label>
<div class="col-sm-2">
{% if dbsettings.tempunit == 'F'%}
<input type="number" class="form-control" name="maxThreehold" readonly value="{{ ((devices['Setpoint_' + v['customData']['merge_thermo_idx']]['attributes']['thermostatTemperatureRange']['maxThresholdCelsius']*1.8)+32)|round|int }}">
{% else %}
<input type="number" class="form-control" name="maxThreehold" readonly value="{{ devices['Setpoint_' + v['customData']['merge_thermo_idx']]['attributes']['thermostatTemperatureRange']['maxThresholdCelsius']|round|int }}">
{% endif %}
</div>
</div>
{% endif %}
<div class="row mb-3">
<label for="inputText" class="col-sm-3 col-form-label">Get setpoint</label>
<div class="col-sm-6">
<select id="merge_thermo_idx" name="merge_thermo_idx" class="form-select" aria-describedby="actTempHelp">
<option value="" {% if v['customData']['merge_thermo_idx'] == None %}selected{% endif %} >None</option>
{% for n, p in devices.items() %}
{% if 'Setpoint' in n %}
<option value="{{ p['customData']['idx'] }}" {% if v['customData']['merge_thermo_idx'] == p['customData']['idx'] %}selected{% endif %}>{{ p['name']['name'].replace('_',' ') }}, idx: {{ p['customData']['idx'] }}</option>
{% endif %}
{% endfor %}
</select>
<div id="modesHelp" class="form-text">Control temp from a setpoint device.</div>
</div>
</div>
{% endif %}
{% if v['customData']['domain'] in ['Thermostat', 'Setpoint', 'Setpoint_Hidden'] %}
<div class="row mb-3">
<label for="inputText" class="col-sm-3 col-form-label">Get actual temp</label>
<div class="col-sm-6">
Expand All @@ -272,12 +319,12 @@ <h5 class="card-title">Description <span>| {{ v['name']['name'] }}</span></h5>
</div>
</div>
{% endif %}
{% if v['customData']['domain'] in ['Thermostat', 'Setpoint'] %}
{% if v['customData']['domain'] in ['Thermostat', 'Setpoint', 'Setpoint_Hidden'] %}
<div class="row mb-3">
<label for="inputText" class="col-sm-3 col-form-label">Get modes</label>
<div class="col-sm-6">
<select id="actual_temp_idx" name="actual_temp_idx" class="form-select" aria-describedby="modesHelp">
<option value="" {% if v['customData']['actual_temp_idx'] == None %}selected{% endif %} >None</option>
<select id="selector_modes_idx" name="selector_modes_idx" class="form-select" aria-describedby="modesHelp">
<option value="" {% if v['customData']['selector_modes_idx'] == None %}selected{% endif %} >None</option>
{% for n, p in devices.items() %}
{% if 'Selector' in n %}
<option value="{{ p['customData']['idx'] }}" {% if v['customData']['selector_modes_idx'] == p['customData']['idx'] %}selected{% endif %}>{{ p['name']['name'].replace('_',' ') }}, idx: {{ p['customData']['idx'] }}</option>
Expand All @@ -288,7 +335,7 @@ <h5 class="card-title">Description <span>| {{ v['name']['name'] }}</span></h5>
</div>
</div>
{% endif %}
{% endif %}

{% if (v['customData']['domain'] == 'Security' and user.admin) %}
<div class="row mb-3" {% if dbsettings.language == 'en' %}style="display: none;"{% endif %}>
<div id="armhome_div" class="col-md-12">
Expand Down Expand Up @@ -354,7 +401,7 @@ <h5 class="card-title">Description <span>| {{ v['name']['name'] }}</span></h5>
{% include 'footer.html' %}

<script>
var updateInterval = 15000
var updateInterval = 30000
var updateSwitches_block = [];
var updateScenes_block = [];
var updateDimmers_block = [];
Expand Down
4 changes: 2 additions & 2 deletions templates/serveradmin.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ <h5 class="card-title">Server settings <span>| Admin</span></h5>
<div class="col-6">
<label for="tempunit" class="form-label">Temperture unit</label>
<select id="tempunit" name="tempunit" class="form-select">
<option {% if dbsettings.language == 'C' %} selected {% endif %}value="C">Celsius</option>
<option {% if dbsettings.language == 'F' %} selected {% endif %}value="F">Fahrenheit</option>
<option {% if dbsettings.tempunit == 'C' %} selected {% endif %}value="C">Celsius</option>
<option {% if dbsettings.tempunit == 'F' %} selected {% endif %}value="F">Fahrenheit</option>
</select>
</div>
<div class="col-md-6">
Expand Down

0 comments on commit a7e576e

Please sign in to comment.