Compare commits

...

23 Commits

Author SHA1 Message Date
dependabot[bot]
41f4062ab8 Bump docker/login-action from 3.6.0 to 3.7.0 (#1418)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.6.0 to 3.7.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.6.0...v3.7.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 3.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 17:24:35 +01:00
dependabot[bot]
f3fffe7b70 Bump github/codeql-action from 3 to 4 (#1411)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-30 13:55:10 +01:00
dependabot[bot]
c4b6a8bd8a Bump frenck/action-addon-linter from 2.18 to 2.21 (#1410)
Bumps [frenck/action-addon-linter](https://github.com/frenck/action-addon-linter) from 2.18 to 2.21.
- [Release notes](https://github.com/frenck/action-addon-linter/releases)
- [Commits](https://github.com/frenck/action-addon-linter/compare/v2.18...v2.21)

---
updated-dependencies:
- dependency-name: frenck/action-addon-linter
  dependency-version: '2.21'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-30 13:54:58 +01:00
dependabot[bot]
81d876b53b Bump actions/checkout from 5 to 6 (#1413)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-30 13:54:20 +01:00
Thomas
d15cb218ce Merge pull request #1414 from tt-tom17/main
fix slider and volume
2025-12-29 16:56:05 +01:00
tt-tom17
114f630b8a fix slider and volume 2025-12-29 16:09:02 +01:00
tt-tom17
53b627be88 fix Mute 2025-12-29 16:06:54 +01:00
tt-tom17
f2e1a7263d fix slider and volume 2025-12-29 15:52:34 +01:00
Armilar
1e2f89ed1d Update TypeScript version and fix slider functionality 2025-12-29 13:56:43 +01:00
joBr99
b6f36d4eac Bump actions/checkout from 4 to 5 (#1378) (add nextion2text) 2025-12-26 19:43:33 +00:00
dependabot[bot]
fa239f8bf0 Bump actions/checkout from 4 to 5 (#1378)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-26 20:41:01 +01:00
dependabot[bot]
2d1719673c Bump actions/setup-python from 5 to 6 (#1382)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-26 20:40:18 +01:00
dependabot[bot]
e9c275216c Bump home-assistant/builder from 2025.03.0 to 2025.09.0 (#1383)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2025.03.0 to 2025.09.0.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2025.03.0...2025.09.0)

---
updated-dependencies:
- dependency-name: home-assistant/builder
  dependency-version: 2025.09.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-26 20:40:07 +01:00
dependabot[bot]
b226b61281 Bump docker/login-action from 3.5.0 to 3.6.0 (#1388)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.5.0 to 3.6.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.5.0...v3.6.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 3.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-26 20:39:45 +01:00
dependabot[bot]
056d8f95c2 Bump stefanzweifel/git-auto-commit-action from 5 to 7 (#1391)
Bumps [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) from 5 to 7.
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v5...v7)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-26 20:39:34 +01:00
Armilar
52c695cf1c Update script version to v5.1.1.2 and fix screensaver logic 2025-12-21 15:33:31 +01:00
Johannes
8805e2189c Remove Tasmota downgrade instructions
Removed instructions for downgrading Tasmota to version 15.0.1.
2025-12-12 17:20:06 +01:00
Nigel Rook
341cdb47ab Fix weather entities reverting to daily forecast (#1402) 2025-11-29 16:47:04 +01:00
Stephen Wesche
3b25d47bc7 Improve clarity and formatting in prepare_nspanel.md (#1400)
Updated formatting and corrected typos in the NSPanel flashing guide.
2025-11-29 15:55:14 +01:00
jacekowski
a721d4ccd7 deduplicate registed callbacks (#1401) 2025-11-29 15:43:57 +01:00
Armilar
044abda65b Add check for ACTUAL state existence before SET 2025-11-21 23:33:54 +01:00
Armilar
155b08d6d5 Change subscription change type from 'any' to 'ne' 2025-11-21 23:19:57 +01:00
Armilar
c038745d1b Update NSPanel DEV TypeScript version to 5.1.1.1 2025-11-21 23:07:35 +01:00
13 changed files with 168 additions and 144 deletions

View File

@@ -21,7 +21,7 @@ jobs:
changed: ${{ steps.changed_addons.outputs.changed }} changed: ${{ steps.changed_addons.outputs.changed }}
steps: steps:
- name: Check out the repository - name: Check out the repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Get changed files - name: Get changed files
id: changed_files id: changed_files
@@ -68,7 +68,7 @@ jobs:
steps: steps:
- name: Check out repository - name: Check out repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Get information - name: Get information
id: info id: info
@@ -92,7 +92,7 @@ jobs:
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
if: env.BUILD_ARGS != '--test' if: env.BUILD_ARGS != '--test'
uses: docker/login-action@v3.5.0 uses: docker/login-action@v3.7.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
@@ -100,7 +100,7 @@ jobs:
- name: Build ${{ matrix.addon }} add-on - name: Build ${{ matrix.addon }} add-on
if: steps.check.outputs.build_arch == 'true' if: steps.check.outputs.build_arch == 'true'
uses: home-assistant/builder@2025.03.0 uses: home-assistant/builder@2025.09.0
with: with:
args: | args: |
${{ env.BUILD_ARGS }} \ ${{ env.BUILD_ARGS }} \

View File

@@ -43,11 +43,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v4
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@@ -58,7 +58,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v3 uses: github/codeql-action/autobuild@v4
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -72,4 +72,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v4

View File

@@ -15,10 +15,10 @@ jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@v5 - uses: actions/setup-python@v6
with: with:
python-version: 3.x python-version: 3.x
- run: pip install mkdocs-material mkdocs-video markdown-include mike - run: pip install mkdocs-material mkdocs-video markdown-include mike

View File

@@ -15,10 +15,10 @@ jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@v5 - uses: actions/setup-python@v6
with: with:
python-version: 3.x python-version: 3.x
- run: pip install mkdocs-material mkdocs-video markdown-include mike - run: pip install mkdocs-material mkdocs-video markdown-include mike

View File

@@ -11,7 +11,7 @@ jobs:
name: HACS Action name: HACS Action
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"
steps: steps:
- uses: "actions/checkout@v4" - uses: "actions/checkout@v6"
- name: HACS Action - name: HACS Action
uses: "hacs/action@main" uses: "hacs/action@main"
with: with:

View File

@@ -18,7 +18,7 @@ jobs:
gen-ioBroker-localization: gen-ioBroker-localization:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
@@ -28,7 +28,7 @@ jobs:
python HMI/code_gen/localization/iobroker.py python HMI/code_gen/localization/iobroker.py
mv ioBroker_NSPanel_locales.json ioBroker/ioBroker_NSPanel_locales.json mv ioBroker_NSPanel_locales.json ioBroker/ioBroker_NSPanel_locales.json
- uses: stefanzweifel/git-auto-commit-action@v5 - uses: stefanzweifel/git-auto-commit-action@v7
with: with:
commit_message: Update iobroker localization file commit_message: Update iobroker localization file
#file_pattern: "**.txt" #file_pattern: "**.txt"

View File

@@ -18,7 +18,7 @@ jobs:
addons: ${{ steps.addons.outputs.addons_list }} addons: ${{ steps.addons.outputs.addons_list }}
steps: steps:
- name: ⤵️ Check out code from GitHub - name: ⤵️ Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: 🔍 Find add-on directories - name: 🔍 Find add-on directories
id: addons id: addons
@@ -33,9 +33,9 @@ jobs:
path: ${{ fromJson(needs.find.outputs.addons) }} path: ${{ fromJson(needs.find.outputs.addons) }}
steps: steps:
- name: ⤵️ Check out code from GitHub - name: ⤵️ Check out code from GitHub
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: 🚀 Run Home Assistant Add-on Lint - name: 🚀 Run Home Assistant Add-on Lint
uses: frenck/action-addon-linter@v2.18 uses: frenck/action-addon-linter@v2.21
with: with:
path: "./${{ matrix.path }}" path: "./${{ matrix.path }}"

View File

@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
@@ -80,7 +80,7 @@ jobs:
find -name "**.txt" find -name "**.txt"
rm Nextion2Text.py* ignore-id.py out.txt rm Nextion2Text.py* ignore-id.py out.txt
- uses: stefanzweifel/git-auto-commit-action@v5 - uses: stefanzweifel/git-auto-commit-action@v7
with: with:
commit_message: ${{ steps.last-commit-message.outputs.msg }} (add nextion2text) commit_message: ${{ steps.last-commit-message.outputs.msg }} (add nextion2text)
#file_pattern: "**.txt" #file_pattern: "**.txt"

View File

@@ -1,4 +1,4 @@
+++ /dev/fd/62 2024-11-22 20:00:11.734673876 +0000 +++ /dev/fd/62 2025-12-26 19:43:25.803166597 +0000
+I/n2t-out/Program.s.txt +I/n2t-out/Program.s.txt
++ HMI/US/portrait/n2t-out/Program.s.txt ++ HMI/US/portrait/n2t-out/Program.s.txt
+1 +12,11 @@ +1 +12,11 @@

View File

@@ -151,7 +151,7 @@ class LuiController(object):
items = self._config.get_all_entity_names() items = self._config.get_all_entity_names()
apis.ha_api.log(f"gtest123: {items}") apis.ha_api.log(f"gtest123: {items}")
prefixes = ("navigate.", "delete", "iText") prefixes = ("navigate.", "delete", "iText")
items = [x for x in items if not (x is None or x.startswith(prefixes))] items = set([x for x in items if not (x is None or x.startswith(prefixes))])
apis.ha_api.log(f"Registering callbacks for the following items: {items}") apis.ha_api.log(f"Registering callbacks for the following items: {items}")
for item in items: for item in items:
if apis.ha_api.entity_exists(item): if apis.ha_api.entity_exists(item):

View File

@@ -388,11 +388,12 @@ class LuiPagesGen(object):
entityTypePanel = "text" entityTypePanel = "text"
unit = get_attr_safe(entity, "temperature_unit", "") unit = get_attr_safe(entity, "temperature_unit", "")
rt = None rt = None
index = item.stype
if type(item.stype) == str and ":" in item.stype and len(item.stype.split(":")) == 2: if type(item.stype) == str and ":" in item.stype and len(item.stype.split(":")) == 2:
spintstr = item.stype.split(":") spintstr = item.stype.split(":")
rt = spintstr[0] rt = spintstr[0]
item.stype = int(spintstr[1]) index = int(spintstr[1])
if type(item.stype) == int: if type(index) == int:
bits = get_attr_safe(entity, "supported_features", 0b0) bits = get_attr_safe(entity, "supported_features", 0b0)
if not rt: if not rt:
rt = "daily" rt = "daily"
@@ -407,8 +408,8 @@ class LuiPagesGen(object):
"weather/get_forecasts", target={"entity_id": entityId}, service_data={"type": rt} "weather/get_forecasts", target={"entity_id": entityId}, service_data={"type": rt}
) )
forecast = results.get("result", {}).get("response", {}).get(entityId, {}).get('forecast') or entity.attributes.get('forecast', []) forecast = results.get("result", {}).get("response", {}).get(entityId, {}).get('forecast') or entity.attributes.get('forecast', [])
if len(forecast) >= item.stype: if len(forecast) >= index:
day_forecast = forecast[item.stype] day_forecast = forecast[index]
fdate = dp.parse(day_forecast['datetime']) fdate = dp.parse(day_forecast['datetime'])
global babel_spec global babel_spec
if babel_spec is not None: if babel_spec is not None:

View File

@@ -1,70 +1,71 @@
# Flash Tasmota to your NSPanel # Flash Tasmota to Your NSPanel
You need to connect to your nspanel via serial and flash tasmota [tasmota32-nspanel.bin](http://ota.tasmota.com/tasmota32/release/tasmota32-nspanel.bin) to your NSPanel. You need to connect to your NSPanel via serial and flash Tasmota using [tasmota32-nspanel.bin](http://ota.tasmota.com/tasmota32/release/tasmota32-nspanel.bin).
You can use the Tasmota Web Installer to do so. [Tasmota Web Installer](https://tasmota.github.io/install/) You can use the [Tasmota Web Installer](https://tasmota.github.io/install/) to do so.
Checkout Blakadders Template Repo for more information on flashing, do not use the autoexec.be from this page. Check out Blakadder's Template Repo for more information on flashing. **Do not** use the autoexec.be from that page.
[NSPanel Page of the Tasmota Template Repository](https://templates.blakadder.com/sonoff_NSPanel.html) [NSPanel Page of the Tasmota Template Repository](https://templates.blakadder.com/sonoff_NSPanel.html)
If you prefer EspHome over Tasmota, you can use this thrid party esphome component, which is replacing tasmota and the berry driver of this project. If you prefer ESPHome over Tasmota, you can use this third-party ESPHome component, which replaces Tasmota and the Berry driver used in this project.
[ESPHome component](https://github.com/sairon/esphome-nspanel-lovelace-ui) [ESPHome Component](https://github.com/sairon/esphome-nspanel-lovelace-ui)
## Downgrade Tasmota
Downgrade your tasmoto to the 15.0.1 - in newer versions flashing the display is currently not working. ---
`https://ota.tasmota.com/tasmota32/release-15.0.1/tasmota32-nspanel.bin`
## Configure Tasmota Template for NSPanel ## Configure Tasmota Template for NSPanel
Configure the NSPanel template for Tasmota. (Go to Configuration and Configure Other and paste the template there, make sure to tick the activate checkbox) Configure the NSPanel template for Tasmota. (Go to Configuration > Configure Other, paste the template there, and make sure to tick the Activate checkbox.)
![tasmota-template-config](img/tasmota-template-config.png) ![tasmota-template-config](img/tasmota-template-config.png)
You can use the following template or copy the one on the [Tasmota Template Repo Site](https://templates.blakadder.com/sonoff_NSPanel.html). You can use the following template or copy the one from the [Tasmota Template Repo Site](https://templates.blakadder.com/sonoff_NSPanel.html):
`{"NAME":"NSPanel","GPIO":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],"FLAG":0,"BASE":1,"CMND":"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1"}` {"NAME":"NSPanel","GPIO":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],"FLAG":0,"BASE":1,"CMND":"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1"}
After a reboot of tasmota your screen will light up with the stock display firmware. After a reboot of Tasmota, your screen will light up with the stock display firmware.
---
## Upload Berry Driver to Tasmota ## Upload Berry Driver to Tasmota
Go to `Consoles` > `Console` in Tasmota and execute the following command: Go to Consoles > Console in Tasmota and execute the following command:
``` Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; SetOption151 0; Restart 1
Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; SetOption151 0;Restart 1
```
This will download the autoexec.be file from the repository and restart tasmota. This downloads the autoexec.be file from the repository and restarts Tasmota.
Note: The command is also disabling matter to free up memory, as it's most likely not used by any homeassistant users anyway. Note: This command also disables Matter to free up memory, as it's unlikely to be used by most Home Assistant users. (Matter can cause memory issues during flashing of the Nextion screen, but you can re-enable it later if needed.)
(Matter could cause memory issues during flashing of the Nextion Screen, but you can still enable it if you need to.)
---
## Flash Firmware to Nextion Screen ## Flash Firmware to Nextion Screen
Due the limitations of Berry, it's not possible to download the tft file directly from github, so I'm also renting a small server where you can download the file via HTTP. Due to the limitations of Berry, it's not possible to download the TFT file directly from GitHub. A small server is available to download the file via HTTP.
Use the one following commands in the tasmota console (not berry console) to flash the latest release from this repository: Use one of the following commands in the Tasmota console (not the Berry console) to flash the latest release from this repository:
EU Version: `FlashNextion http://nspanel.pky.eu/lui-release.tft` EU Version:
FlashNextion http://nspanel.pky.eu/lui-release.tft
US Version Portrait: `FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft` US Version Portrait:
FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
US Version Landscape: `FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft` US Version Landscape:
FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
After sending the command, the screen should show a progress bar. The flashing progress takes around 5 minutes. After sending the command, the screen should show a progress bar. The flashing process takes around 5 minutes.
Note: For the US Version Users - keep in mind that you need to add the model config option to your apps.yaml later, more details on config overview page Note for US users: You'll need to add the model config option to your apps.yaml later. More details can be found on the config overview page.
---
<details> <details>
<summary>Alternatively you can use your own webserver or the one build into HomeAssistant:</summary> <summary>Alternatively, you can use your own web server or the one built into Home Assistant:</summary>
<br> <br>
Upload the nspanel.tft from the lastest release to a Webserver (for example www folder of Home Assistant) and execute the following command in Tasmota Console. (Development Version: [tft file from HMI folder](HMI/nspanel.tft)) Upload the nspanel.tft from the latest release to a web server (for example, the www folder of Home Assistant) and execute the following command in the Tasmota Console.
(Development version: [TFT file from HMI folder](HMI/nspanel.tft))
**Webserver must be HTTP, HTTPS is not supported, due to limitations of berry lang on tasmota** **The web server must be HTTP. HTTPS is not supported due to Berry language limitations in Tasmota.**
`FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft` FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft
</details> </details>

View File

@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------- /*-----------------------------------------------------------------------
TypeScript v5.1.0.3 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar / @TT-Tom / @ticaki / @Britzelpuf / @Sternmiere / @ravenS0ne TypeScript v5.1.1.3 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar / @TT-Tom / @ticaki / @Britzelpuf / @Sternmiere / @ravenS0ne
- abgestimmt auf TFT 61 / v5.1.0 / BerryDriver 10 / Tasmota 15.0.1 - abgestimmt auf TFT 61 / v5.1.1 (v5.1.2 us-p) / BerryDriver 10 / Tasmota 15.2.0
Projekt: Projekt:
https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker
@@ -98,7 +98,10 @@ ReleaseNotes:
- 12.11.2025 - v5.1.0.1 Change Brightsky icon to icon_special - 12.11.2025 - v5.1.0.1 Change Brightsky icon to icon_special
- 15.11.2025 - v5.1.0.2 Add Swiss-Weather-API Adapter - 15.11.2025 - v5.1.0.2 Add Swiss-Weather-API Adapter
- 18.11.2025 - v5.1.0.3 Fix QR-Code Generation cardQR - 18.11.2025 - v5.1.0.3 Fix QR-Code Generation cardQR
- 21.11.2025 - v5.1.1.1 Add some LongPress Actions in TFT/HMI v5.1.1 for NSPanel Adapter
- 21.11.2025 - v5.1.1.1 Remove Subscription if .ON and ON_ACTUAL
- 21.12.2025 - v5.1.1.2 Left screensaver unit from ioBroker data point to create a dynamic screensaver (by ernstdaheim-hub)
- 29.12.2025 - v5.1.1.3 Fix popupSlider (Standard-Slider (not cardMedia) with Functionality on popupSlider) / Wrong Pictures in us-p Slider if BG-Color is black (0)
*************************************************************************************************************** ***************************************************************************************************************
* DE: Für die Erstellung der Aliase durch das Skript, muss in der JavaScript Instanz "setObject" gesetzt sein! * * DE: Für die Erstellung der Aliase durch das Skript, muss in der JavaScript Instanz "setObject" gesetzt sein! *
@@ -211,10 +214,10 @@ Install/Upgrades in Konsole:
Tasmota BerryDriver Install: Backlog UrlFetch https://raw.githubusercontent.com/ticaki/ioBroker.nspanel-lovelace-ui/refs/heads/main/tasmota/berry/10/autoexec.be; Restart 1 Tasmota BerryDriver Install: Backlog UrlFetch https://raw.githubusercontent.com/ticaki/ioBroker.nspanel-lovelace-ui/refs/heads/main/tasmota/berry/10/autoexec.be; Restart 1
Tasmota BerryDriver Update: Backlog UpdateDriverVersion https://raw.githubusercontent.com/ticaki/ioBroker.nspanel-lovelace-ui/refs/heads/main/tasmota/berry/10/autoexec.be; Restart 1 Tasmota BerryDriver Update: Backlog UpdateDriverVersion https://raw.githubusercontent.com/ticaki/ioBroker.nspanel-lovelace-ui/refs/heads/main/tasmota/berry/10/autoexec.be; Restart 1
TFT EU STABLE Version: FlashNextionAdv0 http://nspanel.de/nspanel-v5.1.0.tft TFT EU STABLE Version: FlashNextionAdv0 http://nspanel.de/nspanel-v5.1.1.tft
TFT US-L STABLE Version: FlashNextionAdv0 http://nspanel.de/nspanel-us-l-v5.1.0.tft TFT US-L STABLE Version: FlashNextionAdv0 http://nspanel.de/nspanel-us-l-v5.1.1.tft
TFT US-P STABLE Version: FlashNextionAdv0 http://nspanel.de/nspanel-us-p-v5.1.0.tft TFT US-P STABLE Version: FlashNextionAdv0 http://nspanel.de/nspanel-us-p-v5.1.2.tft
--------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------
*/ */
@@ -1000,8 +1003,8 @@ export const config: Config = {
// _________________________________ DE: Ab hier keine Konfiguration mehr _____________________________________ // _________________________________ DE: Ab hier keine Konfiguration mehr _____________________________________
// _________________________________ EN: No more configuration from here _____________________________________ // _________________________________ EN: No more configuration from here _____________________________________
const scriptVersion: string = 'v5.1.0.3'; const scriptVersion: string = 'v5.1.1.3';
const tft_version: string = 'v5.1.0'; const tft_version: string = 'v5.1.1';
const desired_display_firmware_version = 61; const desired_display_firmware_version = 61;
const berry_driver_version = 10; const berry_driver_version = 10;
@@ -4730,6 +4733,7 @@ function HandleMessage (typ: string, method: NSPanel.EventMethod, page: number |
} }
} }
break; break;
case 'buttonPress3':
case 'buttonPress2': case 'buttonPress2':
screensaverEnabled = false; screensaverEnabled = false;
HandleButtonEvent(words); HandleButtonEvent(words);
@@ -5236,7 +5240,7 @@ function CreateEntity (pageItem: PageItem, placeId: number, useColors: boolean =
val = getState(pageItem.id + '.ACTUAL').val; val = getState(pageItem.id + '.ACTUAL').val;
RegisterEntityWatcher(pageItem.id + '.ACTUAL'); RegisterEntityWatcher(pageItem.id + '.ACTUAL');
} }
if (existsState(pageItem.id + '.SET')) { if (existsState(pageItem.id + '.SET') && !existsState(pageItem.id + 'ACTUAL')) {
val = getState(pageItem.id + '.SET').val; val = getState(pageItem.id + '.SET').val;
RegisterEntityWatcher(pageItem.id + '.SET'); RegisterEntityWatcher(pageItem.id + '.SET');
} }
@@ -5249,7 +5253,7 @@ function CreateEntity (pageItem: PageItem, placeId: number, useColors: boolean =
val = getState(pageItem.id + '.ON_SET').val; val = getState(pageItem.id + '.ON_SET').val;
RegisterEntityWatcher(pageItem.id + '.ON_SET'); RegisterEntityWatcher(pageItem.id + '.ON_SET');
} }
if (existsState(pageItem.id + '.ON')) { if (existsState(pageItem.id + '.ON') && !existsState(pageItem.id + '.ON_ACTUAL')) {
val = getState(pageItem.id + '.ON').val; val = getState(pageItem.id + '.ON').val;
RegisterEntityWatcher(pageItem.id + '.ON'); RegisterEntityWatcher(pageItem.id + '.ON');
} }
@@ -6416,7 +6420,7 @@ function RegisterEntityWatcher (id: string): void {
return; return;
} }
subscriptions[id] = on({id: id, change: 'any'}, (obj) => { subscriptions[id] = on({id: id, change: 'ne'}, (obj) => {
//@ts-ignore //@ts-ignore
if (obj.oldState && obj.oldState.val === obj.state.val && obj.state.ack) { if (obj.oldState && obj.oldState.val === obj.state.val && obj.state.ack) {
return; return;
@@ -10185,6 +10189,10 @@ function HandleButtonEvent (words: any): void {
break; break;
} }
} }
} else {
let pageItemSlider = findPageItem(id);
let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItemSlider.maxValueLevel ? pageItemSlider.maxValue : 100, pageItemSlider.minValueLevel ? pageItemSlider.minValue : 0));
setIfExists(pageItemSlider.id + '.SET', sliderPos) ? true : setIfExists(id + '.ACTUAL', sliderPos);
} }
break; break;
case 'mode-seek': case 'mode-seek':
@@ -10500,7 +10508,11 @@ function HandleButtonEvent (words: any): void {
break; break;
} }
} catch (err: any) { } catch (err: any) {
log('error at function HandleButtonEvent: ' + err.message, 'warn'); if (err.message == "Cannot read properties of undefined (reading 'id')") {
} else {
log('error at function HandleButtonEvent: ' + err.message, 'warn');
}
} }
} }
@@ -11441,7 +11453,7 @@ function GenerateDetailPage (type: NSPanel.PopupType, optional: NSPanel.mediaOpt
let hSlider2MinVal: number = pageItem.minValue ?? 0; let hSlider2MinVal: number = pageItem.minValue ?? 0;
let hSlider2MaxVal: number = pageItem.maxValue ?? 100; let hSlider2MaxVal: number = pageItem.maxValue ?? 100;
let hSlider2ZeroVal: number = 0; let hSlider2ZeroVal: number = 0;
let hSlider2CurVal: number = getState(id + '.ACTUAL').val; let hSlider2CurVal: number = existsState(id + '.ACTUAL') ? getState(id + '.ACTUAL').val : getState(id + '.SET').val;
let hSlider2Step: number = 1; let hSlider2Step: number = 1;
let hSlider2Visibility: string = "enable"; let hSlider2Visibility: string = "enable";
@@ -12472,76 +12484,85 @@ function HandleScreensaverUpdate (): void {
} }
// 3 leftScreensaverEntities // 3 leftScreensaverEntities
if (screensaverAdvanced) { if (screensaverAdvanced) {
let checkpoint = true; let checkpoint = true;
let i = 0; let i = 0;
if (config.leftScreensaverEntity && Array.isArray(config.leftScreensaverEntity) && config.leftScreensaverEntity.length > 0) { if (config.leftScreensaverEntity && Array.isArray(config.leftScreensaverEntity) && config.leftScreensaverEntity.length > 0) {
for (i = 0; i < 3 && i < config.leftScreensaverEntity.length; i++) { for (i = 0; i < 3 && i < config.leftScreensaverEntity.length; i++) {
const leftScreensaverEntity = config.leftScreensaverEntity[i]; const leftScreensaverEntity = config.leftScreensaverEntity[i];
if (leftScreensaverEntity === null || leftScreensaverEntity === undefined) { if (leftScreensaverEntity === null || leftScreensaverEntity === undefined) {
checkpoint = false; checkpoint = false;
break; break;
} }
RegisterScreensaverEntityWatcher(leftScreensaverEntity.ScreensaverEntity); RegisterScreensaverEntityWatcher(leftScreensaverEntity.ScreensaverEntity);
let val = getState(leftScreensaverEntity.ScreensaverEntity).val; let val = getState(leftScreensaverEntity.ScreensaverEntity).val;
let iconColor = rgb_dec565(White); let iconColor = rgb_dec565(White);
let icon; let icon;
if (typeof leftScreensaverEntity.ScreensaverEntityIconOn == 'string' && existsObject(leftScreensaverEntity.ScreensaverEntityIconOn as string)) { if (typeof leftScreensaverEntity.ScreensaverEntityIconOn == 'string' && existsObject(leftScreensaverEntity.ScreensaverEntityIconOn as string)) {
let iconName = getState(leftScreensaverEntity.ScreensaverEntityIconOn!).val; let iconName = getState(leftScreensaverEntity.ScreensaverEntityIconOn!).val;
icon = Icons.GetIcon(iconName); icon = Icons.GetIcon(iconName);
} else { } else {
icon = Icons.GetIcon(leftScreensaverEntity.ScreensaverEntityIconOn); icon = Icons.GetIcon(leftScreensaverEntity.ScreensaverEntityIconOn);
} }
if (parseFloat(val + '') == val) { if (parseFloat(val + '') == val) {
val = parseFloat(val); val = parseFloat(val);
} }
if (typeof val == 'number') { if (typeof val == 'number') {
val = val * (leftScreensaverEntity.ScreensaverEntityFactor ? leftScreensaverEntity.ScreensaverEntityFactor! : 0) val = val * (leftScreensaverEntity.ScreensaverEntityFactor ? leftScreensaverEntity.ScreensaverEntityFactor! : 0)
icon = determineScreensaverStatusIcon(leftScreensaverEntity,val,icon) icon = determineScreensaverStatusIcon(leftScreensaverEntity, val, icon)
val = val.toFixed(
leftScreensaverEntity.ScreensaverEntityDecimalPlaces
) + leftScreensaverEntity.ScreensaverEntityUnitText;
iconColor = GetScreenSaverEntityColor(leftScreensaverEntity);
} else if (typeof val == 'boolean') {
iconColor = GetScreenSaverEntityColor(leftScreensaverEntity);
if (!val && leftScreensaverEntity.ScreensaverEntityIconOff != null) {
icon = Icons.GetIcon(leftScreensaverEntity.ScreensaverEntityIconOff);
}
} else if (typeof val == 'string') {
iconColor = GetScreenSaverEntityColor(leftScreensaverEntity);
let pformat = parseFormat(val);
if (Debug) log('moments.js --> Datum ' + val + ' valid?: ' + moment(val, pformat, true).isValid(), 'info');
if (moment(val, pformat, true).isValid()) {
let DatumZeit = moment(val, pformat).unix(); // Umwandlung in Unix Time-Stamp
if (leftScreensaverEntity.ScreensaverEntityDateFormat !== undefined) {
val = new Date(DatumZeit * 1000).toLocaleString(getState(NSPanel_Path + 'Config.locale').val, leftScreensaverEntity.ScreensaverEntityDateFormat);
} else {
val = new Date(DatumZeit * 1000).toLocaleString(getState(NSPanel_Path + 'Config.locale').val);
}
}
}
const temp = leftScreensaverEntity.ScreensaverEntityIconColor;
if (temp && typeof temp == 'string' && existsObject(temp)) {
iconColor = getState(temp).val;
}
payloadString += '~' + '~' + icon + '~' + iconColor + '~' + leftScreensaverEntity.ScreensaverEntityText + '~' + val + '~'; // Einheit ermitteln: String oder aus DP
} let unitText = '';
} if (typeof leftScreensaverEntity.ScreensaverEntityUnitText === 'string') {
if (existsObject(leftScreensaverEntity.ScreensaverEntityUnitText)) {
unitText = getState(leftScreensaverEntity.ScreensaverEntityUnitText).val;
} else {
unitText = leftScreensaverEntity.ScreensaverEntityUnitText;
}
}
if (i < 3) { val = val.toFixed(leftScreensaverEntity.ScreensaverEntityDecimalPlaces) + unitText;
checkpoint = false; iconColor = GetScreenSaverEntityColor(leftScreensaverEntity);
} } else if (typeof val == 'boolean') {
iconColor = GetScreenSaverEntityColor(leftScreensaverEntity);
if (!val && leftScreensaverEntity.ScreensaverEntityIconOff != null) {
icon = Icons.GetIcon(leftScreensaverEntity.ScreensaverEntityIconOff);
}
} else if (typeof val == 'string') {
iconColor = GetScreenSaverEntityColor(leftScreensaverEntity);
let pformat = parseFormat(val);
if (Debug) log('moments.js --> Datum ' + val + ' valid?: ' + moment(val, pformat, true).isValid(), 'info');
if (moment(val, pformat, true).isValid()) {
let DatumZeit = moment(val, pformat).unix(); // Umwandlung in Unix Time-Stamp
if (leftScreensaverEntity.ScreensaverEntityDateFormat !== undefined) {
val = new Date(DatumZeit * 1000).toLocaleString(getState(NSPanel_Path + 'Config.locale').val, leftScreensaverEntity.ScreensaverEntityDateFormat);
} else {
val = new Date(DatumZeit * 1000).toLocaleString(getState(NSPanel_Path + 'Config.locale').val);
}
}
}
const temp = leftScreensaverEntity.ScreensaverEntityIconColor;
if (temp && typeof temp == 'string' && existsObject(temp)) {
iconColor = getState(temp).val;
}
if (checkpoint == false) { payloadString += '~' + '~' + icon + '~' + iconColor + '~' + leftScreensaverEntity.ScreensaverEntityText + '~' + val + '~';
for (let j = i; j < 3; j++) { }
payloadString += '~~~~~~'; }
}
} if (i < 3) {
} checkpoint = false;
}
if (checkpoint == false) {
for (let j = i; j < 3; j++) {
payloadString += '~~~~~~';
}
}
}
// 6 bottomScreensaverEntities // 6 bottomScreensaverEntities
let maxEntities: number = 7; let maxEntities: number = 7;
@@ -14947,6 +14968,7 @@ function isEventMethod (F: string | NSPanel.EventMethod): F is NSPanel.EventMeth
case 'sleepReached': case 'sleepReached':
case 'pageOpenDetail': case 'pageOpenDetail':
case 'buttonPress2': case 'buttonPress2':
case 'buttonPress3':
case 'renderCurrentPage': case 'renderCurrentPage':
case 'button1': case 'button1':
case 'button2': case 'button2':
@@ -15011,7 +15033,7 @@ function isPagePower (F: NSPanel.PageType | NSPanel.PagePower): F is NSPanel.Pag
namespace NSPanel { namespace NSPanel {
export type PopupType = 'popupFan' | 'popupInSel' | 'popupLight' | 'popupNotify' | 'popupShutter' | 'popupShutter2' | 'popupSlider' | 'popupThermo' | 'popupTimer' | 'popupColor'; export type PopupType = 'popupFan' | 'popupInSel' | 'popupLight' | 'popupNotify' | 'popupShutter' | 'popupShutter2' | 'popupSlider' | 'popupThermo' | 'popupTimer' | 'popupColor';
export type EventMethod = 'startup' | 'sleepReached' | 'pageOpenDetail' | 'buttonPress2' | 'renderCurrentPage' | 'button1' | 'button2'; export type EventMethod = 'startup' | 'sleepReached' | 'pageOpenDetail' | 'buttonPress2' | 'buttonPress3' | 'renderCurrentPage' | 'button1' | 'button2';
export type panelRecvType = { export type panelRecvType = {
event: 'event'; event: 'event';
method: EventMethod; method: EventMethod;