{"title":"Black Friday 2026 – Älylaitteet","description":"\u003cdiv id=\"hesatek-bf-start\" data-starts-at=\"2026-11-10T00:00:00+02:00\" data-ends-at=\"2026-11-28T00:00:00+02:00\" data-ended=\"Black Friday 2026 -kampanja on päättynyt.\" data-started=\"Black Friday -tarjoukset ovat alkaneet!\" data-open-copy=\"Tarkista tuotteen liitännät, yhteensopivuus ja asennusvaatimukset. Vesiventtiilistä valitaan putkistoon sopiva koko.\"\u003e\n\u003cp\u003eÄlylaitteiden Black Friday 2026 -valikoimassa ovat OGEMRAY SMART RELAY 25A, Shelly Pro 4PM ja SMART WATER VALVE -vesiventtiilit koossa DN15, DN20 ja DN25.\u003c\/p\u003e\n\u003cp data-bf-copy hidden\u003e\u003c\/p\u003e\n\u003cp data-bf-validity\u003eTarjoukset voimassa 27.11.2026 asti.\u003c\/p\u003e\n\u003cspan class=\"visually-hidden\" data-bf-status role=\"status\"\u003e\u003c\/span\u003e\n\u003cdiv class=\"hesatek-bf-panel\" data-bf-panel hidden\u003e\n\u003cdiv\u003e\n\u003cspan class=\"bf-title\"\u003eTarjousten alkuun\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"bf-digits\" role=\"timer\" aria-live=\"off\"\u003e\n\u003cdiv\u003e\n\u003cspan class=\"bf-value\" data-bf-hours\u003e--\u003c\/span\u003e\u003cspan class=\"bf-unit\"\u003etuntia\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv\u003e\n\u003cspan class=\"bf-value\" data-bf-minutes\u003e--\u003c\/span\u003e\u003cspan class=\"bf-unit\"\u003eminuuttia\u003c\/span\u003e\n\u003c\/div\u003e\n\u003cdiv\u003e\n\u003cspan class=\"bf-value\" data-bf-seconds\u003e--\u003c\/span\u003e\u003cspan class=\"bf-unit\"\u003esekuntia\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cnav class=\"bf-nav\" aria-label=\"Black Friday -tuoteryhmät\" data-bf-after hidden\u003e\u003ca href=\"\/collections\/black-friday-2026-ilmalampopumput-latausasemat\"\u003eKaikki tarjoukset\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-ilmalampopumput\"\u003eIlmalämpöpumput\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-ilma-vesilampopumput\"\u003eIlma-vesilämpöpumput\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-maalampopumput\"\u003eMaalämpöpumput\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-jaahdytyslaitteet\"\u003eJäähdytyslaitteet\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-ilmanvaihtolaitteet\"\u003eIlmanvaihtolaitteet\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-latausasemat\"\u003eLatausasemat\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-alylaitteet\" aria-current=\"page\"\u003eÄlylaitteet\u003c\/a\u003e\u003ca href=\"\/collections\/black-friday-2026-lisavarusteet-tarvikkeet\"\u003eTarvikkeet ja lisävarusteet\u003c\/a\u003e\u003c\/nav\u003e\n\u003c\/div\u003e\n\u003cstyle\u003e.hesatek-bf-waiting .hdc:has(#hesatek-bf-start) .hdc-grid{filter:blur(9px);opacity:.65;pointer-events:none;user-select:none}\n.hesatek-bf-stage{position:relative;min-width:0;min-height:380px;isolation:isolate}\n.hesatek-bf-overlay{position:absolute;inset:0;z-index:3;padding:clamp(40px,8vw,88px) 20px 32px;background:rgba(255,255,255,.15);pointer-events:none}\n.hesatek-bf-panel{position:sticky;top:110px;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:20px;width:min(100%,620px);margin:0 auto;padding:28px;background:#111815;color:#fff;border-radius:10px;box-shadow:0 14px 40px #10251a1f}\n.hesatek-bf-panel [hidden],.hesatek-bf-panel[hidden]{display:none!important}\n.hesatek-bf-panel .bf-title{display:block;font-size:20px;font-weight:700;line-height:1.25}\n\n.hesatek-bf-panel .bf-digits{display:flex;gap:18px;text-align:center;flex-shrink:0}\n.hesatek-bf-panel .bf-value{display:block;min-width:2.2ch;font-size:36px;line-height:1.1;font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:-.02em}\n.hesatek-bf-panel .bf-unit{display:block;margin-top:5px;font-size:12px;line-height:1.4;color:#dbe6de}\n.hesatek-bf-streamers{position:fixed;inset:0;z-index:10000;overflow:hidden;pointer-events:none;contain:strict}\n.hesatek-bf-ribbon{position:absolute;top:-110px;width:30px;height:100px;animation:hesatek-bf-ribbon-fall 3s cubic-bezier(.2,.55,.45,1) both;will-change:transform,opacity}\n@keyframes hesatek-bf-ribbon-fall{0%{transform:translate3d(0,0,0) rotate(-15deg);opacity:0}8%{opacity:1}80%{opacity:1}100%{transform:translate3d(var(--bf-drift),calc(100vh + 220px),0) rotate(var(--bf-turn));opacity:0}}\n@media(min-width:1000px){.hdc-catalog\u003e.hesatek-bf-stage{grid-column:2;grid-row:4}}\n@media(max-width:599px){.hesatek-bf-overlay{padding:48px 12px 24px}.hesatek-bf-panel{flex-direction:column;justify-content:center;text-align:center;padding:24px 16px;gap:20px}}\n@media(prefers-reduced-motion:reduce){.hesatek-bf-streamers{display:none}.hesatek-bf-ribbon{animation:none}}#hesatek-bf-start [hidden]{display:none!important}\n.hdc-description:has(#hesatek-bf-start){max-width:none;width:100%}\n#hesatek-bf-start{width:100%;min-width:0}\n#hesatek-bf-start .bf-nav{display:flex;flex-wrap:wrap;gap:8px;margin:24px 0 0;padding:4px;border:0}\n#hesatek-bf-start .bf-nav a{display:inline-flex;align-items:center;min-height:44px;padding:10px 16px;border:1px solid #cbd3ce;border-radius:999px;background:#fff;color:#24352b;font-size:14px;line-height:1.45;font-weight:500;text-decoration:none;box-shadow:none}\n#hesatek-bf-start .bf-nav a:hover{border-color:#007f29;background:#f3faf6;color:#007f29}\n#hesatek-bf-start .bf-nav a[aria-current=page]{border-color:#007f29;background:#007f29;color:#fff;font-weight:700}\n#hesatek-bf-start .bf-nav a:focus-visible{outline:3px solid #007f29;outline-offset:3px}\n.hdc:has(#hesatek-bf-start) .hdc-catalog\u003e.hdc-categories{display:none}\n@media(max-width:767px){#hesatek-bf-start .bf-nav{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;overscroll-behavior-x:contain;scroll-padding-inline:4px;padding-bottom:12px}#hesatek-bf-start .bf-nav::-webkit-scrollbar{display:none}#hesatek-bf-start .bf-nav a{flex:0 0 auto;white-space:nowrap}}\n#hesatek-bf-start\u003ep{max-width:76ch}#hesatek-bf-start\u003ep+p{margin-top:12px}\u003c\/style\u003e\n\u003cscript\u003e(function () {\n  var root = document.getElementById('hesatek-bf-start');\n  if (!root || root.dataset.ready) return;\n  var deadline = Date.parse(root.dataset.startsAt);\n  var end = Date.parse(root.dataset.endsAt);\n  if (!Number.isFinite(deadline)) return;\n  root.dataset.ready = 'true';\n  var page = document.documentElement;\n  var waitingClass = 'hesatek-bf-waiting';\n  var launchKey = 'hesatek-bf-opening-' + deadline;\n  if (Date.now() \u003c deadline) page.classList.add(waitingClass);\n\n  function celebrate() {\n    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;\n    if (document.hidden) {\n      var onVisible = function () {\n        if (!document.hidden) {\n          document.removeEventListener('visibilitychange', onVisible);\n          celebrate();\n        }\n      };\n      document.addEventListener('visibilitychange', onVisible);\n      return;\n    }\n    var shower = document.createElement('div');\n    shower.className = 'hesatek-bf-streamers';\n    shower.setAttribute('aria-hidden', 'true');\n    var colors = ['#009730', '#56b76b', '#e6bd60', '#dbe6de'];\n    for (var i = 0; i \u003c 28; i += 1) {\n      var ribbon = document.createElement('span');\n      ribbon.className = 'hesatek-bf-ribbon';\n      ribbon.style.left = (i * 100 \/ 28) + '%';\n      ribbon.style.setProperty('--bf-drift', ((i % 2 ? 1 : -1) * (40 + Math.random() * 130)) + 'px');\n      ribbon.style.setProperty('--bf-turn', ((i % 2 ? 1 : -1) * (180 + Math.random() * 360)) + 'deg');\n      ribbon.style.animationDelay = (Math.random() * 0.35) + 's';\n      ribbon.style.animationDuration = (2.4 + Math.random() * 0.7) + 's';\n      var svg = document.createElementNS('http:\/\/www.w3.org\/2000\/svg', 'svg');\n      svg.setAttribute('viewBox', '0 0 30 100');\n      svg.setAttribute('width', '30');\n      svg.setAttribute('height', '100');\n      svg.setAttribute('focusable', 'false');\n      var path = document.createElementNS('http:\/\/www.w3.org\/2000\/svg', 'path');\n      path.setAttribute('d', 'M15 0 C-5 10 35 20 15 30 S-5 50 15 60 S35 80 15 100');\n      path.setAttribute('fill', 'none');\n      path.setAttribute('stroke', colors[i % colors.length]);\n      path.setAttribute('stroke-width', String(3 + i % 4));\n      path.setAttribute('stroke-linecap', 'round');\n      svg.appendChild(path);\n      ribbon.appendChild(svg);\n      shower.appendChild(ribbon);\n    }\n    document.body.appendChild(shower);\n    window.setTimeout(function () { shower.remove(); }, 3600);\n  }\n\n  function init() {\n    var section = root.closest('[data-hdc]');\n    var grid = section \u0026\u0026 section.querySelector('.hdc-grid');\n    var panel = root.querySelector('[data-bf-panel]');\n    var parts = ['hours', 'minutes', 'seconds'].map(function (name) {\n      return panel.querySelector('[data-bf-' + name + ']');\n    });\n    var stage;\n    var interval;\n    var finished = false;\n    var originalInert = grid \u0026\u0026 grid.inert;\n    var originalHidden = grid \u0026\u0026 grid.getAttribute('aria-hidden');\n\n    function release() {\n      page.classList.remove(waitingClass);\n      panel.remove();\n      root.querySelector('[data-bf-copy]').hidden = false;\n      root.querySelector('[data-bf-copy]').textContent = Date.now() \u003e= end ? root.dataset.ended : root.dataset.openCopy;\n      root.querySelector('[data-bf-status]').textContent = Date.now() \u003e= end ? root.dataset.ended : root.dataset.started;\n      root.querySelectorAll('[data-bf-after]').forEach(function (element) { element.hidden = false; });\n      if (grid) {\n        grid.inert = originalInert;\n        if (originalHidden === null) grid.removeAttribute('aria-hidden');\n        else grid.setAttribute('aria-hidden', originalHidden);\n      }\n      if (stage) stage.replaceWith(grid);\n    }\n\n    function expireSale() {\n      if (Date.now() \u003c end) return;\n      root.querySelector('[data-bf-copy]').hidden = false;\n      root.querySelector('[data-bf-copy]').textContent = root.dataset.ended;\n      root.querySelector('[data-bf-status]').textContent = root.dataset.ended;\n    }\n    if (Date.now() \u003c end) window.setTimeout(expireSale, Math.min(end - Date.now(), 2147483647));\n    document.addEventListener('visibilitychange', expireSale);\n\n    function openSale() {\n      if (finished) return;\n      finished = true;\n      window.clearInterval(interval);\n      document.removeEventListener('visibilitychange', update);\n      release();\n      var canRemember = false;\n      try {\n        window.sessionStorage.setItem(launchKey, String(Date.now()));\n        canRemember = true;\n      } catch (error) { \/* Storage can be disabled by the visitor. *\/ }\n      if (canRemember) {\n        \/\/ Refresh the catalog and prices, then celebrate once on the fresh page.\n        window.location.reload();\n      } else {\n        celebrate();\n        window.setTimeout(function () { window.location.reload(); }, 3600);\n      }\n    }\n\n    function update() {\n      var seconds = Math.max(0, Math.ceil((deadline - Date.now()) \/ 1000));\n      if (seconds === 0) { openSale(); return; }\n      [Math.floor(seconds \/ 3600), Math.floor(seconds \/ 60) % 60, seconds % 60].forEach(function (value, index) {\n        parts[index].textContent = String(value).padStart(2, '0');\n      });\n    }\n\n    if (Date.now() \u003e= deadline) {\n      release();\n      var opening = 0;\n      try {\n        opening = Number(window.sessionStorage.getItem(launchKey));\n        window.sessionStorage.removeItem(launchKey);\n      } catch (error) { \/* The catalog still opens without storage. *\/ }\n      if (opening \u003e 0 \u0026\u0026 Date.now() - opening \u003c 120000) celebrate();\n      return;\n    }\n\n    if (grid) {\n      stage = document.createElement('div');\n      stage.className = 'hesatek-bf-stage';\n      grid.before(stage);\n      stage.appendChild(grid);\n      grid.inert = true;\n      grid.setAttribute('aria-hidden', 'true');\n      var overlay = document.createElement('div');\n      overlay.className = 'hesatek-bf-overlay';\n      overlay.appendChild(panel);\n      stage.appendChild(overlay);\n    }\n    panel.hidden = false;\n    update();\n    interval = window.setInterval(update, 1000);\n    document.addEventListener('visibilitychange', update);\n  }\n  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, {once: true});\n  else init();\n})();\u003c\/script\u003e","products":[{"product_id":"ogemray-smart-relay-25a-alyrele","title":"OGEMRAY SMART RELAY 25A älyrele","description":"\u003cp\u003eOgemray Smart Relay 25A on tehokas älyrele suurille kuormille. Laite soveltuu esimerkiksi lämmityksen, suuritehoisten kuormien ja teollisten sovellusten ohjaukseen. Wi‑Fi‑yhteys mahdollistaa etäohjauksen ja automaatiot.\u003c\/p\u003e\n \u003cul\u003e\n \u003cli\u003eMax 25 A kuorma\u003c\/li\u003e\n \u003cli\u003eWi‑Fi‑ohjaus\u003c\/li\u003e\n \u003cli\u003eSopii suuritehoisille kuormille\u003c\/li\u003e\n \u003c\/ul\u003e\n \u003cp\u003eSmart Relay 25A on suunniteltu kohteisiin, joissa tavallinen älyrele ei riitä kuormankestoltaan.\u003c\/p\u003e","brand":"Shelly","offers":[{"title":"Default Title","offer_id":53723906670932,"sku":"2616156","price":36.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0605\/9501\/1684\/files\/HF_Ogemray_Smart_relay-25A.jpg?v=1770922343"},{"product_id":"shelly-pro-4pm","title":"SHELLY PRO 4PM","description":"\u003cp\u003eShelly Pro 4PM on DIN‑kiskoon asennettava nelikanavainen älyrele tehonmittauksella. Se mahdollistaa neljän kuorman ohjauksen ja mittauksen yhdellä laitteella, ja tukee Wi‑Fiä, LANia ja Bluetoothia.\u003c\/p\u003e\n \u003cul\u003e\n \u003cli\u003e4 kanavaa + tehonmittaus\u003c\/li\u003e\n \u003cli\u003eDIN‑kiskoasennus\u003c\/li\u003e\n \u003cli\u003eWi‑Fi + LAN + Bluetooth\u003c\/li\u003e\n \u003cli\u003ePaikallinen web‑hallinta\u003c\/li\u003e\n \u003c\/ul\u003e\n \u003cp\u003ePro 4PM soveltuu monikanavaiseen ohjaukseen ja energiaseurantaan sähkökaapeissa.\u003c\/p\u003e","brand":"Shelly","offers":[{"title":"Default Title","offer_id":53723909456212,"sku":"2710505","price":114.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0605\/9501\/1684\/files\/Shelly-Pro-4PM-main-image.png?v=1770922390"},{"product_id":"smart-water-valve-alykas-vesiventtiili","title":"SMART WATER VALVE älykäs vesiventtiili","description":"\u003cp\u003eFrankEver Smart Water Valve on Shelly‑yhteensopiva älykäs vesiventtiili. Se tukee Wi‑Fiä ja Bluetoothia sekä etähallintaa Shelly Smart Control ‑sovelluksessa. Venttiili soveltuu juomavesijärjestelmiin ja tukee automaatioita.\u003c\/p\u003e\n \u003cul\u003e\n \u003cli\u003eWi‑Fi + Bluetooth\u003c\/li\u003e\n \u003cli\u003eEtähallinta ja automaatiot\u003c\/li\u003e\n \u003cli\u003eNSF‑sertifioitu juomavedelle\u003c\/li\u003e\n \u003c\/ul\u003e\n \u003cp\u003eValitse sopiva koko: DN15 (1\/2\"), DN20 (3\/4\") tai DN25 (1\").\u003c\/p\u003e","brand":"Shelly","offers":[{"title":"DN15 (1\/2\")","offer_id":53723914666324,"sku":"7109702","price":130.0,"currency_code":"EUR","in_stock":true},{"title":"DN20 (3\/4\")","offer_id":53723914699092,"sku":"7109703","price":136.0,"currency_code":"EUR","in_stock":true},{"title":"DN25 (1\")","offer_id":53723914731860,"sku":"7109704","price":146.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0605\/9501\/1684\/files\/HF_FrankEver_Smart_water_valve-DN15.jpg?v=1770922451"}],"url":"https:\/\/hesatek.fi\/collections\/black-friday-2026-alylaitteet.oembed","provider":"Hesatek","version":"1.0","type":"link"}