diff --git a/README.md b/README.md index 2fea574a..7aa6e1c3 100644 --- a/README.md +++ b/README.md @@ -138,3 +138,12 @@ MQTT was tempting to remove as well since I don't use it, but it is genuinely us ### Improving the transmission +## License + +This project's own source is released into the public domain under [The Unlicense](LICENSE). + +The Unlicense covers **only the original code in this repository**. The firmware and +web bundle also include third-party components (e.g. Bootstrap Icons, ArduinoJson, +arduino-esp32) that remain under their own licenses and are **not** public domain. +Those components and their notices are listed in [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md). + diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md new file mode 100644 index 00000000..c49346b6 --- /dev/null +++ b/THIRD-PARTY-NOTICES.md @@ -0,0 +1,59 @@ +# Third-Party Notices + +This project's own source is released into the public domain under [The Unlicense](LICENSE). + +That dedication applies **only to the original code in this repository**. The project +also bundles and distributes third-party components that remain under their own +licenses — these are **not** public domain. Their copyright and permission notices are +retained below, and the full license texts ship alongside each component +(`components//LICENSE*`, `managed_components//`). + +## Web assets (`data/`) + +| Component | License | Copyright | Source | +|---|---|---|---| +| Bootstrap Icons (SVG files in `data/`: house-fill, house-gear-fill, pencil-fill, trash-fill, sun, sun-fill, file-earmark-arrow-up) | MIT | Copyright (c) 2019-2024 The Bootstrap Authors | https://github.com/twbs/icons | +| QR Code Generator for JavaScript (`qrcode.min.js`) | MIT | Copyright (c) 2009 Kazuhiko Arase | http://www.d-project.com/ | +| Material Symbols (`settings_remote.svg`) | Apache-2.0 | Copyright Google LLC | https://github.com/google/material-design-icons | + +## Firmware libraries (`components/`) + +| Component | License | Copyright | Source | +|---|---|---|---| +| ArduinoJson | MIT | Copyright © 2014-2025 Benoit Blanchon | https://arduinojson.org | +| PubSubClient | MIT | Copyright (c) 2008-2020 Nicholas O'Leary | https://github.com/knolleary/pubsubclient | +| arduinoWebSockets | LGPL-2.1 | Copyright (c) Markus Sattler | https://github.com/Links2004/arduinoWebSockets | +| ELECHOUSE CC1101 driver | see component source headers | Copyright (c) 2010 Michael (ELECHOUSE) | https://github.com/LSatan/SmartRC-CC1101-Driver-Lib | +| esp-homekit-sdk | Apache-2.0 | Copyright (c) Espressif Systems | https://github.com/espressif/esp-homekit-sdk | + +## Managed components (`managed_components/`, via the ESP-IDF Component Manager) + +| Component | License | Copyright | +|---|---|---| +| arduino-esp32 | LGPL-2.1 | Espressif Systems | +| joltwallet/esp_littlefs (bundles `littlefs`) | MIT (esp_littlefs) / BSD-3-Clause (littlefs core) | Brian Pugh / Christopher Haster | +| Espressif ESP-IDF components (mdns, json_parser, libsodium, etc.) | Apache-2.0 unless otherwise noted in the component | Espressif Systems | + +The MIT License (used by several components above) reads: + +``` +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` + +Refer to each component's bundled `LICENSE` file for the authoritative, full text of +its license (including the LGPL-2.1, Apache-2.0, and BSD-3-Clause terms). diff --git a/data/file-earmark-arrow-up.svg b/data/file-earmark-arrow-up.svg new file mode 100644 index 00000000..2f9de52b --- /dev/null +++ b/data/file-earmark-arrow-up.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/data/house-fill.svg b/data/house-fill.svg new file mode 100644 index 00000000..b24b3d05 --- /dev/null +++ b/data/house-fill.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/data/house-gear-fill.svg b/data/house-gear-fill.svg new file mode 100644 index 00000000..ec268ad2 --- /dev/null +++ b/data/house-gear-fill.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/data/icons.css b/data/icons.css index bf793e7b..0281131a 100644 --- a/data/icons.css +++ b/data/icons.css @@ -341,127 +341,22 @@ i.icss-anim:after { top: 54%; left: 54%; } +/* Bootstrap Icons served from LittleFS, painted via CSS mask so they inherit + the element's currentColor (the base i[class*="icss-"] rule sets + background-color: currentColor). */ i.icss-edit { width: 1em; height: 1em; - background-color: transparent; - border-radius: 50% 45% 50% 35%; - overflow: hidden; - margin: 0; + -webkit-mask: url('/pencil-fill.svg') center / contain no-repeat; + mask: url('/pencil-fill.svg') center / contain no-repeat; } - i.icss-edit:before { - width: .3em; - height: .8em; - border: .15em solid transparent; - border-top: .24em solid currentColor; - transform: rotate(45deg) translate(-50%); - transform-origin: 0 0; - box-shadow: 0 -.05em, .24em -.8em, -.24em -.8em, 0 -1.5em; - clip: rect(-.9em .3em 1em 0); - left: .25em; - top: .75em; - } - - i.icss-edit:after { - width: .1em; - height: 0; - background-color: transparent; - transform: translate(-50%, -50%); - top: 50%; - left: 50%; - } - i.icss-trash { - width: .68em; - height: .9em; - background-color: transparent; - border-width: .1em .1em; - border-style: solid; - border-radius: .05em; - margin: .1em .15em 0; -} - - i.icss-trash:before { - border-style: solid; - border-width: .1em; - top: -.23em; - left: 50%; - border-radius: .1em; - width: .275em; - height: 1.03em; - transform: translateX(-50%); - } - - i.icss-trash:after { - border-width: .1em .43em; - border-style: solid; - left: 50%; - top: -.05em; - border-radius: .07em; - transform: translateX(-50%); - } -i.icss-gear { - width: .5em; - height: .5em; - position: relative; - border-radius: 100%; - background-color: transparent; - border-width: .07em; - border-style: solid; - border-color: transparent; - margin: .25em; - box-shadow: 0 0 0 .1em, inset 0 0 0 .3em; -} - - i.icss-gear:before { - width: .18em; - height: .18em; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - box-shadow: .41em 0, -.41em 0, 0 .41em, 0 -.41em; - } - - i.icss-gear:after { - width: .18em; - height: .18em; - top: 50%; - left: 50%; - transform: translate(-50%, -50%) rotate(45deg); - box-shadow: .42em 0, -.42em 0, 0 .42em, 0 -.42em; - } -i.icss-gears { - width: .5em; - height: .5em; - position: relative; - border-radius: 100%; - border-width: .063em; - border-style: solid; - border-color: transparent; - margin: .36em .532em .08em .1em; - box-shadow: .51em -.32em 0 -.06em; + width: 1em; + height: 1em; + -webkit-mask: url('/trash-fill.svg') center / contain no-repeat; + mask: url('/trash-fill.svg') center / contain no-repeat; } - - i.icss-gears:before { - width: .7em; - height: .7em; - border-radius: 100%; - background: linear-gradient(0deg,transparent 39%,currentcolor 39%,currentcolor 61%, transparent 61%), linear-gradient(60deg,transparent 42%, currentcolor 42%,currentcolor 58%, transparent 58%), linear-gradient(120deg,transparent 42%, currentcolor 42%,currentcolor 58%, transparent 58%); - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - i.icss-gears:after { - width: .55em; - height: .55em; - border-radius: 100%; - background: linear-gradient(0deg,transparent 37%,currentcolor 37%,currentcolor 63%, transparent 63%), linear-gradient(60deg,transparent 40%, currentcolor 40%,currentcolor 60%, transparent 60%), linear-gradient(120deg,transparent 40%, currentcolor 40%,currentcolor 60%, transparent 60%); - top: -.135em; - left: .695em; - transform: translate(-50%, -50%) rotate(25deg); - } i.icss-somfy-down { width: 1em; height: 1em; @@ -529,36 +424,6 @@ i.icss-somfy-toggle { -i.icss-home { - width: .8em; - height: .45em; - background-color: transparent; - border-width: 0; - border-style: solid; - border-radius: 0 0 .02em .02em; - box-shadow: inset .285em .1em, inset -.285em .1em; - margin: .55em .1em 0; -} - - i.icss-home:before { - border-width: 0 .4em .4em; - border-style: solid; - border-color: currentColor transparent; - transform: translateX(-50%); - box-shadow: 0 .1em; - top: -.4em; - left: 50%; - } - - i.icss-home:after { - width: .76em; - height: .76em; - border-width: 0.065em 0 0 0.065em; - border-style: solid; - transform: translateX(-50%) rotate(45deg); - top: -0.4em; - left: 50%; - } i.icss-window { width: 1.1em; height: .75em; @@ -905,27 +770,10 @@ i.icss-lightbulb { i.icss-upload { width: 1em; - height: .6em; - background-color: transparent; - border-width: 0 .2em .3em; - border-style: solid; - border-radius: .03em; - margin: .4em 0 0; + height: 1em; + -webkit-mask: url('/file-earmark-arrow-up.svg') center / contain no-repeat; + mask: url('/file-earmark-arrow-up.svg') center / contain no-repeat; } - i.icss-upload:before { - height: .5em; - border-style: solid; - border-width: 0 .25em .25em; - border-color: transparent; - border-bottom-color: currentColor; - background-color: transparent; - box-shadow: 0em .35em 0 -.13em; - top: -.6em; - left: 50%; - transform: translateX(-50%); - } - i.icss-upload:after { - } i.icss-file { width: .8em; height: 1em; @@ -998,129 +846,29 @@ i.icss-awning { background-image: repeating-linear-gradient(90deg, var(--shade-color, currentColor), var(--shade-color, currentColor) calc(25% - 4px), black calc(25% - 2px), var(--shade-color, currentColor) calc(25% - 2px)); background-color: rgba(71, 212, 255, 0); } +/* Sun icons: sun-fill (lit / "on") and sun (outline / "off"), masked from the + served Bootstrap SVGs. icss-sun-c is the filled state, icss-sun-o the outline, + icss-sun the standalone indicator. */ i.icss-sun-c { width: 1em; height: 1em; - border-radius: 50%; - background-color: transparent; - background-image: radial-gradient(ellipse at center, #fd0 1%, #fb0 39%, #fb0 39%, #d61 100%); - box-shadow: 0 0 .06em .03em rgba(255, 107, 0, 0.4), 0 0 22px 11px rgba(255, 203, 0, 0.13); - background-position: -.7em -.6em; - background-size: 165%; - margin: 0; + -webkit-mask: url('/sun-fill.svg') center / contain no-repeat; + mask: url('/sun-fill.svg') center / contain no-repeat; } - i.icss-sun-c:before { - } - - i.icss-sun-c:after { - } - i.icss-sun { - width: .6em; - height: .6em; - border-radius: 50%; - background-color: transparent; - border: 0.03em solid transparent; - box-shadow: inset 0 0 0 .5em; - margin: .2em; -} - - i.icss-sun:before { - width: .1em; - height: .1em; - background-color: transparent; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - box-shadow: .45em 0, .38em 0, -.45em 0, -.38em 0, 0 .45em, 0 .38em, 0 -.45em, 0 -.38em; - } - - i.icss-sun:after { - width: .1em; - height: .1em; - background-color: transparent; - top: 50%; - left: 50%; - transform: translate(-50%, -50%) rotate(45deg); - box-shadow: .45em 0, .38em 0, -.45em 0, -.38em 0, 0 .45em, 0 .38em, 0 -.45em, 0 -.38em; - } -i.icss-sun-o { - width: .6em; - height: .6em; - border-radius: 50%; - background-color: transparent; - border: 0.03em solid transparent; - box-shadow: inset 0 0 0 .065em; - margin: .2em; -} - - i.icss-sun-o:before { - width: .1em; - height: .1em; - background-color: transparent; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - box-shadow: .45em 0, .38em 0, -.45em 0, -.38em 0, 0 .45em, 0 .38em, 0 -.45em, 0 -.38em; - } - - i.icss-sun-o:after { - width: .1em; - height: .1em; - background-color: transparent; - top: 50%; - left: 50%; - transform: translate(-50%, -50%) rotate(45deg); - box-shadow: .45em 0, .38em 0, -.45em 0, -.38em 0, 0 .45em, 0 .38em, 0 -.45em, 0 -.38em; - } -i.icss-sun-c { width: 1em; height: 1em; - border-radius: 50%; - background-color: transparent; - background-image: radial-gradient(ellipse at center, #fd0 1%, #fb0 39%, #fb0 39%, #d61 100%); - box-shadow: 0 0 .06em .03em rgba(255, 107, 0, 0.4), 0 0 22px 11px rgba(255, 203, 0, 0.13); - background-position: -.7em -.6em; - background-size: 165%; - margin: 0; + -webkit-mask: url('/sun-fill.svg') center / contain no-repeat; + mask: url('/sun-fill.svg') center / contain no-repeat; } - i.icss-sun-c:before { - } - - i.icss-sun-c:after { - } - i.icss-sun-o { - width: .6em; - height: .6em; - border-radius: 50%; - background-color: transparent; - border: 0.03em solid transparent; - box-shadow: inset 0 0 0 .065em; - margin: .2em; + width: 1em; + height: 1em; + -webkit-mask: url('/sun.svg') center / contain no-repeat; + mask: url('/sun.svg') center / contain no-repeat; } - - i.icss-sun-o:before { - width: .1em; - height: .1em; - background-color: transparent; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - box-shadow: .45em 0, .38em 0, -.45em 0, -.38em 0, 0 .45em, 0 .38em, 0 -.45em, 0 -.38em; - } - - i.icss-sun-o:after { - width: .1em; - height: .1em; - background-color: transparent; - top: 50%; - left: 50%; - transform: translate(-50%, -50%) rotate(45deg); - box-shadow: .45em 0, .38em 0, -.45em 0, -.38em 0, 0 .45em, 0 .38em, 0 -.45em, 0 -.38em; - } div.button-light { position:absolute; margin-left:-30px; @@ -1153,23 +901,19 @@ div.button-sunflag { margin-left:-30px; cursor:pointer; } - div.button-sunflag[data-on=false] i.icss-sun-c { - background-image: radial-gradient(ellipse at center, gainsboro 1%, #ccc 39%, silver 39%, gray 100%); - } - - div.button-sunflag > i.icss-sun-c { - position: absolute; - font-size: 18px; - color: orange; - left: 6px; - top: 7px; - } - + /* The fill (sun-c) and outline (sun-o) overlay in the same spot; data-on + picks which one shows. background-color paints the mask (orange here; + overridden to white inline in the Virtual Remote). */ + div.button-sunflag > i.icss-sun-c, div.button-sunflag > i.icss-sun-o { position: absolute; font-size: 32px; - color: orange; + background-color: orange; + left: 0; + top: 0; } + div.button-sunflag[data-on=false] > i.icss-sun-c { display: none; } + div.button-sunflag[data-on=true] > i.icss-sun-o { display: none; } i.icss-warning { width: 1em; height: .1em; diff --git a/data/index.html b/data/index.html index b39c8838..8a4f37a9 100644 --- a/data/index.html +++ b/data/index.html @@ -8,9 +8,9 @@ - - - + + + @@ -115,14 +115,14 @@ - +