[homeconnect] Initial contribution (#9187)
Signed-off-by: Jonas Brüstel <jonas@bruestel.net> Co-authored-by: Laurent Garnier <lg.hc@free.fr>
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="homeconnect" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Home Connect Binding</name>
|
||||
<description>The binding integrates the Home Connect (https://www.home-connect.com/) system into openHAB. It connects
|
||||
to household devices from brands like Bosch and Siemens.</description>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,658 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="homeconnect"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Home Connect API Bridge -->
|
||||
<bridge-type id="api_bridge">
|
||||
<label>Home Connect API</label>
|
||||
<description>This bridge represents the gateway to the Home Connect API.</description>
|
||||
<config-description>
|
||||
<parameter name="clientId" type="text" required="true">
|
||||
<label>Client Id</label>
|
||||
<description>Application client id</description>
|
||||
</parameter>
|
||||
<parameter name="clientSecret" type="text" required="true">
|
||||
<label>Client Secret</label>
|
||||
<description>Application client secret</description>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
<parameter name="simulator" type="boolean" required="true">
|
||||
<label>Use Simulator Environment</label>
|
||||
<description>Use simulated environment at https://developer.home-connect.com/simulator/</description>
|
||||
<default>false</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
<!-- Dishwasher -->
|
||||
<thing-type id="dishwasher">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Dishwasher</label>
|
||||
<description>Home Connect connected dishwasher (e.g. Bosch or Siemens).</description>
|
||||
<channels>
|
||||
<channel id="power_state" typeId="system.power"/>
|
||||
<channel id="door_state" typeId="door_state"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_start_allowance_state" typeId="remote_start_allowance_state"/>
|
||||
<channel id="remote_control_active_state" typeId="remote_control_active_state"/>
|
||||
<channel id="selected_program_state" typeId="selected_program_state"/>
|
||||
<channel id="basic_actions_state" typeId="basic_actions_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="remaining_program_time_state" typeId="remaining_program_time_state"/>
|
||||
<channel id="program_progress_state" typeId="program_progress_state"/>
|
||||
<channel id="ambient_light_state" typeId="ambient_light_state"/>
|
||||
<channel id="ambient_light_brightness_state" typeId="system.brightness"/>
|
||||
<channel id="ambient_light_color_state" typeId="ambient_light_color_state"/>
|
||||
<channel id="ambient_light_custom_color_state" typeId="ambient_light_custom_color_state"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Oven -->
|
||||
<thing-type id="oven">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Oven</label>
|
||||
<description>Home Connect connected oven (e.g. Bosch or Siemens).</description>
|
||||
<channels>
|
||||
<channel id="power_state" typeId="system.power"/>
|
||||
<channel id="door_state" typeId="door_state"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_start_allowance_state" typeId="remote_start_allowance_state"/>
|
||||
<channel id="remote_control_active_state" typeId="remote_control_active_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="selected_program_state" typeId="selected_program_state"/>
|
||||
<channel id="setpoint_temperature" typeId="setpoint_temperature"/>
|
||||
<channel id="duration" typeId="duration"/>
|
||||
<channel id="basic_actions_state" typeId="basic_actions_state"/>
|
||||
<channel id="remaining_program_time_state" typeId="remaining_program_time_state"/>
|
||||
<channel id="program_progress_state" typeId="program_progress_state"/>
|
||||
<channel id="oven_current_cavity_temperature" typeId="oven_current_cavity_temperature"/>
|
||||
<channel id="elapsed_program_time" typeId="elapsed_program_time"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Washer -->
|
||||
<thing-type id="washer">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Washer</label>
|
||||
<description>Home Connect connected washing machine (e.g. Bosch or Siemens).</description>
|
||||
<channels>
|
||||
<channel id="door_state" typeId="door_state"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_start_allowance_state" typeId="remote_start_allowance_state"/>
|
||||
<channel id="remote_control_active_state" typeId="remote_control_active_state"/>
|
||||
<channel id="local_control_active_state" typeId="local_control_active_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="selected_program_state" typeId="selected_program_state"/>
|
||||
<channel id="laundry_care_washer_temperature" typeId="laundry_care_washer_temperature"/>
|
||||
<channel id="laundry_care_washer_spin_speed" typeId="laundry_care_washer_spin_speed"/>
|
||||
<channel id="laundry_care_washer_idos1" typeId="laundry_care_washer_idos1"/>
|
||||
<channel id="laundry_care_washer_idos2" typeId="laundry_care_washer_idos2"/>
|
||||
<channel id="basic_actions_state" typeId="basic_actions_state"/>
|
||||
<channel id="remaining_program_time_state" typeId="remaining_program_time_state"/>
|
||||
<channel id="program_progress_state" typeId="program_progress_state"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Washer dryer combination -->
|
||||
<thing-type id="washerdryer">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Washer Dryer Combination</label>
|
||||
<description>Home Connect connected combined washer dryer appliance.</description>
|
||||
<channels>
|
||||
<channel id="door_state" typeId="door_state"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_start_allowance_state" typeId="remote_start_allowance_state"/>
|
||||
<channel id="remote_control_active_state" typeId="remote_control_active_state"/>
|
||||
<channel id="local_control_active_state" typeId="local_control_active_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="selected_program_state" typeId="selected_program_state"/>
|
||||
<channel id="laundry_care_washer_temperature" typeId="laundry_care_washer_temperature"/>
|
||||
<channel id="laundry_care_washer_spin_speed" typeId="laundry_care_washer_spin_speed"/>
|
||||
<channel id="dryer_drying_target" typeId="dryer_drying_target"/>
|
||||
<channel id="basic_actions_state" typeId="basic_actions_state"/>
|
||||
<channel id="remaining_program_time_state" typeId="remaining_program_time_state"/>
|
||||
<channel id="program_progress_state" typeId="program_progress_state"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Dryer -->
|
||||
<thing-type id="dryer">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Dryer</label>
|
||||
<description>Home Connect connected dryer (e.g. Bosch or Siemens).</description>
|
||||
<channels>
|
||||
<channel id="door_state" typeId="door_state"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_start_allowance_state" typeId="remote_start_allowance_state"/>
|
||||
<channel id="remote_control_active_state" typeId="remote_control_active_state"/>
|
||||
<channel id="local_control_active_state" typeId="local_control_active_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="selected_program_state" typeId="selected_program_state"/>
|
||||
<channel id="dryer_drying_target" typeId="dryer_drying_target"/>
|
||||
<channel id="basic_actions_state" typeId="basic_actions_state"/>
|
||||
<channel id="remaining_program_time_state" typeId="remaining_program_time_state"/>
|
||||
<channel id="program_progress_state" typeId="program_progress_state"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Fridge Freezer -->
|
||||
<thing-type id="fridgefreezer">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Refrigerator / Freezer</label>
|
||||
<description>Home Connect connected refrigerator/freezer (e.g. Bosch or Siemens).</description>
|
||||
<channels>
|
||||
<channel id="door_state" typeId="door_state"/>
|
||||
<channel id="setpoint_temperature_refrigerator" typeId="setpoint_temperature_refrigerator"/>
|
||||
<channel id="super_mode_refrigerator" typeId="super_mode_refrigerator"/>
|
||||
<channel id="setpoint_temperature_freezer" typeId="setpoint_temperature_freezer"/>
|
||||
<channel id="super_mode_freezer" typeId="super_mode_freezer"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Coffee Machine -->
|
||||
<thing-type id="coffeemaker">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Coffee Machine</label>
|
||||
<description>Home Connect connected coffee machine (e.g. Bosch or Siemens).</description>
|
||||
<channels>
|
||||
<channel id="power_state" typeId="system.power"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_start_allowance_state" typeId="remote_start_allowance_state"/>
|
||||
<channel id="local_control_active_state" typeId="local_control_active_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="selected_program_state" typeId="selected_program_state"/>
|
||||
<channel id="basic_actions_state" typeId="basic_actions_state"/>
|
||||
<channel id="program_progress_state" typeId="program_progress_state"/>
|
||||
<channel id="coffeemaker_drip_tray_full_state" typeId="coffeemaker_drip_tray_full_state"/>
|
||||
<channel id="coffeemaker_water_tank_empty_state" typeId="coffeemaker_water_tank_empty_state"/>
|
||||
<channel id="coffeemaker_bean_container_empty_state" typeId="coffeemaker_bean_container_empty_state"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Hood -->
|
||||
<thing-type id="hood">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Hood</label>
|
||||
<description>Home Connect connected kitchen hood.</description>
|
||||
<channels>
|
||||
<channel id="power_state" typeId="system.power"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_start_allowance_state" typeId="remote_start_allowance_state"/>
|
||||
<channel id="remote_control_active_state" typeId="remote_control_active_state"/>
|
||||
<channel id="local_control_active_state" typeId="local_control_active_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="hood_venting_level" typeId="hood_venting_level"/>
|
||||
<channel id="hood_intensive_level" typeId="hood_intensive_level"/>
|
||||
<channel id="hood_program_state" typeId="hood_program_state"/>
|
||||
<channel id="ambient_light_state" typeId="ambient_light_state"/>
|
||||
<channel id="ambient_light_brightness_state" typeId="system.brightness"/>
|
||||
<channel id="ambient_light_color_state" typeId="ambient_light_color_state"/>
|
||||
<channel id="ambient_light_custom_color_state" typeId="ambient_light_custom_color_state"/>
|
||||
<channel id="functional_light_state" typeId="functional_light_state"/>
|
||||
<channel id="functional_light_brightness_state" typeId="system.brightness"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Cooktop -->
|
||||
<thing-type id="hob">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api_bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Cooktop</label>
|
||||
<description>Home Connect connected kitchen cooktop (hob).</description>
|
||||
<channels>
|
||||
<channel id="power_state" typeId="system.power"/>
|
||||
<channel id="operation_state" typeId="operation_state"/>
|
||||
<channel id="remote_control_active_state" typeId="remote_control_active_state"/>
|
||||
<channel id="local_control_active_state" typeId="local_control_active_state"/>
|
||||
<channel id="active_program_state" typeId="active_program_state"/>
|
||||
<channel id="selected_program_state" typeId="selected_program_state"/>
|
||||
</channels>
|
||||
<representation-property>haId</representation-property>
|
||||
<config-description>
|
||||
<parameter name="haId" type="text" required="true">
|
||||
<label>haId</label>
|
||||
<description>Unique identifier representing a specific home appliance.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Channel types -->
|
||||
<channel-type id="basic_actions_state">
|
||||
<item-type>String</item-type>
|
||||
<label>Program Actions</label>
|
||||
<state>
|
||||
<options>
|
||||
<option value="start">Start program</option>
|
||||
<option value="stop">Stop program</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="local_control_active_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Local Control State</label>
|
||||
<description>This status indicates whether the home appliance is currently manually controlled by the user operating
|
||||
the home appliance, e.g. opening the door or pressing a button.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="coffeemaker_drip_tray_full_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Drip Tray Full</label>
|
||||
<description>Is coffee maker drip tray full?</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="coffeemaker_water_tank_empty_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Water Tank Empty</label>
|
||||
<description>Is coffee maker water tank empty?</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="coffeemaker_bean_container_empty_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Bean Container Empty</label>
|
||||
<description>Is coffee maker bean container is empty?</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="door_state">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Door State</label>
|
||||
<description>This status describes the door state of a home appliance. A status change is either triggered by the user
|
||||
operating the home appliance locally (i.e. opening/closing door) or automatically by the home appliance (i.e. locking
|
||||
the door).</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="operation_state">
|
||||
<item-type>String</item-type>
|
||||
<label>Operation State</label>
|
||||
<description>This status describes the operation state of the home appliance.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="remote_start_allowance_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Remote Start Allowance State</label>
|
||||
<description>This status indicates whether the remote program start is enabled. This can happen due to a programmatic
|
||||
change (only disabling), or manually by the user changing the flag locally on the home appliance, or automatically
|
||||
after a certain duration - usually 24 hours.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="remote_control_active_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Remote Control Activation State</label>
|
||||
<description>This status indicates whether the allowance for remote controlling is enabled.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="active_program_state">
|
||||
<item-type>String</item-type>
|
||||
<label>Active Program</label>
|
||||
<description>This status describes the active program of the home appliance.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="selected_program_state">
|
||||
<item-type>String</item-type>
|
||||
<label>Selected Program</label>
|
||||
<description>This state describes the selected program of the home appliance.</description>
|
||||
</channel-type>
|
||||
<channel-type id="remaining_program_time_state">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Remaining Program Time</label>
|
||||
<description>This status indicates the remaining program time of the home appliance.</description>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="program_progress_state">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Progress State</label>
|
||||
<description>This status describes the program progress of the home appliance.</description>
|
||||
<state readOnly="true" min="0" max="100" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="oven_current_cavity_temperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Cavity Temperature</label>
|
||||
<description>This status describes the oven cavity temperature of the home appliance.</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="elapsed_program_time">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Elapsed Program Time</label>
|
||||
<description>This status describes the elapsed program time of the home appliance.</description>
|
||||
<state pattern="%d %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="setpoint_temperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Setpoint Temperature</label>
|
||||
<description>This status describes the intended cooking compartment temperature of the home appliance.</description>
|
||||
<state pattern="%.0f %unit%" step="1"/>
|
||||
</channel-type>
|
||||
<channel-type id="duration">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Selected Duration</label>
|
||||
<description>This status describes the duration of the program of the home appliance.</description>
|
||||
<state pattern="%d %unit%" step="60" min="60"/>
|
||||
</channel-type>
|
||||
<channel-type id="laundry_care_washer_temperature">
|
||||
<item-type>String</item-type>
|
||||
<label>Washing Program Temperature</label>
|
||||
<description>This status describes the temperature of the washing program of the home appliance.</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.Cold">Cold water</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC20">20 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC30">30 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC40">40 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC50">50 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC60">60 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC70">70 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC80">80 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.GC90">90 °C</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.Auto">Auto</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.UlCold">Cold (US/CA)</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.UlWarm">Warm (US/CA)</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.UlHot">Hot (US/CA)</option>
|
||||
<option value="LaundryCare.Washer.EnumType.Temperature.UlExtraHot">Extra hot (US/CA)</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="laundry_care_washer_spin_speed">
|
||||
<item-type>String</item-type>
|
||||
<label>Spin Speed</label>
|
||||
<description>This status defines the spin speed of a washer program of the home appliance.</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.Off">No spinning</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.RPM400">400 rpm</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.RPM600">600 rpm</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.RPM800">800 rpm</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.RPM1000">1000 rpm</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.RPM1200">1200 rpm</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.RPM1400">1400 rpm</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.RPM1600">1600 rpm</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.Auto">Auto</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.UlNo">No spinning (US/CA)</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.UlLow">Low (US/CA)</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.UlMedium">Medium (US/CA)</option>
|
||||
<option value="LaundryCare.Washer.EnumType.SpinSpeed.UlHigh">High (US/CA)</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="laundry_care_washer_idos1">
|
||||
<item-type>String</item-type>
|
||||
<label>i-Dos 1 Dosing Level</label>
|
||||
<description>This status defines the i-Dos dosing level of a washer program of the home appliance. (If appliance
|
||||
supports i-Dos)</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Off">Off</option>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Light">Light</option>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Normal">Normal</option>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Strong">Strong</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="laundry_care_washer_idos2">
|
||||
<item-type>String</item-type>
|
||||
<label>i-Dos 2 Dosing Level</label>
|
||||
<description>This status defines the i-Dos dosing level of a washer program of the home appliance. (If appliance
|
||||
supports i-Dos)</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Off">Off</option>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Light">Light</option>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Normal">Normal</option>
|
||||
<option value="LaundryCare.Washer.EnumType.IDosingLevel.Strong">Strong</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="setpoint_temperature_refrigerator">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Refrigerator Temperature</label>
|
||||
<description>Target temperature of the refrigerator compartment (Range depends on appliance - common range 2 to 8°C).</description>
|
||||
<state step="1" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="setpoint_temperature_freezer">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Freezer temperature</label>
|
||||
<description>Target temperature of the freezer compartment (Range depends on appliance - common range -16 to -24°C).</description>
|
||||
<state step="1" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="super_mode_refrigerator">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Refrigerator Super Mode</label>
|
||||
<description>The setting has no impact on setpoint temperatures but will make the fridge compartment cool to the
|
||||
lowest possible temperature until it is disabled manually by the customer or by the HA because of a timeout.</description>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
<channel-type id="super_mode_freezer">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Freezer Super Mode</label>
|
||||
<description>This setting has no impact on setpoint temperatures but will make the freezer compartment cool to the
|
||||
lowest possible temperature until it is disabled manually by the customer or by the home appliance because of a
|
||||
timeout.</description>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
<channel-type id="dryer_drying_target">
|
||||
<item-type>String</item-type>
|
||||
<label>Drying Target</label>
|
||||
<description>Specifies the desired dryness setting.</description>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
<channel-type id="hood_venting_level">
|
||||
<item-type>String</item-type>
|
||||
<label>Venting Level</label>
|
||||
<description>Current venting level of the hood.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="hood_intensive_level">
|
||||
<item-type>String</item-type>
|
||||
<label>Intensive level</label>
|
||||
<description>Current venting intensive level of the hood.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="hood_program_state">
|
||||
<item-type>String</item-type>
|
||||
<label>Program Actions</label>
|
||||
<description>Start hood program.</description>
|
||||
</channel-type>
|
||||
<channel-type id="functional_light_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Functional Light State</label>
|
||||
<description>This setting describes the current functional light state of the home appliance.</description>
|
||||
</channel-type>
|
||||
<channel-type id="ambient_light_state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Ambient Light State</label>
|
||||
<description>This setting describes the current ambient light state of the home appliance.</description>
|
||||
</channel-type>
|
||||
<channel-type id="ambient_light_color_state">
|
||||
<item-type>String</item-type>
|
||||
<label>Ambient Light Color</label>
|
||||
<description>This setting describes the color state of the ambient light.</description>
|
||||
<state readOnly="false">
|
||||
<options>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.CustomColor">Custom Color</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color1">Color 1</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color2">Color 2</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color3">Color 3</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color4">Color 4</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color5">Color 5</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color6">Color 6</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color7">Color 7</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color8">Color 8</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color9">Color 9</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color10">Color 10</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color11">Color 11</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color12">Color 12</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color13">Color 13</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color14">Color 14</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color15">Color 15</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color16">Color 16</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color17">Color 17</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color18">Color 18</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color19">Color 19</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color20">Color 20</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color21">Color 21</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color22">Color 22</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color23">Color 23</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color24">Color 24</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color25">Color 25</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color26">Color 26</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color27">Color 27</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color28">Color 28</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color29">Color 29</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color30">Color 30</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color31">Color 31</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color32">Color 32</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color33">Color 33</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color34">Color 34</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color35">Color 35</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color36">Color 36</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color37">Color 37</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color38">Color 38</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color39">Color 39</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color40">Color 40</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color41">Color 41</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color42">Color 42</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color43">Color 43</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color44">Color 44</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color45">Color 45</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color46">Color 46</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color47">Color 47</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color48">Color 48</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color49">Color 49</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color50">Color 50</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color51">Color 51</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color52">Color 52</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color53">Color 53</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color54">Color 54</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color55">Color 55</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color56">Color 56</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color57">Color 57</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color58">Color 58</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color59">Color 59</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color60">Color 60</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color61">Color 61</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color62">Color 62</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color63">Color 63</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color64">Color 64</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color65">Color 65</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color66">Color 66</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color67">Color 67</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color68">Color 68</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color69">Color 69</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color70">Color 70</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color71">Color 71</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color72">Color 72</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color73">Color 73</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color74">Color 74</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color75">Color 75</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color76">Color 76</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color77">Color 77</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color78">Color 78</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color79">Color 79</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color80">Color 80</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color81">Color 81</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color82">Color 82</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color83">Color 83</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color84">Color 84</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color85">Color 85</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color86">Color 86</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color87">Color 87</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color88">Color 88</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color89">Color 89</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color90">Color 90</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color91">Color 91</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color92">Color 92</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color93">Color 93</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color94">Color 94</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color95">Color 95</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color96">Color 96</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color97">Color 97</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color98">Color 98</option>
|
||||
<option value="BSH.Common.EnumType.AmbientLightColor.Color99">Color 99</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="ambient_light_custom_color_state">
|
||||
<item-type>Color</item-type>
|
||||
<label>Ambient Light (Custom)</label>
|
||||
<description>This setting describes the custom color state of the ambient light.</description>
|
||||
<category>Colorpicker</category>
|
||||
<tags>
|
||||
<tag>Lighting</tag>
|
||||
</tags>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
7
bundles/org.openhab.binding.homeconnect/src/main/resources/assets/css/bootstrap.min.css
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
body {
|
||||
font-size: .875rem;
|
||||
}
|
||||
|
||||
.feather {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100; /* Behind the navbar */
|
||||
padding: 48px 0 0; /* Height of navbar */
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
.sidebar-sticky {
|
||||
position: relative;
|
||||
top: 0;
|
||||
height: calc(100vh - 48px);
|
||||
padding-top: .5rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
|
||||
}
|
||||
|
||||
@supports ((position: -webkit-sticky) or (position: sticky)) {
|
||||
.sidebar-sticky {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sidebar .nav-link .feather {
|
||||
margin-right: 4px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover .feather,
|
||||
.sidebar .nav-link.active .feather {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sidebar-heading {
|
||||
font-size: .75rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/*
|
||||
* Navbar
|
||||
*/
|
||||
|
||||
.navbar-brand {
|
||||
padding-top: .75rem;
|
||||
padding-bottom: .75rem;
|
||||
font-size: 1rem;
|
||||
background-color: rgba(0, 0, 0, .25);
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
|
||||
}
|
||||
|
||||
.navbar .navbar-toggler {
|
||||
top: .25rem;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
.navbar .form-control {
|
||||
padding: .75rem 1rem;
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.form-control-dark {
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, .1);
|
||||
border-color: rgba(255, 255, 255, .1);
|
||||
}
|
||||
|
||||
.form-control-dark:focus {
|
||||
border-color: transparent;
|
||||
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/homeconnect/assets/favicon/mstile-150x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="256.000000pt" height="256.000000pt" viewBox="0 0 256.000000 256.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M1176 2309 c-360 -38 -677 -264 -831 -591 -65 -138 -87 -235 -92
|
||||
-403 -4 -125 -1 -167 15 -249 12 -54 24 -101 27 -104 3 -3 35 23 71 59 l65 65
|
||||
-12 74 c-24 154 9 357 82 503 159 316 487 506 838 484 379 -24 702 -297 791
|
||||
-667 24 -102 27 -281 6 -382 -70 -330 -344 -604 -674 -674 -103 -21 -281 -18
|
||||
-383 7 -154 39 -289 113 -403 223 l-59 57 -59 -58 -58 -57 43 -44 c218 -225
|
||||
565 -345 872 -302 619 86 1023 682 871 1282 -84 330 -328 603 -643 718 -147
|
||||
53 -318 75 -467 59z"/>
|
||||
<path d="M816 1299 c-251 -254 -456 -466 -456 -472 0 -13 72 -137 80 -137 3 0
|
||||
194 189 425 420 l420 420 321 -321 322 -322 22 43 c12 24 28 60 35 80 l13 37
|
||||
-357 357 c-196 196 -359 356 -363 356 -3 0 -211 -208 -462 -461z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
7
bundles/org.openhab.binding.homeconnect/src/main/resources/assets/js/bootstrap.bundle.min.js
vendored
Normal file
13
bundles/org.openhab.binding.homeconnect/src/main/resources/assets/js/feather.min.js
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
/* globals Chart:false, feather:false, Plotly:false, requests:false */
|
||||
|
||||
(function () {
|
||||
'use strict'
|
||||
|
||||
feather.replace();
|
||||
|
||||
$(".redirectUri").text(window.location.href.substring(0, window.location.href.lastIndexOf('/homeconnect') + 12));
|
||||
|
||||
$('#apiDetailModal').on('show.bs.modal', function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var thingId = button.data('thing-id');
|
||||
var action = button.data('api-action');
|
||||
var titleText = button.data('title');
|
||||
var modal = $(this);
|
||||
var title = modal.find('.modal-title');
|
||||
var subTitle = modal.find('.modal-subtitle');
|
||||
var responseBodyElement = modal.find('.modal-response-body');
|
||||
|
||||
responseBodyElement.text('Loading...');
|
||||
title.text(titleText);
|
||||
subTitle.text(thingId);
|
||||
modal.modal('handleUpdate');
|
||||
|
||||
let jqxhr = $.get('appliances?thingId=' + thingId + '&action=' + action, function (data) {
|
||||
responseBodyElement.text(JSON.stringify(data, null, '\t'));
|
||||
});
|
||||
jqxhr.fail(function (data) {
|
||||
responseBodyElement.text(JSON.stringify(data, null, '\t'));
|
||||
})
|
||||
jqxhr.always(function () {
|
||||
modal.modal('handleUpdate');
|
||||
});
|
||||
})
|
||||
|
||||
$('#rawCommandDetailModal').on('show.bs.modal', function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var thingId = button.data('thing-id');
|
||||
var haId = button.data('ha-id');
|
||||
|
||||
var modal = $(this);
|
||||
var subTitle = modal.find('.modal-subtitle');
|
||||
var inputPath = modal.find('#raw-path');
|
||||
var inputBody = modal.find('#raw-request-body');
|
||||
var submit = modal.find('#raw-submit');
|
||||
var responseBodyElement = modal.find('.modal-response-body');
|
||||
var responseTitle = modal.find('.raw-response-header');
|
||||
|
||||
subTitle.text(thingId);
|
||||
responseBodyElement.text('');
|
||||
responseTitle.hide();
|
||||
inputPath.val('/api/homeappliances/' + haId + '/programs/active')
|
||||
modal.modal('handleUpdate');
|
||||
|
||||
submit.click(function () {
|
||||
responseBodyElement.text('Loading...');
|
||||
let jqxhr = $.post('appliances?thingId=' + thingId + '&action=put-raw&path=' + inputPath.val(),
|
||||
inputBody.val(), function (data) {
|
||||
responseBodyElement.text(JSON.stringify(data, null, '\t'));
|
||||
responseTitle.show();
|
||||
});
|
||||
jqxhr.fail(function (data) {
|
||||
responseBodyElement.text(JSON.stringify(data, null, '\t'));
|
||||
responseTitle.show();
|
||||
})
|
||||
jqxhr.always(function () {
|
||||
modal.modal('handleUpdate');
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
$('#rawGetDetailModal').on('show.bs.modal', function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var thingId = button.data('thing-id');
|
||||
var haId = button.data('ha-id');
|
||||
|
||||
var modal = $(this);
|
||||
var subTitle = modal.find('.modal-subtitle');
|
||||
var inputPath = modal.find('#raw-get-path');
|
||||
var submit = modal.find('#raw-get-submit');
|
||||
var responseBodyElement = modal.find('.modal-response-body');
|
||||
var responseTitle = modal.find('.raw-response-header');
|
||||
|
||||
subTitle.text(thingId);
|
||||
responseBodyElement.text('');
|
||||
responseTitle.hide();
|
||||
inputPath.val('/api/homeappliances/' + haId + '/programs')
|
||||
modal.modal('handleUpdate');
|
||||
|
||||
submit.click(function () {
|
||||
responseBodyElement.text('Loading...');
|
||||
let jqxhr = $.post('appliances?thingId=' + thingId + '&action=get-raw&path=' + inputPath.val(), function (data) {
|
||||
responseBodyElement.text(JSON.stringify(data, null, '\t'));
|
||||
responseTitle.show();
|
||||
});
|
||||
jqxhr.fail(function (data) {
|
||||
responseBodyElement.text(JSON.stringify(data, null, '\t'));
|
||||
responseTitle.show();
|
||||
})
|
||||
jqxhr.always(function () {
|
||||
modal.modal('handleUpdate');
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
$('#requestDetailModal').on('show.bs.modal', function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var requestId = button.data('request-id');
|
||||
var request = requests.find(item => item.id == requestId);
|
||||
var requestHeader = request.homeConnectRequest.header;
|
||||
var requestBody = request.homeConnectRequest.body;
|
||||
var modal = $(this);
|
||||
var requestBodyElement = modal.find('.modal-request-body');
|
||||
var title = modal.find('.modal-title');
|
||||
var responseBodyElement = modal.find('.modal-response-body');
|
||||
var requestHeaderElement = modal.find('.modal-request-header');
|
||||
var responseHeaderElement = modal.find('.modal-response-header');
|
||||
|
||||
title.text(request.homeConnectRequest.method + ' ' + request.homeConnectRequest.url);
|
||||
|
||||
if (requestBody) {
|
||||
requestBodyElement.text(requestBody);
|
||||
requestBodyElement.removeClass('text-muted')
|
||||
} else {
|
||||
requestBodyElement.text('Empty request body');
|
||||
requestBodyElement.addClass('text-muted')
|
||||
}
|
||||
|
||||
if (request.homeConnectResponse && request.homeConnectResponse.body) {
|
||||
responseBodyElement.text(request.homeConnectResponse.body);
|
||||
responseBodyElement.removeClass('text-muted')
|
||||
} else {
|
||||
responseBodyElement.text('Empty response body');
|
||||
responseBodyElement.addClass('text-muted')
|
||||
}
|
||||
|
||||
responseHeaderElement.empty();
|
||||
if (request.homeConnectResponse && request.homeConnectResponse.header) {
|
||||
var responseHeader = request.homeConnectResponse.header;
|
||||
Object.keys(responseHeader).forEach(key => {
|
||||
console.log(`key=${key} value=${responseHeader[key]}`);
|
||||
responseHeaderElement.append($(`<dt class="col-sm-4">${key}</dt>`));
|
||||
responseHeaderElement.append($(`<dd class="col-sm-8 text-break">${responseHeader[key]}</dd>`));
|
||||
responseHeaderElement.append($('<div class="w-100"></div>'));
|
||||
});
|
||||
}
|
||||
|
||||
requestHeaderElement.empty();
|
||||
Object.keys(requestHeader).forEach(key => {
|
||||
console.log(`key=${key} value=${requestHeader[key]}`);
|
||||
requestHeaderElement.append($(`<dt class="col-sm-4">${key}</dt>`));
|
||||
requestHeaderElement.append($(`<dd class="col-sm-8 text-break">${requestHeader[key]}</dd>`));
|
||||
requestHeaderElement.append($('<div class="w-100"></div>'));
|
||||
});
|
||||
|
||||
modal.modal('handleUpdate');
|
||||
})
|
||||
|
||||
$('.reload-page').click(function () {
|
||||
location.reload();
|
||||
});
|
||||
|
||||
$('.request-chart').each(function (index, element) {
|
||||
var bridgeId = $(this).data('bridge-id');
|
||||
var chartElement = element;
|
||||
|
||||
function makeplot (bridgeId, chartElement) {
|
||||
Plotly.d3.csv('requests?bridgeId=' + bridgeId + '&action=request-csv', function (data) {
|
||||
processData(data, chartElement)
|
||||
});
|
||||
}
|
||||
|
||||
function processData (allRows, chartElement) {
|
||||
console.log(allRows);
|
||||
var x = [], y = [], standardDeviation = [];
|
||||
|
||||
for (var i = 0; i < allRows.length; i++) {
|
||||
var row = allRows[i];
|
||||
x.push(row['time']);
|
||||
y.push(row['requests']);
|
||||
}
|
||||
console.log('X', x, 'Y', y, 'SD', standardDeviation);
|
||||
makePlotly(x, y, standardDeviation, chartElement);
|
||||
}
|
||||
|
||||
function makePlotly (x, y, standard_deviation, chartElement){
|
||||
var traces = [{
|
||||
x: x,
|
||||
y: y,
|
||||
type: 'histogram',
|
||||
histfunc: 'sum',
|
||||
xbins: {
|
||||
size: 1000
|
||||
}
|
||||
}];
|
||||
|
||||
Plotly.newPlot(chartElement, traces,
|
||||
{
|
||||
xaxis: {
|
||||
rangemode: 'nonnegative',
|
||||
autorange: true,
|
||||
title: '',
|
||||
type: 'date'
|
||||
},
|
||||
yaxis: {
|
||||
title: 'requests',
|
||||
rangemode: 'nonnegative'
|
||||
}
|
||||
},
|
||||
{
|
||||
displayModeBar: false,
|
||||
responsive: true
|
||||
});
|
||||
}
|
||||
|
||||
makeplot(bridgeId, chartElement);
|
||||
});
|
||||
}())
|
||||
2
bundles/org.openhab.binding.homeconnect/src/main/resources/assets/js/jquery-3.5.1.min.js
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head th:replace="base :: head"></head>
|
||||
|
||||
<body>
|
||||
<nav th:replace="base :: topNav"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav th:replace="base :: sidebarMenu (current='appliances')"></nav>
|
||||
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Appliances</h1>
|
||||
</div>
|
||||
|
||||
<div th:if="${bridgeHandlers.size() == 0}">No Home Connect bridge found. Please manually add 'Home Connect API' bridge and authorize it here.</div>
|
||||
<div th:each="bridgeHandler: ${bridgeHandlers}">
|
||||
<div th:each="thingHandler: ${bridgeHandler.getThingHandler()}">
|
||||
<div class="card mb-3" th:with="events=${bridgeHandler.getEventSourceClient().getLatestEvents(thingHandler.getThingHaId())}, thing=${thingHandler.getThing()}, status=${thingHandler.getThing().getStatus().toString()}, uid=${thingHandler.getThing().getUID().getAsString()}, haId=${thingHandler.getThingHaId()}">
|
||||
<div class="card-body">
|
||||
<section th:id="${uid}">
|
||||
<h5 class="card-title" th:text="${thing.getLabel()}">Card title</h5>
|
||||
</section>
|
||||
<h6 class="card-subtitle mb-2 text-muted" th:text="${uid}">Card subtitle</h6>
|
||||
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">Bridge</dt>
|
||||
<dd class="col-sm-8" th:text="${bridgeHandler.getThing().getLabel() + ' (' + bridgeHandler.getThing().getUID().getAsString() + ')'}">1234567890</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">HaId</dt>
|
||||
<dd class="col-sm-8" th:text="${haId}">1234567890</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">Status</dt>
|
||||
<dd class="col-sm-8">
|
||||
<span class="badge" th:classappend="|${status == 'UNINITIALIZED' ? 'badge-warning' : ''} ${status == 'OFFLINE' ? 'badge-danger' : ''} ${status == 'ONLINE' ? 'badge-success' : ''}|" th:text="${status}">OFFLINE</span>
|
||||
</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">Accessible (SSE)</dt>
|
||||
<dd class="col-sm-8">
|
||||
<span class="badge" th:classappend="${thingHandler.isThingAccessibleViaServerSentEvents() ? 'badge-success' : 'badge-danger'}" th:text="${thingHandler.isThingAccessibleViaServerSentEvents() ? 'TRUE' : 'FALSE'}">OFFLINE</span>
|
||||
</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">Last Event received (SSE)</dt>
|
||||
<dd class="col-sm-8" th:if="${events.size() > 0}" th:text="${#temporals.format(events.get(events.size()-1).creation, 'yyyy-MM-dd HH:mm:ss.SSS Z')}">1234567890</dd>
|
||||
<dd class="col-sm-8" th:unless="${events.size() > 0}">unknown</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">API Actions</dt>
|
||||
<dd class="col-sm-8">
|
||||
<div class="mb-1">
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-primary btn-sm py-0" data-title="Appliance Details" data-api-action="show-details" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Appliance Details
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-primary btn-sm py-0" data-title="Operation State" data-api-action="operation-state" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Operation State
|
||||
</button>
|
||||
<div class="w-100"></div>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-secondary btn-sm py-0" data-title="All Programs" data-api-action="all-programs" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
All Programs
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-secondary btn-sm py-0" data-title="Available Programs" data-api-action="available-programs" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Available Programs
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-secondary btn-sm py-0" data-title="Selected Program" data-api-action="selected-program" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Selected Program
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-secondary btn-sm py-0" data-title="Active Program" data-api-action="active-program" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Active Program
|
||||
</button>
|
||||
<div class="w-100"></div>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-info btn-sm py-0" data-title="Power State" data-api-action="power-state" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Power State
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-info btn-sm py-0" data-title="Door State" data-api-action="door-state" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Door State
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-info btn-sm py-0" data-title="Remote Control Start Allowed" data-api-action="remote-control-start-allowed" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Remote Control Start Allowed
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-info btn-sm py-0" data-title="Remote Control Active" data-api-action="remote-control-active" th:attr="data-thing-id=${uid}" data-toggle="modal" data-target="#apiDetailModal">
|
||||
Remote Control Active
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-warning btn-sm py-0" data-title="Send Raw Command (PUT)" th:attr="data-thing-id=${uid}, data-ha-id=${haId}" data-toggle="modal" data-target="#rawCommandDetailModal">
|
||||
Send Raw Command (PUT)
|
||||
</button>
|
||||
<button style="display: inline-block;font-size: 0.8em;" type="button" class="btn btn-warning btn-sm py-0" data-title="Send Raw Request (GET)" th:attr="data-thing-id=${uid}, data-ha-id=${haId}" data-toggle="modal" data-target="#rawGetDetailModal">
|
||||
Send Raw Request (GET)
|
||||
</button>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- API action detail modal -->
|
||||
<div class="modal fade" id="apiDetailModal" tabindex="-1" role="dialog" aria-labelledby="apiDetailModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div>
|
||||
<h5 class="modal-title text-truncate" id="apiDetailModalLabel">API</h5>
|
||||
<h6 class="modal-subtitle mb-2 text-muted text-truncate">Card subtitle</h6>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre class="modal-response-body"></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Send Raw Command modal -->
|
||||
<div class="modal fade" id="rawCommandDetailModal" tabindex="-1" role="dialog" aria-labelledby="rawCommandDetailModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div>
|
||||
<h5 class="modal-title text-truncate" id="rawCommandDetailModalLabel">Send Raw Command</h5>
|
||||
<h6 class="modal-subtitle mb-2 text-muted text-truncate">Card subtitle</h6>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="raw-path" class="col-form-label">Path:</label>
|
||||
<input type="text" class="form-control" id="raw-path">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="raw-request-body" class="col-form-label">Request Body:</label>
|
||||
<textarea cols=100 rows=12 class="form-control" id="raw-request-body"></textarea>
|
||||
</div>
|
||||
</form>
|
||||
<label class="raw-response-header">Response:</label>
|
||||
<pre class="modal-response-body"></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" id="raw-submit">Submit Request</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Send Raw Request modal -->
|
||||
<div class="modal fade" id="rawGetDetailModal" tabindex="-1" role="dialog" aria-labelledby="rawGetDetailModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div>
|
||||
<h5 class="modal-title text-truncate" id="rawGetDetailModalLabel">Send Request (GET)</h5>
|
||||
<h6 class="modal-subtitle mb-2 text-muted text-truncate">Card subtitle</h6>
|
||||
</div>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="raw-path" class="col-form-label">Path:</label>
|
||||
<input type="text" class="form-control" id="raw-get-path">
|
||||
</div>
|
||||
</form>
|
||||
<label class="raw-response-header">Response:</label>
|
||||
<pre class="modal-response-body"></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" id="raw-get-submit">Submit Request</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!--/*/ <th:block th:include="base :: js">
|
||||
</th:block> /*/-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head th:fragment="head">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>Home Connect Console</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link th:href="@{/homeconnect/asset/css/bootstrap.min.css}" rel="stylesheet">
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="apple-touch-icon" sizes="180x180" th:href="@{/homeconnect/asset/favicon/apple-touch-icon.png}">
|
||||
<link rel="icon" type="image/png" sizes="32x32" th:href="@{/homeconnect/asset/favicon/favicon-32x32.png}">
|
||||
<link rel="icon" type="image/png" sizes="16x16" th:href="@{/homeconnect/asset/favicon/favicon-16x16.png}">
|
||||
<link rel="manifest" th:href="@{/homeconnect/asset/favicon/site.webmanifest}">
|
||||
<link rel="mask-icon" th:href="@{/homeconnect/asset/favicon/safari-pinned-tab.svg}" color="#5bbad5">
|
||||
<link rel="shortcut icon" th:href="@{/homeconnect/asset/favicon/favicon.ico}">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="msapplication-config" th:content="@{/homeconnect/asset/favicon/browserconfig.xml}" content="browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<!-- Home Connect binding CSS -->
|
||||
<link th:href="@{/homeconnect/asset/css/homeconnect.css}" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav th:fragment="topNav" class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
|
||||
<a class="navbar-brand col-md-3 col-lg-2 mr-0 px-3" href="#">Home Connect Console</a>
|
||||
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-toggle="collapse" data-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav th:fragment="sidebarMenu (current)" th:assert="${!#strings.isEmpty(current)}" id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
||||
<div class="sidebar-sticky pt-3">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" th:href="@{/homeconnect}" href="#" th:classappend="${current == 'bridges' ? 'active' : ''}">
|
||||
<span data-feather="link-2"></span>
|
||||
Bridges
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" th:href="@{/homeconnect/appliances}" href="#" th:classappend="${current == 'appliances' ? 'active' : ''}">
|
||||
<span data-feather="grid"></span>
|
||||
Appliances
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||
<span>Reports</span>
|
||||
</h6>
|
||||
<ul class="nav flex-column mb-2">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" th:href="@{/homeconnect/log/requests}" href="#" th:classappend="${current == 'log-requests' ? 'active' : ''}">
|
||||
<span data-feather="file-text"></span>
|
||||
API Requests
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" th:href="@{/homeconnect/log/events}" href="#" th:classappend="${current == 'log-events' ? 'active' : ''}">
|
||||
<span data-feather="file-text"></span>
|
||||
Events (SSE)
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<th:block th:fragment="js">
|
||||
<script th:src="@{/homeconnect/asset/js/jquery-3.5.1.min.js}"></script>
|
||||
<script th:src="@{/homeconnect/asset/js/bootstrap.bundle.min.js}"></script>
|
||||
<script th:src="@{/homeconnect/asset/js/feather.min.js}"></script>
|
||||
<script th:src="@{/homeconnect/asset/js/homeconnect.js}"></script>
|
||||
</th:block>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head th:replace="base :: head"></head>
|
||||
|
||||
<body>
|
||||
<nav th:replace="base :: topNav"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav th:replace="base :: sidebarMenu (current='bridges')"></nav>
|
||||
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Bridges</h1>
|
||||
</div>
|
||||
|
||||
<div th:if="${bridgeHandlers.size() == 0}">No Home Connect bridge found. Please manually add 'Home Connect API' bridge and authorize it here.</div>
|
||||
<div th:each="bridgeHandler: ${bridgeHandlers}">
|
||||
<div class="card mb-3" th:with="thing=${bridgeHandler.getThing()}, status=${bridgeHandler.getThing().getStatus().toString()}, uid=${thing.getUID().getAsString()}">
|
||||
<div class="card-body">
|
||||
<section th:id="${uid}">
|
||||
<h5 class="card-title" th:text="${thing.getLabel()}">Card title</h5>
|
||||
</section>
|
||||
<h6 class="card-subtitle mb-2 text-muted" th:text="${uid}">Card subtitle</h6>
|
||||
|
||||
<div th:if="${action == uid + 'clearCredentials'}" class="alert alert-success" role="alert">
|
||||
Successfully cleared credentials.
|
||||
</div>
|
||||
|
||||
<div th:if="${action == uid + 'authorize'}" class="alert alert-success" role="alert">
|
||||
Successfully authorized bridge.
|
||||
</div>
|
||||
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">OAuth Flow</dt>
|
||||
<dd class="col-sm-8">Authorization Code Grant Flow</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">Client ID</dt>
|
||||
<dd class="col-sm-8" th:text="${bridgeHandler.getConfiguration().getClientId()}">1234567890</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">Client Secret</dt>
|
||||
<dd class="col-sm-8" th:text="${bridgeHandler.getConfiguration().getClientSecret()}">xyz</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">Redirect URI</dt>
|
||||
<dd class="col-sm-8">
|
||||
<span class="redirectUri">http://xy/homeconnect</span><br />
|
||||
<small class="text-muted">Please make sure the redirect URI is matching the one specified at https://developer.home-connect.com/applications/.</small>
|
||||
</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">API Endpoint</dt>
|
||||
<dd class="col-sm-8" th:text="${bridgeHandler.getConfiguration().isSimulator() ? @org.openhab.binding.homeconnect.internal.HomeConnectBindingConstants@API_SIMULATOR_BASE_URL : @org.openhab.binding.homeconnect.internal.HomeConnectBindingConstants@API_BASE_URL}">xyz</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">SSE connections</dt>
|
||||
<dd class="col-sm-8" th:text="${bridgeHandler.getEventSourceClient().connectionSize()}">xyz</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2">Status</dt>
|
||||
<dd class="col-sm-8">
|
||||
<span class="badge" th:classappend="|${status == 'UNINITIALIZED' ? 'badge-warning' : ''} ${status == 'OFFLINE' ? 'badge-danger' : ''} ${status == 'ONLINE' ? 'badge-success' : ''}|" th:text="${status}">OFFLINE</span>
|
||||
</dd>
|
||||
<div class="w-100"></div>
|
||||
|
||||
<dt class="col-sm-2"></dt>
|
||||
<dd class="col-sm-8">
|
||||
<form method="post" style="display: inline-block">
|
||||
<input type="hidden" name="bridgeId" th:value="${uid}"/>
|
||||
<input type="hidden" name="action" value="clearCredentials">
|
||||
<button type="submit" class="btn btn-secondary btn-sm">Clear stored credentials</button>
|
||||
</form>
|
||||
<form method="post" style="display: inline-block">
|
||||
<input type="hidden" name="bridgeId" th:value="${uid}"/>
|
||||
<input type="hidden" name="action" value="authorize">
|
||||
<button type="submit" class="btn btn-primary btn-sm">Authorize bridge</button>
|
||||
</form>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--/*/ <th:block th:include="base :: js">
|
||||
</th:block> /*/-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head th:replace="base :: head"></head>
|
||||
|
||||
<body>
|
||||
<nav th:replace="base :: topNav"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav th:replace="base :: sidebarMenu (current='log-events')"></nav>
|
||||
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Events</h1>
|
||||
</div>
|
||||
|
||||
<div th:if="${bridgeHandlers.size() == 0}" class="mb-4"><span class="text-muted">No events</span></div>
|
||||
<div class="mb-4" th:each="bridgeHandler: ${bridgeHandlers}" th:with="thing=${bridgeHandler.getThing()}, queue=${bridgeHandler.getEventSourceClient().getLatestEvents()}, status=${bridgeHandler.getThing().getStatus().toString()}, uid=${bridgeHandler.getThing().getUID().getAsString()}">
|
||||
<h2 th:text="${thing.getLabel() + ' (' + uid + ')'}" style="display: inline-block;">Section title</h2>
|
||||
<div class="btn-toolbar float-right">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary reload-page mr-2"><span data-feather="refresh-cw"></span></button>
|
||||
<a th:href="@{/homeconnect/log/events(export='json',bridgeId=${uid})}" class="btn btn-sm btn-outline-secondary">Export</a>
|
||||
</div>
|
||||
|
||||
<div th:if="${queue.size() == 0}"><span class="text-muted">No events</span></div>
|
||||
<div th:if="${queue.size() > 0}" class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Timestamp</th>
|
||||
<th>HaId</th>
|
||||
<th>Type</th>
|
||||
<th>Level</th>
|
||||
<th>Handling</th>
|
||||
<th>URI</th>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
<th>Unit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="entry: ${queue}">
|
||||
<td th:text="${#temporals.format(entry.creation, 'yyyy-MM-dd HH:mm:ss.SSS Z')}">27.04.2020 14:30</td>
|
||||
<td><span th:text="${entry.haId}" class="badge badge-light">align-middle</span></td>
|
||||
<td><span th:text="${entry.type}" class="badge badge-secondary"></span></td>
|
||||
<td><span th:if="${entry.level}" th:text="${entry.level}" class="badge" th:classappend="|${entry.level.getLevel() == 'critical' || entry.level.getLevel() == 'alert' ? 'badge-danger' : ''} ${entry.level.getLevel() == 'info' || entry.level.getLevel() == 'hint' ? 'badge-success' : ''} ${entry.level.getLevel() == 'warning' ? 'badge-warning' : ''}|">hint</span></td>
|
||||
<td><span class="badge badge-light" th:text="${entry.handling}">none</span></td>
|
||||
<td class="text-break" th:text="${entry.uri}">/api/homeappliances/BOSCH-HNG6764B6-0000000011FF/programs/active/options/Cooking.Oven.Option.SetpointTemperature</td>
|
||||
<td th:text="${entry.name}">Target temperature for the oven</td>
|
||||
<td th:text="${entry.value}">200</td>
|
||||
<td th:text="${entry.unit}">°C</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--/*/ <th:block th:include="base :: js">
|
||||
</th:block> /*/-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head th:replace="base :: head"></head>
|
||||
|
||||
<body>
|
||||
<nav th:replace="base :: topNav"></nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav th:replace="base :: sidebarMenu (current='log-requests')"></nav>
|
||||
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">API Requests</h1>
|
||||
</div>
|
||||
|
||||
<div th:if="${bridgeHandlers.size() == 0}" class="mb-4"><span class="text-muted">No requests</span></div>
|
||||
<div class="mb-4" th:each="bridgeHandler: ${bridgeHandlers}" th:with="thing=${bridgeHandler.getThing()}, queue=${bridgeHandler.getApiClient().getLatestApiRequests()}, status=${bridgeHandler.getThing().getStatus().toString()}, uid=${bridgeHandler.getThing().getUID().getAsString()}">
|
||||
<h2 th:text="${thing.getLabel() + ' (' + uid + ')'}" style="display: inline-block;">Section title</h2>
|
||||
<div class="btn-toolbar float-right">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary reload-page mr-2"><span data-feather="refresh-cw"></span></button>
|
||||
<a th:href="@{/homeconnect/log/requests(export='json',bridgeId=${uid})}" class="btn btn-sm btn-outline-secondary">Export</a>
|
||||
</div>
|
||||
|
||||
<div th:if="${queue.size() == 0}"><span class="text-muted">No requests</span></div>
|
||||
<div th:unless="${queue.size() == 0}" class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Request Time</th>
|
||||
<th class="text-center">Response Code</th>
|
||||
<th class="text-center">Method</th>
|
||||
<th>URL</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="entry: ${queue}">
|
||||
<td th:text="${#temporals.format(entry.time, 'yyyy-MM-dd HH:mm:ss.SSS Z')}">27.04.2020 14:30</td>
|
||||
<td class="text-center"><span th:if="${entry.response}" class="badge" th:classappend="|${entry.response.code >= 300 && entry.response.code != 404 ? 'badge-danger' : ''} ${entry.response.code >=200 && entry.response.code < 300 ? 'badge-success' : ''} ${entry.response.code == 404 ? 'badge-warning' : ''}|" th:text="${entry.response.code}">200</span></td>
|
||||
<td class="text-center" th:text="${entry.request.method}">GET</td>
|
||||
<td th:text="${entry.request.getShortUrl()}">/bla/bla?w92374=34</td>
|
||||
<td class="text-center">
|
||||
<button type="button" class="btn btn-info btn-sm py-0" style="font-size: 0.8em;" th:attr="data-request-id=${entry.id}" data-toggle="modal" data-target="#requestDetailModal">
|
||||
Details
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Request detail modal -->
|
||||
<div class="modal fade" id="requestDetailModal" tabindex="-1" role="dialog" aria-labelledby="requestDetailModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title .text-truncate" id="requestDetailModalLabel">Request Details</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5>Request Body</h5>
|
||||
<pre class="modal-request-body"></pre>
|
||||
<hr>
|
||||
<h5>Response Body</h5>
|
||||
<pre class="modal-response-body"></pre>
|
||||
<hr>
|
||||
<h5>Response Header</h5>
|
||||
<dl class="row modal-response-header"></dl>
|
||||
<hr>
|
||||
<h5>Request Header</h5>
|
||||
<dl class="row modal-request-header"></dl>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:inline="javascript">
|
||||
var requests = JSON.parse(/*[[${requests}]]*/);
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
<!--/*/ <th:block th:include="base :: js">
|
||||
</th:block> /*/-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||