1527 lines
98 KiB
HTML
1527 lines
98 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||
<meta name="theme-color" content="#151515" id="themeColorMeta">
|
||
<meta name="description" content="Local GREE air conditioner controller" data-i18n-content="meta.description">
|
||
<link rel="manifest" href="__GREE_BASE_PATH__/manifest.webmanifest">
|
||
<link rel="icon" href="__GREE_BASE_PATH__/favicon.svg" type="image/svg+xml">
|
||
<link rel="stylesheet" href="__GREE_STYLES_ASSET__">
|
||
<script src="__GREE_THEME_INIT_ASSET__"></script>
|
||
<title>GREE Controller</title>
|
||
</head>
|
||
|
||
<body>
|
||
<header class="topbar">
|
||
<div class="brand">
|
||
<div class="brand-line"><strong>GREE Controller</strong><small id="connectionLabel"
|
||
class="connection-dot connecting" role="status" aria-label="Connecting" title="Connecting"></small></div>
|
||
</div>
|
||
<div class="toolbar-runtime-status" id="toolbarRuntimeStatus" aria-live="polite">0/0</div>
|
||
<div class="top-actions">
|
||
<div class="toolbar-picker" data-i18n-title="controls.language" title="Language">
|
||
<span class="toolbar-picker-value" id="languageLabel" aria-hidden="true">EN</span>
|
||
<span class="toolbar-picker-chevron" aria-hidden="true">⌄</span>
|
||
<select class="toolbar-picker-select" id="languageSelect" data-i18n-aria="controls.language"
|
||
aria-label="Language">
|
||
<option value="en">English</option>
|
||
</select>
|
||
</div>
|
||
<div class="toolbar-picker" data-i18n-title="controls.theme" title="Theme">
|
||
<span class="toolbar-picker-value theme-picker-value" id="themeIcon" aria-hidden="true">◐</span>
|
||
<span class="toolbar-picker-chevron" aria-hidden="true">⌄</span>
|
||
<select class="toolbar-picker-select" id="themeSelect" data-i18n-aria="controls.theme" aria-label="Theme">
|
||
<option value="system" data-i18n="theme.system">System</option>
|
||
<option value="light" data-i18n="theme.light">Light</option>
|
||
<option value="dark" data-i18n="theme.dark">Dark</option>
|
||
</select>
|
||
</div>
|
||
<button class="icon-button toolbar-icon-control" id="refreshButton" data-i18n-title="actions.refresh"
|
||
data-i18n-aria="actions.refresh" title="Refresh" aria-label="Refresh">↻</button>
|
||
</div>
|
||
<div class="connection-banner" id="connectionBanner" role="status" aria-live="polite" hidden>
|
||
<span class="connection-banner-dot" aria-hidden="true"></span>
|
||
<div><strong id="connectionBannerTitle">Disconnected</strong><span id="connectionBannerText">Live updates are
|
||
unavailable. Displayed data may be stale.</span></div>
|
||
<button class="secondary" type="button" id="connectionRetry" data-i18n="actions.retry">Retry</button>
|
||
</div>
|
||
<div class="simulation-mode-banner" id="simulationModeBanner" role="status" aria-live="polite" hidden>
|
||
<strong data-i18n="simulation.bannerTitle">SIMULATION MODE</strong>
|
||
<span data-i18n="simulation.bannerText">Simulation is enabled. Verify the mode before relying on controller
|
||
output.</span>
|
||
</div>
|
||
</header>
|
||
|
||
<main>
|
||
<section class="view active" data-view="dashboard">
|
||
<nav class="dashboard-tabs" data-i18n-aria="dashboard.sections" aria-label="Dashboard sections">
|
||
<button type="button" class="active" data-dashboard-tab="main" data-i18n="dashboard.tabMain">Main</button>
|
||
<button type="button" data-dashboard-tab="thermostats" data-i18n="dashboard.tabThermostats">Thermostats</button>
|
||
<button type="button" data-dashboard-tab="manual" data-i18n="dashboard.tabManual">Manual control</button>
|
||
</nav>
|
||
|
||
<div class="dashboard-tab-panel active" data-dashboard-panel="main">
|
||
<div class="hero dashboard-summary-card">
|
||
<div class="dashboard-summary-copy"><span class="eyebrow" data-i18n="dashboard.home">Home</span>
|
||
<h1 data-i18n="dashboard.title">Comfort under control</h1>
|
||
<p id="summaryText" data-i18n="dashboard.loading">Loading devices…</p>
|
||
</div>
|
||
<div class="dashboard-summary-status">
|
||
<div class="metrics" id="metrics"></div>
|
||
<div class="hero-temp" id="heroTemperature">--<small>°C</small></div>
|
||
</div>
|
||
</div>
|
||
<div class="panel dashboard-global-panel">
|
||
<div class="dashboard-global-power">
|
||
<div><span class="eyebrow" data-i18n="house.powerAllEyebrow">Global power</span>
|
||
<h3 data-i18n="house.powerAllTitle">All air conditioners</h3>
|
||
<p data-i18n="house.powerAllHint">Bulk power action for all units. OFF leaves thermostats locally off
|
||
until you explicitly turn a thermostat, group or the whole house back on.</p>
|
||
</div>
|
||
<div class="house-power-actions"><button id="housePowerOn" type="button" class="secondary"
|
||
data-action="house-power" data-value="true" data-i18n="house.powerOnAll">Turn all on</button><button
|
||
id="housePowerOff" type="button" class="secondary" data-action="house-power" data-value="false"
|
||
data-i18n="house.powerOffAll">Turn all off</button></div>
|
||
</div>
|
||
<div class="dashboard-global-divider"></div>
|
||
<div class="house-climate dashboard-house-climate" id="houseClimate"></div>
|
||
</div>
|
||
<section class="panel dashboard-section-panel" id="controlPlanSection">
|
||
<div class="dashboard-section-head compact-head">
|
||
<div><span class="eyebrow" data-i18n="plan.eyebrow">Control plan</span>
|
||
<h2 data-i18n="plan.title">What happens next</h2>
|
||
</div>
|
||
</div>
|
||
<div class="automation-plan-grid" id="controlPlan"></div>
|
||
</section>
|
||
</div>
|
||
|
||
<div class="dashboard-tab-panel" data-dashboard-panel="thermostats" hidden>
|
||
<section class="dashboard-primary-section">
|
||
<div class="dashboard-section-head">
|
||
<div><span class="eyebrow" data-i18n="groups.eyebrow">Group control</span>
|
||
<h2 data-i18n="groups.dashboardTitle">Control selected air conditioners</h2>
|
||
<p data-i18n="groups.dashboardHint">Group ON activates its thermostats; Group OFF powers its units down
|
||
and releases group ownership. You can also choose a mode, preset, or custom temperature.</p>
|
||
</div>
|
||
<div class="dashboard-section-actions"><span class="badge" id="dashboardGroupCount">0</span><button
|
||
type="button" class="secondary" data-go="groups" data-i18n="groups.manage">Manage groups</button></div>
|
||
</div>
|
||
<div class="group-quick-grid dashboard-group-strip" id="dashboardGroups"></div>
|
||
</section>
|
||
<section class="panel dashboard-section-panel dashboard-thermostat-section">
|
||
<div class="dashboard-section-head compact-head">
|
||
<div><span class="eyebrow" data-i18n="nav.zones">Zones</span>
|
||
<h2 data-i18n="dashboard.quickThermostats">Thermostats</h2>
|
||
</div>
|
||
<div class="dashboard-section-actions"><button type="button" class="secondary queue-overview-button"
|
||
data-action="open-compressor-queue"><span data-i18n="zones.queueOverview">Queue</span><b
|
||
class="queue-overview-count" data-compressor-queue-count>0</b></button><span class="badge"
|
||
id="dashboardZoneCount">0</span></div>
|
||
</div>
|
||
<div class="list-grid dashboard-zones" id="dashboardZones"></div>
|
||
</section>
|
||
</div>
|
||
|
||
<div class="dashboard-tab-panel" data-dashboard-panel="manual" hidden>
|
||
<section class="panel dashboard-section-panel">
|
||
<div class="dashboard-section-head compact-head">
|
||
<div><span class="eyebrow" data-i18n="nav.devices">Devices</span>
|
||
<h2 data-i18n="dashboard.quickControl">Manual control</h2>
|
||
<p data-i18n="dashboard.manualControlHint">Direct GREE control: power, temperature, mode, fan and
|
||
supported unit functions.</p>
|
||
</div>
|
||
<span class="badge" id="dashboardDeviceCount">0</span>
|
||
</div>
|
||
<div class="device-grid" id="dashboardDevices"></div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="view" data-view="devices">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="devices.lan">LAN network</span>
|
||
<h1 data-i18n="nav.devices">Devices</h1>
|
||
</div>
|
||
<div class="section-heading-actions"><button class="primary compact" id="discoverButton"
|
||
data-i18n="actions.discover">Discover</button><button class="secondary" data-open="deviceDialog"
|
||
data-i18n="devices.addManual">Add manually</button></div>
|
||
</div>
|
||
<p class="lead" data-i18n="devices.technicalDescription">Technical configuration and diagnostics only. Current
|
||
operating settings are available in Manual control.</p>
|
||
<div class="device-grid" id="deviceList"></div>
|
||
</section>
|
||
|
||
<section class="view" data-view="zones">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="zones.automation">Automation</span>
|
||
<h1 data-i18n="nav.zones">Zones</h1>
|
||
</div>
|
||
<div class="section-heading-actions"><button type="button" class="secondary queue-overview-button"
|
||
data-action="open-compressor-queue"><span data-i18n="zones.queueOverview">Queue</span><b
|
||
class="queue-overview-count" data-compressor-queue-count>0</b></button><button class="secondary"
|
||
data-open="zoneDialog" data-i18n="zones.new">New zone</button></div>
|
||
</div>
|
||
<p class="lead" data-i18n="zones.description">Zones define thermostat logic and sensor configuration. Use Quick
|
||
thermostats on the Dashboard for current temperature changes and presets.</p>
|
||
<div class="list-grid" id="zoneList"></div>
|
||
</section>
|
||
|
||
<section class="view" data-view="groups">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="groups.eyebrow">Group control</span>
|
||
<h1 data-i18n="nav.groups">Groups</h1>
|
||
</div><button class="secondary" data-open="groupDialog" data-i18n="groups.new">New group</button>
|
||
</div>
|
||
<p class="lead" data-i18n="groups.description">Combine thermostat zones and control only that set. Turning a group
|
||
on activates its thermostats; turning it off powers its units down and releases group ownership.</p>
|
||
<div class="list-grid" id="groupList"></div>
|
||
</section>
|
||
|
||
<section class="view" data-view="flows">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="flow.eyebrow">Visual logic</span>
|
||
<h1 data-i18n="nav.flows">Flow</h1>
|
||
</div>
|
||
<div class="section-actions flow-page-actions"><button class="secondary" type="button" data-action="import-flow"
|
||
data-i18n="flow.import">Import Flow</button><button class="primary" type="button" data-action="new-flow"
|
||
data-i18n="flow.new">New Flow</button></div>
|
||
</div>
|
||
<nav class="automation-tabs" data-i18n-aria="automationHub.navigation" aria-label="Automation navigation">
|
||
<button type="button" class="active" data-go="flows" data-i18n="nav.flows">Flow</button>
|
||
<button type="button" data-go="schedules" data-i18n="nav.schedules">Schedules</button>
|
||
<button type="button" data-go="automations" data-i18n="nav.automations">Automations</button>
|
||
</nav>
|
||
<div class="panel flow-info-panel">
|
||
<div><strong data-i18n="flow.infoTitle">One place for schedules and automations</strong>
|
||
<p data-i18n="flow.infoText">Build the logic from blocks. GREE Controller translates Flow into generated
|
||
schedules and automations. Generated entries are read-only outside this editor.</p>
|
||
<button type="button" class="secondary flow-shared-settings-link" data-action="flow-shared-input-settings"
|
||
data-i18n="flow.sharedInputsSettingsLink">Wspólne wejścia Flow w Home Assistant →</button>
|
||
</div>
|
||
<span class="badge" data-i18n="flow.sourceOfTruth">Flow = source of truth</span>
|
||
</div>
|
||
<section class="flow-list-section">
|
||
<div class="flow-list-heading flow-list-heading-count"><span id="flowListCount" class="badge"></span></div>
|
||
<div class="list-grid" id="flowList"></div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="view" data-view="schedules">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="schedules.calendar">Calendar</span>
|
||
<h1 data-i18n="nav.schedules">Schedules</h1>
|
||
</div><button class="secondary" data-open="scheduleDialog" data-i18n="actions.add">Add</button>
|
||
</div>
|
||
<nav class="automation-tabs" data-i18n-aria="automationHub.navigation" aria-label="Automation navigation">
|
||
<button type="button" data-go="flows" data-i18n="nav.flows">Flow</button>
|
||
<button type="button" class="active" data-go="schedules" data-i18n="nav.schedules">Schedules</button>
|
||
<button type="button" data-go="automations" data-i18n="nav.automations">Automations</button>
|
||
</nav>
|
||
<div class="panel schedule-template-panel">
|
||
<div>
|
||
<h3 data-i18n="schedules.quickSetup">Quick schedule setup</h3>
|
||
<p class="field-note" data-i18n="schedules.quickSetupHint">Choose a zone and a ready-made daily rhythm. You
|
||
can edit every generated entry afterwards.</p>
|
||
</div>
|
||
<select id="schedulePresetZone"></select>
|
||
<div class="template-grid">
|
||
<button class="secondary" data-schedule-template="family" data-i18n="schedules.templateFamily">Family</button>
|
||
<button class="secondary" data-schedule-template="child" data-i18n="schedules.templateChild">Child
|
||
room</button>
|
||
<button class="secondary" data-schedule-template="bedroom"
|
||
data-i18n="schedules.templateBedroom">Bedroom</button>
|
||
<button class="secondary" data-schedule-template="workday"
|
||
data-i18n="schedules.templateWorkday">Workday</button>
|
||
<button class="secondary" data-schedule-template="always" data-i18n="schedules.templateAlways">Always
|
||
comfort</button>
|
||
</div>
|
||
</div>
|
||
<div class="list-grid" id="scheduleList"></div>
|
||
</section>
|
||
|
||
<section class="view" data-view="automations">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="automations.rules">Rules</span>
|
||
<h1 data-i18n="nav.automations">Automations</h1>
|
||
</div><button class="secondary" data-open="automationDialog" data-i18n="actions.add">Add</button>
|
||
</div>
|
||
<nav class="automation-tabs" data-i18n-aria="automationHub.navigation" aria-label="Automation navigation">
|
||
<button type="button" data-go="flows" data-i18n="nav.flows">Flow</button>
|
||
<button type="button" data-go="schedules" data-i18n="nav.schedules">Schedules</button>
|
||
<button type="button" class="active" data-go="automations" data-i18n="nav.automations">Automations</button>
|
||
</nav>
|
||
<div class="panel automation-hint"><strong data-i18n="automations.smartHintTitle">Use thermostat presets for daily
|
||
comfort</strong>
|
||
<p data-i18n="automations.smartHint">Schedules and zone presets handle normal heating/cooling automatically.
|
||
Keep automations for special exceptions so they do not fight the thermostat.</p>
|
||
</div>
|
||
<div class="list-grid" id="automationList"></div>
|
||
</section>
|
||
|
||
<section class="view" data-view="simulation">
|
||
<div class="section-heading simulation-page-head">
|
||
<div><span class="eyebrow" data-i18n="simulation.eyebrow">Simulator</span>
|
||
<h1 data-i18n="simulation.title">Automation simulator</h1>
|
||
</div>
|
||
<div class="simulation-head-actions"><button class="secondary" id="simulationOpenTab"
|
||
data-i18n="simulation.openTab">Open only simulator in new tab</button><button class="secondary"
|
||
id="simulationFullscreen" data-i18n="simulation.fullscreen">Full screen</button></div>
|
||
</div>
|
||
<p class="lead" data-i18n="simulation.description">Live preview of the thermostat and automation logic. The flow
|
||
board shows how sensor readings, schedules, night mode and thermostat decisions become commands sent to each
|
||
GREE unit.</p>
|
||
<div class="panel simulation-scope-toolbar"><label><span data-i18n="simulation.viewBy">View by</span><select
|
||
id="simulationScope">
|
||
<option value="units" data-i18n="simulation.unitsView">Individual units</option>
|
||
<option value="groups" data-i18n="simulation.groupsView">Groups</option>
|
||
</select></label><label><span data-i18n="simulation.show">Show</span><select
|
||
id="simulationTarget"></select></label></div>
|
||
<div class="simulation-summary-grid" id="simulationSummary"></div>
|
||
<div class="panel simulation-flow-shell">
|
||
<div class="simulation-flow-head">
|
||
<div><span class="eyebrow" data-i18n="simulation.flowEyebrow">Live flow</span>
|
||
<h2 data-i18n="simulation.flowTitle">Automation flow board</h2>
|
||
</div>
|
||
<div class="flow-legend"><span><i class="flow-legend-dot input"></i><b
|
||
data-i18n="simulation.legendInput">Input</b></span><span><i class="flow-legend-dot logic"></i><b
|
||
data-i18n="simulation.legendLogic">Logic</b></span><span><i class="flow-legend-dot action"></i><b
|
||
data-i18n="simulation.legendAction">Action</b></span></div>
|
||
</div>
|
||
<div class="simulation-flow-scroll">
|
||
<div class="simulation-flow-board" id="simulationFlowBoard"></div>
|
||
</div>
|
||
</div>
|
||
<div class="panel simulation-timeline-panel">
|
||
<div class="simulation-section-head">
|
||
<div><span class="eyebrow" data-i18n="simulation.timelineEyebrow">Timeline</span>
|
||
<h2 data-i18n="simulation.timelineTitle">What will happen next</h2>
|
||
</div>
|
||
</div>
|
||
<div class="simulation-timeline" id="simulationTimeline"></div>
|
||
</div>
|
||
<div class="simulation-section-head">
|
||
<div><span class="eyebrow" data-i18n="simulation.rulesEyebrow">Rules</span>
|
||
<h2 data-i18n="simulation.rulesTitle">Automation rules</h2>
|
||
</div>
|
||
</div>
|
||
<div class="simulation-rules-grid" id="simulationRules"></div>
|
||
</section>
|
||
|
||
<section class="view" data-view="history">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="history.measurements">Measurements</span>
|
||
<h1 data-i18n="history.title">Climate history</h1>
|
||
</div>
|
||
</div>
|
||
<div class="history-tabs" id="historyTabs" role="tablist">
|
||
<button data-history-tab="overview" data-i18n="history.tabOverview">Overview</button>
|
||
<button data-history-tab="zones" data-i18n="history.tabZones">Zones</button>
|
||
<button data-history-tab="devices" data-i18n="history.tabDevices">GREE devices</button>
|
||
<button data-history-tab="sensors" data-i18n="history.tabSensors">HA sensors</button>
|
||
<button data-history-tab="custom" data-i18n="history.tabCustom">Custom chart</button>
|
||
</div>
|
||
<div class="panel chart-panel history-toolbar-panel">
|
||
<div class="chart-toolbar">
|
||
<div id="historyContextControls" class="history-context-controls"></div>
|
||
<label class="history-range-control"><span data-i18n="history.range">Range</span><select id="historyHours"
|
||
data-i18n-aria="history.range" aria-label="History range">
|
||
<option value="6" data-i18n="history.6h">6 hours</option>
|
||
<option value="24" selected data-i18n="history.24h">24 hours</option>
|
||
<option value="168" data-i18n="history.7d">7 days</option>
|
||
<option value="720" data-i18n="history.30d">30 days</option>
|
||
<option value="2160" data-i18n="history.90d">90 days</option>
|
||
<option value="8760" data-i18n="history.1y">1 year</option>
|
||
</select></label>
|
||
<button class="secondary history-refresh-button" id="historyRefresh"
|
||
data-i18n="actions.refresh">Refresh</button>
|
||
</div>
|
||
<div class="history-summary" id="historySummary"></div>
|
||
</div>
|
||
<div id="historyCustomBuilder" class="history-custom-builder"></div>
|
||
<div id="historyCharts" class="history-charts"></div>
|
||
</section>
|
||
|
||
|
||
<section class="view" data-view="night">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="night.eyebrow">Comfort</span>
|
||
<h1 data-i18n="nav.nightMode">Night mode</h1>
|
||
</div>
|
||
</div>
|
||
<p class="lead" data-i18n="night.description">Configure quieter thermostat behavior for sleeping hours without
|
||
mixing it with application settings.</p>
|
||
<form class="settings-form standalone-settings-form" id="nightModeForm">
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.nightMode">Night mode</h3>
|
||
<p data-i18n="settings.nightModeHint">During selected hours the thermostat limits fan speed and can
|
||
request Quiet on supported units.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="check wide"><input type="checkbox" name="night_mode_enabled"> <span
|
||
data-i18n="settings.nightModeEnabled">Enable night mode</span></label>
|
||
<label><span data-i18n="settings.nightStart">Start</span><input type="time" name="night_mode_start"
|
||
value="22:00"></label>
|
||
<label><span data-i18n="settings.nightEnd">End</span><input type="time" name="night_mode_end"
|
||
value="06:00"></label>
|
||
<label><span data-i18n="settings.nightMaxFan">Maximum fan speed</span><select
|
||
name="night_mode_max_fan_speed">
|
||
<option value="1" data-i18n="fan.low">Low</option>
|
||
<option value="2" data-i18n="fan.mediumLow">Medium-low</option>
|
||
<option value="3" data-i18n="fan.medium">Medium</option>
|
||
<option value="4" data-i18n="fan.mediumHigh">Medium-high</option>
|
||
<option value="5" data-i18n="fan.high">High</option>
|
||
</select></label>
|
||
<label class="check"><input type="checkbox" name="night_mode_force_quiet"> <span
|
||
data-i18n="settings.nightForceQuiet">Use Quiet when supported</span></label>
|
||
<label class="check wide"><input type="checkbox" name="night_mode_native_sleep"> <span
|
||
data-i18n="settings.nightNativeSleep">Use native Sleep when supported</span></label>
|
||
</div>
|
||
</section>
|
||
<div class="settings-save-bar"><span data-i18n="night.saveHint">Save night-mode changes.</span><button
|
||
class="primary" type="submit" data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="view" data-view="homeassistant">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="homeAssistant.eyebrow">Integration</span>
|
||
<h1 data-i18n="nav.homeAssistant">Home Assistant / Sensors</h1>
|
||
</div>
|
||
</div>
|
||
<p class="lead" data-i18n="homeAssistant.description">Connection, temperature sensors, friendly aliases and access
|
||
tokens for the Home Assistant integration.</p>
|
||
<form class="settings-form standalone-settings-form" id="homeAssistantForm">
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.haConnection">Połączenie z Home Assistant</h3>
|
||
<p data-i18n="settings.haConnectionHint">Adres serwera i dane dostępu używane przez wszystkie funkcje Home
|
||
Assistant.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="wide"><span>URL</span><input type="url" name="ha_url"
|
||
placeholder="http://homeassistant.local:8123"></label>
|
||
<label class="wide"><span data-i18n="settings.haLongLivedToken">Long-Lived Access Token</span><input
|
||
type="password" name="ha_token" autocomplete="new-password" data-i18n-placeholder="settings.haTokenKeep"
|
||
placeholder="Leave empty to keep the saved token"></label>
|
||
<label class="check wide"><input type="checkbox" name="ha_allow_invalid_tls"> <span
|
||
data-i18n="settings.allowInvalidTls">Allow invalid/self-signed HTTPS certificate</span></label>
|
||
<p class="field-note wide warning-note" data-i18n="settings.allowInvalidTlsHint">Use only for a trusted
|
||
local Home Assistant server.</p>
|
||
<div class="form-actions wide"><button type="button" class="secondary" id="haTest"
|
||
data-i18n="settings.testHa">Test HA</button></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.haThermostatSources">Źródła temperatury sterowania</h3>
|
||
<p data-i18n="settings.haThermostatSourcesHint">Te ustawienia należą do logiki termostatów i źródeł
|
||
temperatury, nie do wspólnych wejść Flow.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="wide"><span data-i18n="settings.defaultEntity">Connection test entity_id</span><input
|
||
name="ha_entity_id" placeholder="sensor.living_room_temperature"></label>
|
||
<p class="field-note wide" data-i18n="settings.defaultEntityHint">This entity is used by the Home Assistant
|
||
connection test when no other entity is specified. It is not automatically used as a zone temperature
|
||
source.</p>
|
||
<label class="wide"><span data-i18n="settings.outdoorEntity">Outdoor temperature entity_id</span><input
|
||
name="ha_outdoor_entity_id" placeholder="sensor.outdoor_temperature"></label>
|
||
<label class="wide"><span data-i18n="settings.haSensorStaleAfterMinutes">Maximum HA sensor reading age
|
||
(min)</span><input type="number" name="ha_sensor_stale_after_minutes" min="1" max="1440" step="1"
|
||
value="5"></label>
|
||
<p class="field-note wide" data-i18n="settings.haSensorStaleAfterHint">If the HA sensor is not updated
|
||
within this time, the reading is treated as stale.</p>
|
||
<label class="check wide"><input type="checkbox" name="outdoor_assist_enabled"> <span
|
||
data-i18n="settings.outdoorAssist">Use outdoor temperature as smart-control assist</span></label>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel settings-block flow-shared-settings" id="flowSharedInputsSettings">
|
||
<div class="settings-block-head flow-shared-settings-head">
|
||
<div>
|
||
<h3 data-i18n="flow.sharedInputsTitle">Wspólne wejścia Flow</h3>
|
||
<p data-i18n="flow.sharedInputsHint">Zdefiniuj wspólne źródła wartości raz i używaj ich w wielu Flow.
|
||
Czujniki HA dodane tylko tutaj nie są zapisywane do metryk.</p>
|
||
</div><button type="button" class="primary flow-shared-add-button" id="addFlowSharedInput"
|
||
data-i18n="flow.sharedInputAdd">Dodaj wejście</button>
|
||
</div>
|
||
<input type="hidden" id="flowSharedInputsRevision" name="flow_inputs_revision" value="[]">
|
||
<div id="flowSharedInputList" class="flow-shared-input-list"></div>
|
||
</section>
|
||
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.sensorAliases">Sensor aliases</h3>
|
||
<p data-i18n="settings.sensorAliasesHint">Badges show whether an entity is collected as metrics, used by
|
||
Flow, or both.</p>
|
||
</div>
|
||
</div>
|
||
<div class="sensor-alias-manager">
|
||
<div id="sensorAliasList" class="sensor-alias-list"></div>
|
||
<div class="sensor-alias-add"><input id="sensorAliasEntity" placeholder="sensor.gabinet_temperature"><input
|
||
id="sensorAliasName" data-i18n-placeholder="settings.aliasPlaceholder" placeholder="Gabinet"><button
|
||
type="button" class="secondary" id="addSensorAlias" data-i18n="actions.add">Add</button></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.haIntegrationAccess">Home Assistant integration access</h3>
|
||
<p data-i18n="settings.haIntegrationHint">Create a controller token and paste it into the GREE Controller
|
||
integration in Home Assistant.</p>
|
||
</div>
|
||
</div>
|
||
<div class="token-manager">
|
||
<div id="accessTokenList" class="token-list"></div>
|
||
<div class="form-actions"><button type="button" class="primary" id="createAccessToken"
|
||
data-i18n="settings.newToken">Create new token</button></div>
|
||
</div>
|
||
</section>
|
||
<div class="settings-save-bar"><span data-i18n="homeAssistant.saveHint">Save Home Assistant and sensor
|
||
changes.</span><button class="primary" type="submit" data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="view" data-view="settings">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="settings.system">System</span>
|
||
<h1 data-i18n="nav.settings">Settings</h1>
|
||
</div>
|
||
</div>
|
||
<div class="settings-mode-tabs" role="tablist" data-i18n-aria="settings.settingsSections"
|
||
aria-label="Settings sections">
|
||
<button type="button" class="active" role="tab" aria-selected="true" data-settings-tab="app"
|
||
data-i18n="settings.applicationSettings">Application</button>
|
||
<button type="button" role="tab" aria-selected="false" data-settings-tab="gree"
|
||
data-i18n="settings.greeSettings">GREE</button>
|
||
</div>
|
||
<form class="settings-form" id="settingsForm" novalidate>
|
||
<div class="settings-pane" data-settings-pane="app">
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.applicationRuntime">Application runtime</h3>
|
||
<p data-i18n="settings.applicationRuntimeHint">Application-wide behavior that does not change GREE
|
||
transport or discovery.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="check wide"><input type="checkbox" name="simulator_enabled"> <span
|
||
data-i18n="settings.simulationMode">Simulation mode</span></label>
|
||
<p class="field-note wide warning-note" data-i18n="settings.simulationModeHint">When enabled, a prominent
|
||
warning is shown throughout the application.</p>
|
||
</div>
|
||
</section>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="notifications.title">Notifications</h3>
|
||
<p data-i18n="notifications.hint">Send important events or only problems/anomalies.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="check wide"><input type="checkbox" name="notifications_enabled"> <span
|
||
data-i18n="notifications.enable">Enable notifications</span></label>
|
||
<label><span data-i18n="notifications.mode">Mode</span><select name="notifications_mode">
|
||
<option value="problems" data-i18n="notifications.problems">Errors and anomalies only</option>
|
||
<option value="important" data-i18n="notifications.important">Important events + problems</option>
|
||
</select></label>
|
||
<label><span data-i18n="notifications.provider">Provider</span><select name="notifications_provider">
|
||
<option value="pushover">Pushover</option>
|
||
<option value="slack">Slack</option>
|
||
<option value="discord">Discord</option>
|
||
</select></label>
|
||
<div class="wide notification-provider" data-notification-provider="pushover"><label><span
|
||
data-i18n="notifications.pushoverToken">Pushover application token</span><input type="password"
|
||
name="pushover_app_token" autocomplete="new-password" data-i18n-placeholder="settings.secretKeep"
|
||
placeholder="Leave empty to keep saved secret"></label><label><span
|
||
data-i18n="notifications.pushoverUser">Pushover user/group key</span><input type="password"
|
||
name="pushover_user_key" autocomplete="new-password" data-i18n-placeholder="settings.secretKeep"
|
||
placeholder="Leave empty to keep saved secret"></label></div>
|
||
<label class="wide notification-provider" data-notification-provider="slack"><span
|
||
data-i18n="notifications.slackWebhook">Slack incoming webhook</span><input type="password"
|
||
name="slack_webhook_url" autocomplete="new-password"
|
||
placeholder="https://hooks.slack.com/services/…"></label>
|
||
<label class="wide notification-provider" data-notification-provider="discord"><span
|
||
data-i18n="notifications.discordWebhook">Discord webhook</span><input type="password"
|
||
name="discord_webhook_url" autocomplete="new-password"
|
||
placeholder="https://discord.com/api/webhooks/…"></label>
|
||
<label><span data-i18n="notifications.cooldown">Cooldown (s)</span><input type="number"
|
||
name="notification_cooldown_seconds" min="30" max="86400" value="300"></label>
|
||
<label><span data-i18n="notifications.failureThreshold">Communication failures before alert</span><input
|
||
type="number" name="notification_failure_threshold" min="2" max="100" value="3"></label>
|
||
<label><span data-i18n="notifications.targetTimeout">Target not reached timeout (min)</span><input
|
||
type="number" name="notification_target_timeout" min="5" max="1440" value="60"></label>
|
||
<fieldset class="notification-alert-types wide">
|
||
<legend data-i18n="notifications.alertTypes">Alert types</legend>
|
||
<p class="field-note" data-i18n="notifications.alertTypesHint">Choose exactly which alerts may be
|
||
delivered. Thresholds above still define when applicable alerts are raised.</p>
|
||
<div class="notification-alert-grid">
|
||
<label class="check"><input type="checkbox" name="notification_alert_stale_sensor"> <span
|
||
data-i18n="notifications.alertStaleSensor">Stale Home Assistant sensor readings</span></label>
|
||
<label class="check"><input type="checkbox" name="notification_alert_sensor_errors"> <span
|
||
data-i18n="notifications.alertSensorErrors">Other Home Assistant sensor errors</span></label>
|
||
<label class="check"><input type="checkbox" name="notification_alert_communication"> <span
|
||
data-i18n="notifications.alertCommunication">Device communication problems</span></label>
|
||
<label class="check"><input type="checkbox" name="notification_alert_target_timeout"> <span
|
||
data-i18n="notifications.alertTargetTimeout">Target temperature timeout</span></label>
|
||
<label class="check"><input type="checkbox" name="notification_alert_automation"> <span
|
||
data-i18n="notifications.alertAutomation">Automation errors and conflicts</span></label>
|
||
<label class="check"><input type="checkbox" name="notification_alert_control_errors"> <span
|
||
data-i18n="notifications.alertControlErrors">Thermostat and group control errors</span></label>
|
||
<label class="check"><input type="checkbox" name="notification_alert_important_events"> <span
|
||
data-i18n="notifications.alertImportantEvents">Important state changes</span></label>
|
||
<label class="check"><input type="checkbox" name="notification_alert_other"> <span
|
||
data-i18n="notifications.alertOther">Other warnings and errors</span></label>
|
||
</div>
|
||
</fieldset>
|
||
<div class="form-actions wide"><button type="button" class="secondary" id="testNotifications"
|
||
data-i18n="notifications.test">Send test notification</button></div>
|
||
</div>
|
||
</section>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.metricsAndLogs">Metrics and logs</h3>
|
||
<p data-i18n="settings.compactionHint">SQLite keeps recent data locally and compacts older samples to
|
||
the resolution used by charts.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label><span data-i18n="settings.retentionDays">Local metric retention (days)</span><input type="number"
|
||
name="history_retention_days" min="1" max="3650" required></label>
|
||
<label><span data-i18n="settings.eventRetentionDays">Event/log retention (days)</span><input type="number"
|
||
name="event_log_retention_days" min="1" max="3650" required></label>
|
||
<label class="check wide"><input type="checkbox" name="history_compaction_enabled"> <span
|
||
data-i18n="settings.compaction">Compact old metrics</span></label>
|
||
</div>
|
||
</section>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.influx">Long-term InfluxDB history</h3>
|
||
<p data-i18n="settings.influxHint">Optional archive for older history. InfluxDB 1.x and 2.x are
|
||
supported.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="check wide"><input type="checkbox" name="influx_enabled"> <span
|
||
data-i18n="settings.influxEnabled">Enable InfluxDB archive</span></label>
|
||
<label><span data-i18n="settings.influxVersion">InfluxDB version</span><select name="influx_version">
|
||
<option value="1">1.x</option>
|
||
<option value="2">2.x</option>
|
||
</select></label>
|
||
<label><span data-i18n="settings.influxThreshold">Use archive for history older than (days)</span><input
|
||
type="number" name="influx_threshold_days" min="1" max="3650" value="30"></label>
|
||
<label class="wide"><span>URL</span><input type="url" name="influx_url"
|
||
placeholder="http://influxdb:8086"></label>
|
||
<div class="wide influx-fields" data-influx-fields="1">
|
||
<label><span data-i18n="settings.influxDatabase">Database</span><input name="influx_database"
|
||
placeholder="gree_controller"></label>
|
||
<label><span data-i18n="settings.influxUsername">Username</span><input name="influx_username"></label>
|
||
<label><span data-i18n="settings.influxPassword">Password</span><input type="password"
|
||
name="influx_password" autocomplete="new-password" data-i18n-placeholder="settings.secretKeep"
|
||
placeholder="Leave empty to keep saved secret"></label>
|
||
</div>
|
||
<div class="wide influx-fields" data-influx-fields="2">
|
||
<label><span data-i18n="settings.influxOrg">Organization</span><input name="influx_org"></label>
|
||
<label><span data-i18n="settings.influxBucket">Bucket</span><input name="influx_bucket"
|
||
placeholder="gree_controller"></label>
|
||
<label><span data-i18n="settings.influxToken">Token</span><input type="password" name="influx_token"
|
||
autocomplete="new-password" data-i18n-placeholder="settings.secretKeep"
|
||
placeholder="Leave empty to keep saved secret"></label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.debug">On-screen debug</h3>
|
||
<p data-i18n="settings.debugHint">Live diagnostics displayed on every application page.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="check"><input type="checkbox" name="debug_overlay_enabled"> <span
|
||
data-i18n="settings.debugOverlay">Show debug window on every page</span></label>
|
||
<label class="check"><input type="checkbox" name="debug_gree_frames"> <span
|
||
data-i18n="settings.debugGreeFrames">Include GREE protocol frames</span></label>
|
||
</div>
|
||
</section>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.backup">Configuration backup</h3>
|
||
<p class="warning-note" data-i18n="settings.backupHint">Export/import application configuration.
|
||
Exported files can contain GREE device keys plus Home Assistant and InfluxDB secrets; metrics and API
|
||
access tokens are not included.</p>
|
||
</div>
|
||
</div>
|
||
<div class="form-actions backup-actions"><button type="button" class="secondary" id="exportSettings"
|
||
data-i18n="settings.export">Export settings</button><button type="button" class="secondary"
|
||
id="importSettings" data-i18n="settings.import">Import settings</button><input type="file"
|
||
id="importSettingsFile" accept="application/json,.json" hidden></div>
|
||
</section>
|
||
<div class="panel system-panel" id="systemInfo"></div>
|
||
</div>
|
||
<div class="settings-pane" data-settings-pane="gree" hidden>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.greeConnection">GREE connection</h3>
|
||
<p data-i18n="settings.greeConnectionHint">Controller identity, polling intervals and LAN discovery
|
||
transport.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label><span data-i18n="settings.clientId">Client identifier</span><input name="controller_id"
|
||
required></label>
|
||
<label><span data-i18n="settings.pollInterval">Poll interval (s)</span><input type="number"
|
||
name="poll_interval_seconds" min="2" max="3600" required></label>
|
||
<label><span data-i18n="settings.zoneInterval">Zone interval (s)</span><input type="number"
|
||
name="zone_interval_seconds" min="2" max="3600" required></label>
|
||
<label><span data-i18n="settings.broadcast">Broadcast address</span><input name="discovery_broadcast"
|
||
placeholder="255.255.255.255:7000" required></label>
|
||
<label><span data-i18n="settings.discoveryTimeout">Discovery timeout (ms)</span><input type="number"
|
||
name="discovery_timeout_ms" min="300" max="30000" required></label>
|
||
</div>
|
||
</section>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.greeCommands">GREE commands</h3>
|
||
<p data-i18n="settings.suppressBeepHint">Only changed properties are sent. Buzzer suppression is also
|
||
requested when supported by the unit firmware.</p>
|
||
</div>
|
||
</div>
|
||
<div class="settings-grid">
|
||
<label class="check wide"><input type="checkbox" name="suppress_device_beep"> <span
|
||
data-i18n="settings.suppressBeep">Try to suppress command beeps</span></label>
|
||
<label class="check wide"><input type="checkbox" name="compressor_protection_enabled"> <span
|
||
data-i18n="settings.compressorProtection">Compressor protection</span></label>
|
||
<label><span data-i18n="settings.compressorProtectionTime">Protection time (min)</span><input
|
||
type="number" name="compressor_protection_minutes" min="0.5" max="30" step="0.5" value="3"></label>
|
||
<p class="field-note wide" data-i18n="settings.compressorProtectionHint">Recommended: 3 minutes. Starts
|
||
and Heat/Cool changes requested during the protection window are queued and can be cancelled from
|
||
Thermostats.</p>
|
||
</div>
|
||
</section>
|
||
<section class="panel settings-block">
|
||
<div class="settings-block-head">
|
||
<div>
|
||
<h3 data-i18n="settings.greeTraffic">GREE traffic</h3>
|
||
<p data-i18n="settings.greeTrafficHint">Live counters of UDP frames received from configured air
|
||
conditioners since controller startup.</p>
|
||
</div>
|
||
</div>
|
||
<div id="greeFrameStats" class="gree-frame-stats"></div>
|
||
</section>
|
||
</div>
|
||
<div class="settings-save-bar"><span data-i18n="settings.saveHint">Save changes made in the blocks
|
||
above.</span><button class="primary" type="submit" data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="view" data-view="logs">
|
||
<div class="section-heading">
|
||
<div><span class="eyebrow" data-i18n="logs.diagnostics">Diagnostics</span>
|
||
<h1 data-i18n="nav.logs">Events</h1>
|
||
</div><button class="secondary" id="logsRefresh" data-i18n="actions.refresh">Refresh</button>
|
||
</div>
|
||
<div class="panel logs-toolbar">
|
||
<div><strong data-i18n="logs.retention">Log retention</strong><small data-i18n="logs.retentionHint">Old event
|
||
rows are removed automatically during maintenance.</small></div><label><span
|
||
data-i18n="logs.level">Level</span><select id="logLevelFilter">
|
||
<option value="all" data-i18n="logs.all">All</option>
|
||
<option value="error" data-i18n="logs.errors">Errors</option>
|
||
<option value="warn" data-i18n="logs.warnings">Warnings</option>
|
||
<option value="info" data-i18n="logs.info">Info</option>
|
||
</select></label><label><span data-i18n="logs.category">Category</span><select id="logCategoryFilter">
|
||
<option value="all" data-i18n="logs.all">All</option>
|
||
<option value="device" data-i18n="nav.devices">Devices</option>
|
||
<option value="zone" data-i18n="nav.zones">Thermostats</option>
|
||
<option value="automation" data-i18n="nav.automations">Automations</option>
|
||
<option value="settings" data-i18n="nav.settings">Settings</option>
|
||
<option value="integration" data-i18n="logs.integrations">Integrations</option>
|
||
<option value="system" data-i18n="logs.systemOther">System/other</option>
|
||
</select></label><label><span data-i18n="logs.keepFor">Keep for</span><select id="logRetentionDays">
|
||
<option value="7" data-i18n="logs.days7">7 days</option>
|
||
<option value="14" data-i18n="logs.days14">14 days</option>
|
||
<option value="30" data-i18n="logs.days30">30 days</option>
|
||
<option value="90" data-i18n="logs.days90">90 days</option>
|
||
<option value="180" data-i18n="logs.days180">180 days</option>
|
||
<option value="365" data-i18n="logs.days365">365 days</option>
|
||
</select></label><button class="secondary" id="saveLogRetention" data-i18n="actions.save">Save</button>
|
||
</div>
|
||
<div class="panel log-list" id="logList"></div>
|
||
</section>
|
||
</main>
|
||
|
||
|
||
<section id="flowEditor" class="flow-editor" hidden aria-label="Flow editor">
|
||
<header class="flow-editor-bar">
|
||
<div class="flow-editor-title"><button type="button" class="icon-button" data-action="close-flow-editor"
|
||
aria-label="Back">←</button>
|
||
<div><span class="eyebrow" data-i18n="flow.editorEyebrow">Flow editor</span>
|
||
<div class="flow-name-wrap">
|
||
<div id="flowNameView" class="flow-name-view" hidden><button id="flowNameText" class="flow-name-text"
|
||
type="button" data-action="edit-flow-name" data-i18n-title="flow.editName"
|
||
title="Edit Flow name"></button><button class="flow-name-edit" type="button"
|
||
data-action="edit-flow-name" data-i18n-title="flow.editName" data-i18n-aria="flow.editName"
|
||
title="Edit Flow name" aria-label="Edit Flow name">✎</button></div><input id="flowName" maxlength="100"
|
||
data-i18n-placeholder="flow.namePlaceholder" data-i18n-title="flow.nameAliasHint"
|
||
placeholder="My automation">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flow-editor-actions"><button class="secondary flow-desktop-action" type="button"
|
||
data-action="flow-templates" data-i18n="flow.templates">Templates</button><button
|
||
class="secondary flow-desktop-action" type="button" data-action="import-flow"
|
||
data-i18n="flow.import">Import</button><button class="secondary flow-desktop-action" type="button"
|
||
data-action="export-flow" data-i18n="flow.export">Export</button><button class="secondary flow-desktop-action"
|
||
type="button" data-action="flow-dry-run" data-i18n="flow.dryRun">Dry-run</button><button
|
||
class="secondary flow-desktop-action" type="button" data-action="flow-logs"
|
||
data-i18n="flow.logs">Logs</button><label class="flow-enabled"><input type="checkbox" id="flowEnabled"
|
||
checked><span id="flowEnabledLabel" data-i18n="common.enabled">Enabled</span></label><span
|
||
id="flowSaveStatus" class="flow-save-status" aria-live="polite"></span><span id="flowCompileStatus"
|
||
class="badge flow-compile-status"></span><button class="secondary flow-mobile-actions-button" type="button"
|
||
data-action="flow-mobile-actions" data-i18n="flow.actions">Actions</button></div>
|
||
<button class="primary flow-save-button" type="button" data-action="save-flow"
|
||
data-i18n="actions.save">Save</button>
|
||
</header>
|
||
<div class="flow-editor-body">
|
||
<aside class="flow-palette">
|
||
<div class="flow-palette-head"><strong data-i18n="flow.blocks">Blocks</strong><small
|
||
data-i18n="flow.paletteHint">Add a block, then connect its output to the next block.</small></div>
|
||
<div class="flow-palette-group flow-palette-trigger"><span data-i18n="flow.triggers">Wyzwalacze</span>
|
||
<button type="button" data-flow-add="cron_trigger" data-i18n="flow.node.cronTrigger">CRON</button>
|
||
</div>
|
||
<div class="flow-palette-group flow-palette-time"><span data-i18n="flow.time">Czas</span>
|
||
<button type="button" data-flow-add="weekday" data-i18n="flow.node.weekday">Dni tygodnia</button><button
|
||
type="button" data-flow-add="time_range" data-i18n="flow.node.timeRange">Przedział godzin</button><button
|
||
type="button" data-flow-add="date_range" data-i18n="flow.node.dateRange">Zakres dat</button><button
|
||
type="button" data-flow-add="night_mode" data-i18n="flow.node.nightMode">Tryb nocny</button>
|
||
</div>
|
||
<div class="flow-palette-group flow-palette-timeop"><span data-i18n="flow.timeOps">Operacje czasu</span>
|
||
<button type="button" data-flow-add="stable_for" data-i18n="flow.node.stableFor">Utrzymuje się
|
||
przez…</button><button type="button" data-flow-add="state_duration" data-i18n="flow.node.stateDuration">Czas
|
||
trwania stanu</button><button type="button" data-flow-add="on_change" data-i18n="flow.node.onChange">Tylko
|
||
przy zmianie</button><button type="button" data-flow-add="rate_limit" data-i18n="flow.node.rateLimit">Maks.
|
||
X razy / okres</button><button type="button" data-flow-add="delay"
|
||
data-i18n="flow.node.delay">Odczekaj…</button>
|
||
</div>
|
||
<div class="flow-palette-group flow-palette-sensor"><span data-i18n="flow.sensors">Sensory / wartości</span>
|
||
<button type="button" data-flow-add="outdoor_temperature" data-i18n="flow.node.outdoorTemperature">Temperatura
|
||
zewn.</button><button type="button" data-flow-add="device_temperature"
|
||
data-i18n="flow.node.deviceTemperature">Temperatura urządzenia</button><button type="button"
|
||
data-flow-add="zone_temperature" data-i18n="flow.node.zoneTemperature">Temperatura strefy</button><button
|
||
type="button" data-flow-add="house_mode" data-i18n="flow.node.houseMode">Tryb domu</button><button
|
||
type="button" data-flow-add="device_state" data-i18n="flow.node.deviceState">Stan urządzenia</button><button
|
||
type="button" data-flow-add="zone_state" data-i18n="flow.node.zoneState">Stan termostatu</button><button
|
||
type="button" data-flow-add="group_state" data-i18n="flow.node.groupState">Stan grupy</button><button
|
||
type="button" data-flow-add="ha_state" data-i18n="flow.node.haState">HA: stan</button><button type="button"
|
||
data-flow-add="ha_numeric" data-i18n="flow.node.haNumeric">HA: wartość</button><button type="button"
|
||
data-flow-add="ha_attribute" data-i18n="flow.node.haAttribute">HA: atrybut</button><button type="button"
|
||
data-flow-add="ha_available" data-i18n="flow.node.haAvailable">HA: dostępność</button><button type="button"
|
||
data-flow-add="constant" data-i18n="flow.node.constant">Stała testowa</button><button type="button"
|
||
data-flow-add="shared_input" data-i18n="flow.node.sharedInput">Wspólne wejście</button><button type="button"
|
||
data-flow-add="rolling_stat" data-i18n="flow.node.rollingStat">Średnia / mediana</button><button
|
||
type="button" data-flow-add="oscillates" data-i18n="flow.node.oscillates">Wartość oscyluje</button>
|
||
</div>
|
||
<div class="flow-palette-group flow-palette-logic"><span data-i18n="flow.logic">Logika</span><button
|
||
type="button" data-flow-add="logic_and" data-i18n="flow.node.and">AND</button><button type="button"
|
||
data-flow-add="logic_or" data-i18n="flow.node.or">OR</button><button type="button" data-flow-add="logic_not"
|
||
data-i18n="flow.node.not">NOT</button></div>
|
||
<div class="flow-palette-group flow-palette-action"><span data-i18n="flow.actions">Akcje</span>
|
||
<button type="button" data-flow-add="zone_thermostat"
|
||
data-i18n="flow.node.thermostat">Termostat</button><button type="button" data-flow-add="device_action"
|
||
data-i18n="flow.node.greeDevice">Urządzenie GREE</button><button type="button" data-flow-add="group_action"
|
||
data-i18n="flow.node.group">Grupa</button>
|
||
</div>
|
||
<div class="flow-palette-group flow-palette-haaction"><span data-i18n="flow.haActions">Home Assistant</span>
|
||
<button type="button" data-flow-add="ha_service_action" data-i18n="flow.node.haServiceAction">Home Assistant:
|
||
usługa</button>
|
||
</div>
|
||
</aside>
|
||
<div class="flow-workspace-wrap">
|
||
<div class="flow-workspace-toolbar">
|
||
<div class="flow-workspace-primary-actions"><button type="button" class="primary flow-add-block-button"
|
||
data-action="flow-add-block"><span aria-hidden="true">+</span><span data-i18n="flow.addBlock">Add
|
||
block</span></button><button type="button" class="secondary flow-selection-action"
|
||
data-action="flow-select-all" data-i18n="flow.selectAll">Zaznacz wszystko</button><button type="button"
|
||
class="secondary flow-selection-action" data-action="flow-clear-selection"
|
||
data-i18n="flow.clearSelection">Wyczyść zaznaczenie</button><span id="flowSelectionCount"
|
||
class="badge"></span></div>
|
||
<div class="flow-zoom-controls" role="group" data-i18n-aria="flow.zoomControls" aria-label="Canvas zoom">
|
||
<button type="button" class="secondary icon-button" data-action="flow-zoom-out"
|
||
data-i18n-title="flow.zoomOut" title="Zoom out">−</button><span id="flowZoomLabel"
|
||
aria-live="polite">100%</span><button type="button" class="secondary icon-button"
|
||
data-action="flow-zoom-in" data-i18n-title="flow.zoomIn" title="Zoom in">+</button><button type="button"
|
||
class="secondary flow-fit-button" data-action="flow-fit" data-i18n="flow.fitView" data-i18n-title="flow.fitView" title="Fit">Fit</button></div>
|
||
</div>
|
||
<div id="flowWorkspace" class="flow-workspace" tabindex="0">
|
||
<div id="flowCanvas" class="flow-canvas"><svg id="flowEdges" class="flow-edges" aria-hidden="true"></svg>
|
||
<div id="flowNodes" class="flow-nodes"></div>
|
||
</div>
|
||
<div id="flowEmptyHint" class="flow-empty-hint"><strong data-i18n="flow.emptyCanvas">Start by adding
|
||
blocks</strong><span data-i18n="flow.emptyCanvasHint">Conditions go on the left, actions on the
|
||
right.</span><button type="button" class="primary" data-action="flow-add-block"
|
||
data-i18n="flow.addBlock">Add block</button></div>
|
||
</div>
|
||
<div class="flow-natural-preview" id="flowNaturalPreview">
|
||
<button type="button" class="flow-preview-toggle" data-action="flow-preview-toggle"
|
||
aria-expanded="false"><strong data-i18n="flow.interpretation">Interpretation</strong><span
|
||
class="flow-preview-toggle-icon" aria-hidden="true">⌃</span></button>
|
||
<div class="flow-preview-details">
|
||
<div class="flow-preview-item flow-preview-interpretation"><strong
|
||
data-i18n="flow.interpretation">Interpretation</strong><span id="flowInterpretation"></span></div>
|
||
<div class="flow-preview-item flow-preview-runtime" id="flowRuntimeInfo"><strong
|
||
data-i18n="flow.runtimeInfo">Flow cycle</strong><span id="flowRuntimeSummary"></span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<aside id="flowInspector" class="flow-inspector">
|
||
<div class="empty compact"><strong data-i18n="flow.selectBlock">Select a block</strong><span
|
||
data-i18n="flow.selectBlockHint">Its settings will appear here.</span></div>
|
||
</aside>
|
||
</div>
|
||
</section>
|
||
|
||
<dialog id="flowBlockDialog" class="sheet flow-block-dialog">
|
||
<div class="dialog-head">
|
||
<div><span class="eyebrow" data-i18n="flow.blocks">Blocks</span>
|
||
<h2 data-i18n="flow.addBlock">Add block</h2>
|
||
</div><button type="button" data-close aria-label="Close">×</button>
|
||
</div>
|
||
<div class="flow-block-search"><input id="flowBlockSearch" type="search" autocomplete="off"
|
||
data-i18n-placeholder="flow.searchBlocks" placeholder="Search blocks…"></div>
|
||
<div id="flowBlockLibrary" class="flow-block-library"></div>
|
||
</dialog>
|
||
|
||
<dialog id="flowEditorActionsDialog" class="sheet flow-editor-actions-dialog">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="flow.actions">Actions</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<div class="menu-list">
|
||
<button type="button" data-action="flow-templates"><span
|
||
data-i18n="flow.templates">Templates</span><span>›</span></button>
|
||
<button type="button" data-action="import-flow"><span data-i18n="flow.import">Import</span><span>›</span></button>
|
||
<button type="button" data-action="export-flow"><span data-i18n="flow.export">Export</span><span>›</span></button>
|
||
<button type="button" data-action="flow-dry-run"><span
|
||
data-i18n="flow.dryRun">Dry-run</span><span>›</span></button>
|
||
<button type="button" data-action="flow-logs"><span data-i18n="flow.logs">Logs</span><span>›</span></button>
|
||
</div>
|
||
</dialog>
|
||
|
||
<input id="flowImportFile" type="file" accept="application/json,.json,.flow.json" hidden>
|
||
|
||
<dialog id="flowSharedInputDialog">
|
||
<form id="flowSharedInputForm" class="dialog-form">
|
||
<div class="dialog-head">
|
||
<div><span class="eyebrow" data-i18n="flow.sharedInputEyebrow">Wspólne dane</span>
|
||
<h2 id="flowSharedInputDialogTitle" data-i18n="flow.sharedInputTitle">Wspólne wejście Flow</h2>
|
||
</div><button type="button" data-close>×</button>
|
||
</div>
|
||
<input type="hidden" name="id">
|
||
<label><span data-i18n="common.name">Nazwa</span><input name="name" maxlength="100" required
|
||
placeholder="Okno w salonie zamknięte"></label>
|
||
<label><span data-i18n="flow.sharedInputType">Typ źródła</span><select name="kind"
|
||
id="flowSharedInputKind"></select></label>
|
||
<div id="flowSharedInputFields" class="flow-shared-input-fields"></div>
|
||
<div id="flowSharedInputTestPanel" class="flow-shared-test-panel" hidden>
|
||
<div><strong data-i18n="flow.sharedInputTest">Testuj wejście HA</strong>
|
||
<p class="field-note" data-i18n="flow.sharedInputTestHint">Test używa zapisanej konfiguracji połączenia Home
|
||
Assistant i nie zapisuje tego wejścia.</p>
|
||
</div>
|
||
<button type="button" class="secondary" id="flowSharedInputTest" data-i18n="flow.sharedInputTest">Testuj wejście
|
||
HA</button>
|
||
<div id="flowSharedInputTestResult" class="flow-shared-test-result" role="status" aria-live="polite" hidden>
|
||
</div>
|
||
</div>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Anuluj</button><button type="submit" class="primary"
|
||
data-i18n="actions.save">Zapisz</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="flowTemplateDialog" class="dialog-wide">
|
||
<div class="dialog-form">
|
||
<div class="dialog-head">
|
||
<div><span class="eyebrow" data-i18n="flow.templateLibrary">Flow library</span>
|
||
<h2 data-i18n="flow.templates">Templates</h2>
|
||
</div><button type="button" data-close>×</button>
|
||
</div>
|
||
<p class="field-note" data-i18n="flow.templatesHint">Ready-made layouts create an editable graph using existing
|
||
zones, devices and groups.</p>
|
||
<div class="flow-template-toolbar"><label><span data-i18n="flow.templateSearchLabel">Szukaj presetów</span><input
|
||
id="flowTemplateSearch" type="search" autocomplete="off" data-i18n-placeholder="flow.templateSearch"
|
||
placeholder="Szukaj presetów…"></label></div>
|
||
<div class="flow-template-browser">
|
||
<div class="flow-template-catalog">
|
||
<div id="flowTemplateTabs" class="flow-template-tabs" role="tablist" data-i18n-aria="flow.templateCategories"
|
||
aria-label="Preset categories"></div>
|
||
<div id="flowTemplateList" class="flow-template-list"></div>
|
||
</div>
|
||
<aside id="flowTemplatePreview" class="flow-template-preview">
|
||
<div class="empty compact"><strong data-i18n="flow.templatePreview">Podgląd presetu</strong><span
|
||
data-i18n="flow.templateSelectPreview">Wybierz preset, aby zobaczyć podgląd.</span></div>
|
||
</aside>
|
||
</div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="flowTestDialog" class="dialog-wide">
|
||
<div class="dialog-form">
|
||
<div class="dialog-head">
|
||
<div><span class="eyebrow" data-i18n="flow.testMode">Flow diagnostics</span>
|
||
<h2 id="flowTestTitle" data-i18n="flow.dryRun">Dry-run</h2>
|
||
</div><button type="button" data-close>×</button>
|
||
</div>
|
||
<div id="flowSimulationControls" class="flow-simulation-controls">
|
||
<p class="field-note" data-i18n="flow.dryRunHint">Dry-run does not change thermostat, device, group, schedule or
|
||
automation state.</p>
|
||
<label><span data-i18n="flow.simulationTime">Simulation date and time</span><input id="flowSimulationAt"
|
||
type="datetime-local"></label>
|
||
<div><strong data-i18n="flow.simulationOverrides">Sensor overrides</strong>
|
||
<p class="field-note" data-i18n="flow.simulationOverridesHint">Leave blank to use the current application or
|
||
Home Assistant state.</p>
|
||
<div id="flowSimulationOverrides" class="flow-simulation-overrides"></div>
|
||
</div>
|
||
<div class="form-actions"><button class="primary" type="button" data-action="run-flow-dry-run"
|
||
data-i18n="flow.runSimulation">Run simulation</button></div>
|
||
</div>
|
||
<div id="flowTestResults" class="flow-test-results"></div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<nav class="bottom-nav" data-i18n-aria="nav.navigation" aria-label="Navigation">
|
||
<span class="nav-section-label desktop-nav-only" data-i18n="nav.sectionControl">Sterowanie</span>
|
||
<button class="active" data-nav="dashboard"><span>⌂</span><b data-i18n="nav.dashboard">Dashboard</b></button>
|
||
<button data-nav="zones"><span>◎</span><b data-i18n="nav.zones">Zones</b></button>
|
||
<button class="desktop-nav-only" data-nav="groups"><span>◉</span><b data-i18n="nav.groups">Groups</b></button>
|
||
<span class="nav-section-label desktop-nav-only" data-i18n="nav.sectionAutomation">Automatyzacja</span>
|
||
<button data-nav="flows"><span>◇</span><b data-i18n="nav.flows">Flow</b></button>
|
||
<button class="desktop-nav-only" data-nav="schedules"><span>◷</span><b
|
||
data-i18n="nav.schedules">Schedules</b></button>
|
||
<button class="desktop-nav-only" data-nav="automations"><span>⌁</span><b
|
||
data-i18n="nav.automations">Automations</b></button>
|
||
<span class="nav-section-label desktop-nav-only" data-i18n="nav.sectionData">Dane i system</span>
|
||
<button data-nav="history"><span>⌁</span><b data-i18n="nav.history">History</b></button>
|
||
<button class="desktop-nav-only" data-nav="devices"><span>▣</span><b data-i18n="nav.devices">Devices</b></button>
|
||
<button class="desktop-nav-only" data-nav="homeassistant"><span>HA</span><b data-i18n="nav.homeAssistantShort">Home
|
||
Assistant</b></button>
|
||
<button class="desktop-nav-only" data-nav="simulation"><span>▶</span><b
|
||
data-i18n="nav.simulation">Simulator</b></button>
|
||
<button class="desktop-nav-only" data-nav="night"><span>☾</span><b data-i18n="nav.nightMode">Night mode</b></button>
|
||
<button class="desktop-nav-only" data-nav="logs"><span>≡</span><b data-i18n="nav.logs">Events</b></button>
|
||
<button class="desktop-nav-only" data-nav="settings"><span>⚙</span><b data-i18n="nav.settings">Settings</b></button>
|
||
<button class="mobile-nav-only" data-nav="more"><span>•••</span><b data-i18n="nav.more">More</b></button>
|
||
</nav>
|
||
|
||
<dialog id="moreDialog" class="sheet">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="nav.more">More</h2><button data-close>×</button>
|
||
</div>
|
||
<div class="menu-list more-menu-list">
|
||
<span class="menu-section-label" data-i18n="nav.sectionControl">Sterowanie</span>
|
||
<button data-go="devices"><span data-i18n="nav.devices">Devices</span><span>›</span></button>
|
||
<button data-go="groups"><span data-i18n="nav.groups">Groups</span><span>›</span></button>
|
||
<span class="menu-section-label" data-i18n="nav.sectionAutomation">Automatyzacja</span>
|
||
<button data-go="schedules"><span data-i18n="nav.schedules">Schedules</span><span>›</span></button>
|
||
<button data-go="automations"><span data-i18n="nav.automations">Automations</span><span>›</span></button>
|
||
<span class="menu-section-label" data-i18n="nav.sectionData">Dane i system</span>
|
||
<button data-go="simulation"><span data-i18n="nav.simulation">Simulator</span><span>›</span></button>
|
||
<button data-go="night"><span data-i18n="nav.nightMode">Night mode</span><span>›</span></button>
|
||
<button data-go="homeassistant"><span data-i18n="nav.homeAssistant">Home Assistant /
|
||
Sensors</span><span>›</span></button>
|
||
<button data-go="settings"><span data-i18n="nav.settings">Settings</span><span>›</span></button>
|
||
<button data-go="logs"><span data-i18n="nav.logsAndEvents">Events and logs</span><span>›</span></button>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="deviceDialog">
|
||
<form method="dialog" id="deviceForm" class="dialog-form">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="devices.add">Add device</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<label><span data-i18n="common.name">Name</span><input name="name" required
|
||
data-i18n-placeholder="placeholder.livingRoom" placeholder="Living room"></label>
|
||
<label><span>MAC / CID</span><input name="mac" required placeholder="AABBCCDDEEFF"></label>
|
||
<label><span data-i18n="devices.ipAddress">IP address</span><input name="ip" required
|
||
placeholder="192.168.1.50"></label>
|
||
<div class="two"><label><span>Port</span><input type="number" name="port" value="7000" min="1"
|
||
max="65535"></label><label><span data-i18n="devices.protocol">Protocol</span><select
|
||
name="protocol_version">
|
||
<option value="0" data-i18n="devices.protocolAuto">Auto (V1 + V2)</option>
|
||
<option value="1">V1 AES-ECB</option>
|
||
<option value="2">V2 AES-GCM</option>
|
||
</select></label></div>
|
||
<label><span data-i18n="devices.keyOptional">Key (optional)</span><input name="key"
|
||
data-i18n-placeholder="devices.keyPlaceholder" placeholder="Leave empty for automatic bind"></label>
|
||
<label class="check"><input type="checkbox" name="simulated"> <span data-i18n="devices.simulated">Simulated
|
||
device</span></label>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
||
data-i18n="actions.add">Add</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
|
||
<dialog id="discoverDialog">
|
||
<form method="dialog" id="discoverForm" class="dialog-form">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="discovery.title">Discover GREE devices</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<p class="field-note" data-i18n="discovery.help">Auto searches both AES-ECB and AES-GCM devices. Multiple passes
|
||
improve discovery when several Wi-Fi modules answer the same broadcast.</p>
|
||
<label><span data-i18n="discovery.protocol">Discovery protocol</span><select name="protocol_version">
|
||
<option value="0" data-i18n="devices.protocolAuto">Auto (V1 + V2)</option>
|
||
<option value="1">V1 AES-ECB</option>
|
||
<option value="2">V2 AES-GCM</option>
|
||
</select></label>
|
||
<div class="two"><label><span data-i18n="discovery.passes">Scan passes</span><input type="number" name="passes"
|
||
min="1" max="10" value="3"></label><label><span data-i18n="discovery.timeout">Total scan time
|
||
(ms)</span><input type="number" name="timeout_ms" min="500" max="30000" value="6000"></label></div>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
||
data-i18n="actions.discover">Discover</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="discoveryNamesDialog">
|
||
<form method="dialog" id="discoveryNamesForm" class="dialog-form">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="discovery.nameDevices">Name discovered devices</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<p class="field-note" data-i18n="discovery.nameDevicesHelp">Give each new unit a friendly room name. The technical
|
||
model and MAC remain available in diagnostics.</p>
|
||
<div id="discoveryNamesList" class="discovery-name-list"></div>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.later">Later</button><button class="primary" type="submit"
|
||
data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="renameDeviceDialog">
|
||
<form method="dialog" id="renameDeviceForm" class="dialog-form">
|
||
<input type="hidden" name="id">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="devices.technicalConfig">Technical configuration</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<label><span data-i18n="common.name">Name</span><input name="name" required maxlength="80"></label>
|
||
<div class="two"><label><span data-i18n="devices.ipAddress">IP address</span><input name="ip"
|
||
required></label><label><span>Port</span><input type="number" name="port" min="1" max="65535"
|
||
required></label></div>
|
||
<label><span data-i18n="devices.protocol">Protocol</span><select name="protocol_version">
|
||
<option value="0" data-i18n="devices.protocolAuto">Auto (V1 + V2)</option>
|
||
<option value="1">V1 AES-ECB</option>
|
||
<option value="2">V2 AES-GCM</option>
|
||
</select></label>
|
||
<p class="field-note" data-i18n="devices.protocolChangeHint">Changing protocol clears the saved device key. Save
|
||
and check connection immediately performs the required bind and test.</p>
|
||
<div id="deviceConfigCheckResult" class="config-check-result" hidden></div>
|
||
<div class="form-actions technical-config-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Cancel</button><button class="secondary" type="submit" data-save-mode="save"
|
||
data-i18n="actions.save">Save</button><button class="primary" type="submit" data-save-mode="check"
|
||
data-i18n="devices.saveAndCheck">Save and check connection</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="pingDialog" class="dialog-wide ping-dialog">
|
||
<div class="dialog-form">
|
||
<div class="dialog-head">
|
||
<div><span class="eyebrow" data-i18n="devices.diagnostics">Diagnostics</span>
|
||
<h2 data-i18n="devices.pingLive">Live ping</h2>
|
||
</div>
|
||
<button type="button" data-close>×</button>
|
||
</div>
|
||
<p class="field-note" data-i18n="devices.pingHint">Measures a minimal GREE round-trip without changing device
|
||
state, error counters or automation ownership. The chart refreshes while monitoring is enabled.</p>
|
||
<div class="ping-toolbar">
|
||
<label><span data-i18n="common.device">Device</span><select id="pingDeviceSelect"></select></label>
|
||
<label class="check ping-all-toggle"><input type="checkbox" id="pingAllDevices"> <span
|
||
data-i18n="devices.pingAll">Ping all units</span></label>
|
||
<button type="button" class="primary" id="pingToggleButton" data-action="ping-toggle"
|
||
data-i18n="devices.pingStop">Stop</button>
|
||
</div>
|
||
<div class="ping-live-grid" id="pingLiveGrid"></div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="zoneDialog">
|
||
<form method="dialog" id="zoneForm" class="dialog-form">
|
||
<input type="hidden" name="id">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="common.zone">Zone</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<label><span data-i18n="common.name">Name</span><input name="name" required
|
||
data-i18n-placeholder="placeholder.livingRoom" placeholder="Living room"></label>
|
||
<label><span data-i18n="common.device">Device</span><select name="device_id" required></select></label>
|
||
<div class="copy-settings-row"><select id="copyZoneSource">
|
||
<option value="" data-i18n="zones.copyFrom">Copy thermostat settings from…</option>
|
||
</select><button type="button" class="secondary" id="copyZoneSettings" data-i18n="zones.copySettings">Copy
|
||
settings</button></div>
|
||
<label><span data-i18n="zones.modePolicy">Mode policy</span><select name="mode_policy">
|
||
<option value="house" data-i18n="zones.followHouse">Follow global mode</option>
|
||
<option value="cool" data-i18n="zones.coolOnly">Cooling only</option>
|
||
<option value="heat" data-i18n="zones.heatOnly">Heating only</option>
|
||
</select></label><input type="hidden" name="setpoint" value="23">
|
||
<p class="field-note" data-i18n="zones.modePolicyHint">If this zone should use the global Heating/Cooling mode
|
||
selected in GREE Controller, leave “Follow global mode” unchanged. Cooling only / Heating only forces a fixed
|
||
mode for this zone.</p>
|
||
<details class="profile-editor">
|
||
<summary data-i18n="zones.profileTemperatures">Comfort / sleep / away temperatures</summary>
|
||
<div class="profile-grid"><strong data-i18n="mode.cool">Cooling</strong><label><span
|
||
data-i18n="preset.comfort">Comfort</span><input type="text" inputmode="decimal" step="0.5"
|
||
name="cool_comfort_setpoint" value="23"></label><label><span data-i18n="preset.sleep">Sleep</span><input
|
||
type="text" inputmode="decimal" step="0.5" name="cool_sleep_setpoint" value="24.5"></label><label><span
|
||
data-i18n="preset.away">Away</span><input type="text" inputmode="decimal" step="0.5"
|
||
name="cool_away_setpoint" value="27"></label></div>
|
||
<div class="profile-grid"><strong data-i18n="mode.heat">Heating</strong><label><span
|
||
data-i18n="preset.comfort">Comfort</span><input type="text" inputmode="decimal" step="0.5"
|
||
name="heat_comfort_setpoint" value="21"></label><label><span data-i18n="preset.sleep">Sleep</span><input
|
||
type="text" inputmode="decimal" step="0.5" name="heat_sleep_setpoint" value="19"></label><label><span
|
||
data-i18n="preset.away">Away</span><input type="text" inputmode="decimal" step="0.5"
|
||
name="heat_away_setpoint" value="17"></label></div>
|
||
</details>
|
||
<div class="two zone-hysteresis-row">
|
||
<div class="hysteresis-config"><label id="commonHysteresisField"><span data-i18n="zones.hysteresis">Hysteresis
|
||
°C</span><input type="text" inputmode="decimal" step="0.1" min="0.1" max="5" name="hysteresis"
|
||
value="0.6"></label><label class="check" data-i18n-title="zones.separateHysteresisHint"
|
||
title="Use different hysteresis values for heating and cooling"><input type="checkbox"
|
||
name="separate_hysteresis"> <span data-i18n="zones.separateHysteresis">Set heating and cooling hysteresis
|
||
separately</span></label></div><label><span data-i18n="zones.source">Temperature strategy</span><select
|
||
name="sensor_source">
|
||
<option value="combined" selected data-i18n="zones.combinedSensor">GREE + room sensor</option>
|
||
<option value="device" data-i18n="zones.greeSensor">GREE only</option>
|
||
<option value="home_assistant" data-i18n="zones.externalSensor">Room sensor only</option>
|
||
</select></label>
|
||
</div>
|
||
<div id="separateHysteresisFields" class="two" hidden><label><span data-i18n="zones.coolHysteresis">Cooling
|
||
hysteresis °C</span><input type="text" inputmode="decimal" step="0.1" min="0.1" max="5"
|
||
name="cool_hysteresis" value="0.6"></label><label><span data-i18n="zones.heatHysteresis">Heating hysteresis
|
||
°C</span><input type="text" inputmode="decimal" step="0.1" min="0.1" max="5" name="heat_hysteresis"
|
||
value="0.6"></label></div>
|
||
<div id="externalSensorFields">
|
||
<label><span data-i18n="zones.roomSensorEntity">Room sensor entity_id</span><input name="ha_entity_id"
|
||
placeholder="sensor.living_room_temperature"></label>
|
||
<div class="two"><label><span data-i18n="zones.roomSensorWeight">Room sensor weight %</span><input type="number"
|
||
step="5" min="0" max="100" name="external_sensor_weight_percent" value="40"></label><label><span
|
||
data-i18n="zones.maxDifference">Max. sensor difference °C</span><input type="text" inputmode="decimal"
|
||
step="0.1" min="0.1" max="20" name="max_sensor_difference" value="3.0"></label></div>
|
||
<p class="field-note" data-i18n="zones.sensorHelp">The room sensor is assigned only to this zone. If it becomes
|
||
unavailable, the controller falls back to the GREE sensor.</p>
|
||
</div>
|
||
<div class="two"><label><span data-i18n="zones.minAdjust">Minimum adjustment interval (s)</span><input
|
||
type="number" min="15" name="min_adjust_seconds" value="120"></label><label><span
|
||
data-i18n="zones.standbyOffset">Standby setpoint offset °C</span><input type="text" inputmode="decimal"
|
||
step="0.5" min="0.5" max="8" name="standby_offset_c" value="2"></label></div>
|
||
<label class="check"><input type="checkbox" name="smart_fan" checked> <span data-i18n="zones.smartFan">Smart fan
|
||
assist</span></label>
|
||
<input type="hidden" name="min_on_seconds" value="180"><input type="hidden" name="min_off_seconds"
|
||
value="180"><input type="hidden" name="sensor_stale_after_seconds" value="300"><input type="hidden"
|
||
name="revision" value="">
|
||
<label class="check"><input type="checkbox" name="enabled" checked> <span
|
||
data-i18n="common.enabled">Enabled</span></label>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
||
data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="compressorQueueDialog" class="compressor-queue-dialog">
|
||
<div class="dialog-form compressor-queue-dialog-body">
|
||
<div class="dialog-head">
|
||
<div><span class="eyebrow" data-i18n="zones.queueEyebrow">Compressor protection</span>
|
||
<h2 data-i18n="zones.queueTitle">Command queue</h2>
|
||
</div><button type="button" data-close>×</button>
|
||
</div>
|
||
<p class="field-note" data-i18n="zones.queueHint">Commands waiting for the compressor protection window to end.
|
||
You can cancel one task or clear the whole queue.</p>
|
||
<div class="compressor-queue-summary"><span data-i18n="zones.queuePendingLabel">Waiting</span><strong
|
||
id="compressorQueueModalCount">0</strong></div>
|
||
<div id="compressorQueueList" class="compressor-queue-list"></div>
|
||
<div class="form-actions compressor-queue-actions"><button type="button" class="danger"
|
||
id="compressorQueueCancelAll" data-action="cancel-all-compressor-tasks"
|
||
data-i18n="zones.cancelAllQueued">Cancel all waiting</button><button type="button" class="primary" data-close
|
||
data-i18n="actions.done">Done</button></div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="temporaryThermostatDialog">
|
||
<form method="dialog" id="temporaryThermostatForm" class="dialog-form temporary-thermostat-form">
|
||
<input type="hidden" name="zone_id">
|
||
<div class="dialog-head">
|
||
<div><span class="eyebrow" data-i18n="zones.quickThermostat">Szybki termostat</span>
|
||
<h2 data-i18n="zones.temporaryTitle">Włącz czasowo</h2>
|
||
</div><button type="button" data-close>×</button>
|
||
</div>
|
||
<div id="temporaryThermostatActive" class="temporary-active-summary" hidden>
|
||
<div><small id="temporaryThermostatActiveLabel" data-i18n="zones.temporaryActive">Aktywny tryb
|
||
czasowy</small><strong id="temporaryThermostatActiveCountdown">—</strong><span
|
||
id="temporaryThermostatActiveDetail"></span></div>
|
||
<button type="button" class="danger" id="temporaryThermostatStop" data-i18n="zones.temporaryStop">Zakończ
|
||
teraz</button>
|
||
</div>
|
||
<label><span data-i18n="zones.temporaryTarget">Temperatura szybkiego termostatu</span><input type="number"
|
||
name="target_temperature" min="8" max="30" step="0.5" required></label>
|
||
<label><span data-i18n="zones.temporaryStartRule">Kiedy uruchomić</span><select name="start_kind"
|
||
id="temporaryStartKind">
|
||
<option value="now" data-i18n="zones.temporaryStartNow">Od razu</option>
|
||
<option value="delay" data-i18n="zones.temporaryStartDelay">Z opóźnieniem</option>
|
||
<option value="at" data-i18n="zones.temporaryStartAt">O konkretnej dacie i godzinie</option>
|
||
</select></label>
|
||
|
||
<div id="temporaryStartDelayFields" class="temporary-rule-fields" hidden>
|
||
<label><span data-i18n="zones.temporaryStartDelayMinutes">Uruchom za (min)</span><input type="number"
|
||
name="start_delay_minutes" min="1" max="43200" value="30"></label>
|
||
<div class="temporary-presets"><button type="button" data-temporary-start-delay="15">15 min</button><button
|
||
type="button" data-temporary-start-delay="30">30 min</button><button type="button"
|
||
data-temporary-start-delay="60">1 h</button><button type="button" data-temporary-start-delay="120">2
|
||
h</button></div>
|
||
</div>
|
||
|
||
<div id="temporaryStartAtFields" class="temporary-rule-fields" hidden>
|
||
<label><span data-i18n="zones.temporaryStartAtDate">Uruchom o</span><input type="datetime-local"
|
||
name="start_at"></label>
|
||
</div>
|
||
|
||
<label><span data-i18n="zones.temporaryFinishRule">Kiedy wrócić do automatyki</span><select name="finish_kind"
|
||
id="temporaryFinishKind">
|
||
<option value="duration" data-i18n="zones.temporaryDuration">Po określonym czasie</option>
|
||
<option value="until" data-i18n="zones.temporaryUntil">O konkretnej dacie i godzinie</option>
|
||
<option value="temperature_reached" data-i18n="zones.temporaryReached">Po osiągnięciu warunku temperatury
|
||
</option>
|
||
<option value="temperature_stable" data-i18n="zones.temporaryStable">Po utrzymaniu warunku temperatury
|
||
</option>
|
||
<option value="schedule_boundary" data-i18n="zones.temporaryScheduleBoundary">Przy następnym przejściu
|
||
harmonogramu</option>
|
||
</select></label>
|
||
|
||
<div id="temporaryDurationFields" class="temporary-rule-fields">
|
||
<label><span data-i18n="zones.temporaryDurationMinutes">Czas działania (min)</span><input type="number"
|
||
name="duration_minutes" min="1" max="14400" value="60"></label>
|
||
<div class="temporary-presets"><button type="button" data-temporary-duration="30">30 min</button><button
|
||
type="button" data-temporary-duration="60">1 h</button><button type="button" data-temporary-duration="120">2
|
||
h</button><button type="button" data-temporary-duration="240">4 h</button></div>
|
||
</div>
|
||
|
||
<div id="temporaryUntilFields" class="temporary-rule-fields" hidden>
|
||
<label><span data-i18n="zones.temporaryUntilDate">Wyłącz o</span><input type="datetime-local"
|
||
name="until"></label>
|
||
</div>
|
||
|
||
<div id="temporaryTemperatureFields" class="temporary-rule-fields" hidden>
|
||
<div class="two"><label><span data-i18n="zones.temporaryCondition">Warunek</span><select
|
||
name="temperature_operator">
|
||
<option value="within" data-i18n="zones.temporaryWithin">w zakresie celu ± tolerancja</option>
|
||
<option value="at_or_below" data-i18n="zones.temporaryAtOrBelow">temperatura ≤ cel</option>
|
||
<option value="at_or_above" data-i18n="zones.temporaryAtOrAbove">temperatura ≥ cel</option>
|
||
</select></label><label><span data-i18n="zones.temporaryTolerance">Tolerancja °C</span><input type="number"
|
||
name="tolerance_c" min="0.1" max="3" step="0.1" value="0.3"></label></div>
|
||
<label id="temporaryHoldField"><span data-i18n="zones.temporaryHoldMinutes">Warunek musi trwać
|
||
(min)</span><input type="number" name="hold_minutes" min="1" max="1440" value="60"></label>
|
||
<label><span data-i18n="zones.temporarySafetyLimit">Limit bezpieczeństwa (min, opcjonalnie)</span><input
|
||
type="number" name="max_duration_minutes" min="1" max="14400" value="240"></label>
|
||
<p class="field-note" data-i18n="zones.temporaryStableHint">Jeśli temperatura wyjdzie poza warunek, licznik
|
||
utrzymania zeruje się i zaczyna od nowa po ponownym wejściu w zakres.</p>
|
||
</div>
|
||
|
||
<div id="temporaryScheduleFields" class="temporary-rule-fields" hidden>
|
||
<p class="field-note" data-i18n="zones.temporaryScheduleHint">Szybki termostat zakończy się przy najbliższej
|
||
zmianie aktywnego wpisu harmonogramu tej strefy.</p>
|
||
</div>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Anuluj</button><button class="primary" type="submit" id="temporaryThermostatSubmit"
|
||
data-i18n="zones.temporaryStart">Włącz czasowo</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="groupDialog">
|
||
<form method="dialog" id="groupForm" class="dialog-form">
|
||
<input type="hidden" name="id">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="groups.group">Group</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<label><span data-i18n="common.name">Name</span><input name="name" required
|
||
data-i18n-placeholder="groups.namePlaceholder" placeholder="Upstairs"></label>
|
||
<fieldset>
|
||
<legend data-i18n="groups.members">Group members</legend>
|
||
<div class="group-zone-choices" id="groupZoneChoices"></div>
|
||
</fieldset>
|
||
<p class="field-note" data-i18n="groups.membersHint">Groups are built from thermostat zones. ON takes control of
|
||
members; OFF powers their units down without leaving a group ownership lock.</p>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
||
data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="scheduleDialog">
|
||
<form method="dialog" id="scheduleForm" class="dialog-form">
|
||
<input type="hidden" name="id">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="common.schedule">Schedule</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<label><span data-i18n="common.name">Name</span><input name="name" required
|
||
data-i18n-placeholder="placeholder.night" placeholder="Night"></label>
|
||
<label><span data-i18n="common.zone">Zone</span><select name="zone_id" required></select></label>
|
||
<fieldset>
|
||
<legend data-i18n="schedules.weekdays">Weekdays</legend>
|
||
<div class="days"><label><input type="checkbox" name="weekday" value="1" checked><span
|
||
data-day="1">Mon</span></label><label><input type="checkbox" name="weekday" value="2" checked><span
|
||
data-day="2">Tue</span></label><label><input type="checkbox" name="weekday" value="3" checked><span
|
||
data-day="3">Wed</span></label><label><input type="checkbox" name="weekday" value="4" checked><span
|
||
data-day="4">Thu</span></label><label><input type="checkbox" name="weekday" value="5" checked><span
|
||
data-day="5">Fri</span></label><label><input type="checkbox" name="weekday" value="6"><span
|
||
data-day="6">Sat</span></label><label><input type="checkbox" name="weekday" value="7"><span
|
||
data-day="7">Sun</span></label></div>
|
||
</fieldset>
|
||
<div class="two"><label><span data-i18n="common.from">From</span><input type="time" name="start_time"
|
||
value="22:00" required></label><label><span data-i18n="common.to">To</span><input type="time"
|
||
name="end_time" value="06:00" required></label></div>
|
||
<label><span data-i18n="schedules.profile">Profile</span><select name="preset">
|
||
<option value="comfort" data-i18n="preset.comfort">Comfort</option>
|
||
<option value="sleep" data-i18n="preset.sleep">Sleep</option>
|
||
<option value="away" data-i18n="preset.away">Away</option>
|
||
<option value="custom" data-i18n="preset.custom">Custom temperature</option>
|
||
</select></label>
|
||
<label id="scheduleSetpointField"><span data-i18n="common.temperatureC">Custom temperature °C</span><input
|
||
type="text" inputmode="decimal" name="setpoint" step="0.5" min="8" max="30" value="23"></label>
|
||
<label class="check"><input type="checkbox" name="enabled" checked> <span
|
||
data-i18n="common.enabled">Enabled</span></label>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
||
data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="automationDialog">
|
||
<form method="dialog" id="automationForm" class="dialog-form">
|
||
<input type="hidden" name="id">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="common.automation">Automation</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<div class="copy-settings-row"><select id="automationPreset">
|
||
<option value="" data-i18n="automations.preset">Preset…</option>
|
||
<option value="hot" data-i18n="automations.presetHot">High temperature cooling</option>
|
||
<option value="cold" data-i18n="automations.presetCold">Low temperature heating</option>
|
||
<option value="morning" data-i18n="automations.presetMorning">Morning comfort</option>
|
||
<option value="nightoff" data-i18n="automations.presetNightOff">Night power off</option>
|
||
</select><button type="button" class="secondary" id="applyAutomationPreset"
|
||
data-i18n="actions.apply">Apply</button></div>
|
||
<label><span data-i18n="common.name">Name</span><input name="name" required
|
||
data-i18n-placeholder="automations.namePlaceholder" placeholder="Emergency cooling"></label>
|
||
<label><span data-i18n="automations.trigger">Trigger</span><select name="trigger_kind">
|
||
<option value="temperature_above" data-i18n="automations.tempAbove">Temperature above</option>
|
||
<option value="temperature_below" data-i18n="automations.tempBelow">Temperature below</option>
|
||
<option value="time" data-i18n="automations.time">Time</option>
|
||
</select></label>
|
||
<label><span data-i18n="automations.measurementDevice">Measurement device</span><select
|
||
name="trigger_device_id"></select></label>
|
||
<div class="two"><label><span data-i18n="automations.thresholdC">Threshold °C</span><input type="text"
|
||
inputmode="decimal" step="0.1" name="threshold" value="27"></label><label><span
|
||
data-i18n="automations.time">Time</span><input type="time" name="at_time" value="08:00"></label></div>
|
||
<hr>
|
||
<h3 data-i18n="automations.action">Action</h3>
|
||
<label><span data-i18n="automations.targetType">Target type</span><select name="action_target_kind">
|
||
<option value="device" data-i18n="common.device">Device</option>
|
||
<option value="group" data-i18n="groups.group">Group</option>
|
||
</select></label>
|
||
<label id="automationDeviceTarget"><span data-i18n="common.device">Device</span><select
|
||
name="action_device_id"></select></label>
|
||
<label id="automationGroupTarget" hidden><span data-i18n="groups.group">Group</span><select
|
||
name="action_group_id"></select></label>
|
||
<div class="two"><label><span data-i18n="common.power">Power</span><select name="action_power">
|
||
<option value="" data-i18n="actions.noChange">No change</option>
|
||
<option value="true" data-i18n="actions.turnOn">Turn on</option>
|
||
<option value="false" data-i18n="actions.turnOff">Turn off</option>
|
||
</select></label><label><span data-i18n="common.mode">Mode</span><select name="action_mode">
|
||
<option value="" data-i18n="actions.noChange">No change</option>
|
||
<option value="cool" data-i18n="mode.cool">Cooling</option>
|
||
<option value="heat" data-i18n="mode.heat">Heating</option>
|
||
<option value="dry" data-i18n="mode.dry">Dry</option>
|
||
<option value="fan" data-i18n="mode.fan">Fan</option>
|
||
<option value="auto" data-i18n="mode.auto">Auto</option>
|
||
</select></label></div>
|
||
<label id="automationGroupPreset" hidden><span data-i18n="groups.profile">Group profile</span><select
|
||
name="action_preset">
|
||
<option value="" data-i18n="actions.noChange">No change</option>
|
||
<option value="auto" data-i18n="preset.auto">Auto</option>
|
||
<option value="comfort" data-i18n="preset.comfort">Comfort</option>
|
||
<option value="sleep" data-i18n="preset.sleep">Sleep</option>
|
||
<option value="away" data-i18n="preset.away">Away</option>
|
||
</select></label>
|
||
<div class="two"><label id="automationTargetTemperature"><span data-i18n="common.targetC">Target °C</span><input
|
||
type="text" inputmode="decimal" step="0.1" min="8" max="30"
|
||
name="action_target_temperature"></label><label><span data-i18n="common.cooldownSeconds">Cooldown
|
||
(s)</span><input type="number" min="30" name="cooldown_seconds" value="300"></label></div>
|
||
<p class="field-note" id="automationGroupHint" hidden data-i18n="automations.groupHint">For a group, Auto mode
|
||
means follow the whole-house heating/cooling mode. Group presets are applied to all member zones.</p>
|
||
<label class="check"><input type="checkbox" name="enabled" checked> <span
|
||
data-i18n="common.enabled">Enabled</span></label>
|
||
<div class="form-actions"><button type="button" class="secondary" data-close
|
||
data-i18n="actions.cancel">Cancel</button><button class="primary" type="submit"
|
||
data-i18n="actions.save">Save</button></div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="generatedTokenDialog" class="auth-dialog">
|
||
<div class="dialog-form">
|
||
<div class="dialog-head">
|
||
<h2 data-i18n="settings.tokenCreated">Token created</h2><button type="button" data-close>×</button>
|
||
</div>
|
||
<p class="field-note" data-i18n="settings.tokenCreatedHint">Copy this token now. It will not be shown again.</p>
|
||
<label><span data-i18n="auth.token">Access token</span><input id="generatedAccessToken" class="mono"
|
||
readonly></label>
|
||
<div class="form-actions"><button type="button" class="secondary" id="copyAccessToken"
|
||
data-i18n="actions.copy">Copy</button><button type="button" class="primary" data-close
|
||
data-i18n="actions.done">Done</button></div>
|
||
</div>
|
||
</dialog>
|
||
|
||
<dialog id="tokenDialog" class="auth-dialog">
|
||
<form method="dialog" id="tokenForm" class="dialog-form">
|
||
<div class="brand large">
|
||
<div><strong>GREE Controller</strong><small data-i18n="auth.required">Authentication required</small></div>
|
||
</div>
|
||
<label><span data-i18n="auth.token">Access token</span><input type="password" name="token" required
|
||
autocomplete="current-password"></label>
|
||
<button class="primary" type="submit" data-i18n="auth.connect">Connect</button>
|
||
</form>
|
||
</dialog>
|
||
|
||
<aside id="debugOverlay" class="debug-overlay" hidden>
|
||
<div class="debug-overlay-head">
|
||
<div class="debug-overlay-title"><strong data-i18n="debug.title">Live debug</strong><small
|
||
id="debugOverlayStatus"></small></div>
|
||
<div class="debug-overlay-actions">
|
||
<div class="debug-source-tabs" role="tablist" data-i18n-aria="debug.filterAria" aria-label="Debug source">
|
||
<button type="button" class="active" role="tab" aria-selected="true" data-debug-filter="all"
|
||
data-i18n="debug.all">All</button>
|
||
<button type="button" role="tab" aria-selected="false" data-debug-filter="requests"
|
||
data-i18n="debug.requests">Requests</button>
|
||
<button type="button" role="tab" aria-selected="false" data-debug-filter="gree"
|
||
data-i18n="debug.gree">GREE</button>
|
||
</div>
|
||
<button type="button" class="debug-clear" data-action="debug-clear" data-i18n="debug.clear">Clear</button>
|
||
</div>
|
||
</div>
|
||
<div id="debugOverlayLines" class="debug-overlay-lines"></div>
|
||
</aside>
|
||
<div id="toastStack" class="toast-stack" role="status" aria-live="polite" aria-atomic="false"></div>
|
||
<script src="__GREE_APP_ASSET__" defer></script>
|
||
</body>
|
||
|
||
</html> |