NSPanel Lovelace UI Helpers (part 1/5, v0.8)

logo

This is part 1 of a 5-part collection of blockLibraries to use the NSPanel with the Lovelace UI. Check out the online documentation about how to use this library.

The required 5 libraries are:

All installed libraries need to have the same version number!

Blocks

For some description of the individual blocks of this library have a look in the online documentation.

Changelog

Version 0.8

  • fixed various selector issues
  • finally got shutter returnValue right
  • added page reload helper

Version 0.7

  • added option to hide the unit in cardThermo
  • fix for missing timerName, triggered error on direct call of some cards

Version 0.6

  • enhancement: changed returnValue uppercase for cardShutter to be compatible with openHAB shutter item
  • cleanup: moved fullpage Notification to Cards
  • bugfix: context Usage for next Statement was broken in ‘ForceContextForScript’
  • enhancement: modified context handling to prevent usage on non-Card statements (stuck on screensaver)
  • enhancement: added helpers to modify all callback settings on-the-fly

Version 0.5

  • fix for broken refresh timers (since 0.4)
  • improved context usage of ‘start with forced context’-helper

Version 0.4

  • improved multi-hardware-panel usage (not backwards compatible)
  • added feature to start on same page after leaving screensaver
  • added refresh on hardware button press
  • start screensaver if no startup action is given on callback
  • various bugfixes

Version 0.3

  • improved popupPage handling
  • returnValue of Entitiy Selector modification
  • added support for OpenWeatherMap Icons

Version 0.2

  • added documentation
  • initial release

Version 0.1

  • pre-release

Resources

nspanel_helpers.yaml

3 Likes

Wow, that is great. Thank you for sharing your work! Now i really want to buy a NSPanel to try it :smiley:

Love it, I own a nspanel for some time, but I was always unhappy with the stock HMI or nxpanel. Lovelace-ui looked worthy to give it a try, but not without an easy to use OH integration. Lucky me here it is.
I would like to request integration of OpenWeatherMap condition Ids in to the icon mapping.
something like this:

   - component: UtilityFunction
      config:
        code: >-
          function {{name}}(code) {
            
            // see https://github.com/sevesalm/eInk-weather-display/blob/master/weather_icon_codes.md
            let mapping = {
              "1":"fullscreen", "2":"weather-partly-cloudy", "21":"weather-partly-rainy", "22":"weather-rainy",
              "23":"weather-pouring", "3":"weather-cloudy", "31":"weather-partly-rainy", "32":"weather-rainy",
              "33":"weather-pouring", "41":"weather-partly-snowy-rainy", "42":"weather-snowy-rainy", "43":"weather-snowy-rainy",
              "51":"weather-partly-snowy", "52":"weather-snowy", "53":"weather-snowy-heavy", "61":"weather-windy", "62":"weather-windy",
              "63":"weather-tornado", "64":"weather-hurricane", "71":"weather-partly-snowy-rainy", "72":"weather-partly-snowy-rainy",
              "73":"weather-hail", "81":"weather-partly-snowy-rainy", "82":"weather-partly-snowy-rainy", "83":"weather-hail",
              "91":"weather-fog", "92":"weather-fog"
              };
            // see https://openweathermap.org/weather-conditions
            let owm_mapping = {
              "200":"weather-lightning-rainy",
              "201":"weather-lightning-rainy",
              "202":"weather-lightning-rainy",
              "210":"weather-lightning",
              "211":"weather-lightning",
              "212":"weather-lightning",
              "221":"weather-lightning-rainy",
              "230":"weather-lightning-rainy",
              "231":"weather-lightning-rainy",
              "232":"weather-lightning-rainy",
              "300":"weather-hail",
              "301":"weather-hail",
              "302":"weather-hail",
              "310":"weather-hail",
              "311":"weather-hail",
              "312":"weather-hail",
              "313":"weather-hail",
              "314":"weather-hail",
              "321":"weather-hail",
              "500":"weather-rainy",
              "501":"weather-rainy",
              "502":"weather-rainy",
              "503":"weather-pouring",
              "504":"weather-pouring",
              "511":"snowflake-melt",
              "520":"weather-pouring",
              "521":"weather-pouring",
              "531":"weather-pouring",
              "600":"weather-snowy",
              "601":"weather-snowy",
              "602":"weather-snowy-heavy",
              "611":"weather-snowy",
              "612":"weather-snowy-heavy",
              "613":"weather-snowy-heavy",
              "615":"weather-snowy-rainy",
              "616":"weather-snowy-rainy",
              "620":"weather-snowy-heavy",
              "621":"weather-snowy-heavy",
              "622":"weather-snowy-heavy",
              "701":"weather-fog",
              "711":"smoke",
              "721":"weather-hazy",
              "731":"weather-tornado",
              "741":"weather-fog",
              "751":"weather-tornado",
              "761":"weather-tornado",
              "762":"smog",
              "771":"weather-tornado",
              "781":"weather-tornado",
              "800":"weather-sunny",
              "801":"weather-partly-cloudy",
              "802":"weather-cloudy",
              "803":"weather-cloudy",
              "804":"cloud"              
            };
              
            let owm_short_mapping = {
              "01d":"weather-sunny",
              "01n":"weather-night",
              "02d":"weather-partly-cloudy",
              "02n":"weather-night-partly-cloudy",
              "03d":"weather-cloudy",
              "03n":"weather-cloudy",
              "04d":"cloud",
              "04n":"cloud",
              "09d":"weather-pouring",
              "09n":"weather-pouring",
              "10d":"weather-rainy",
              "10n":"weather-rainy",
              "11d":"weather-lightning",
              "11n":"weather-lightning",
              "13d":"weather-snowy",
              "13n":"weather-snowy",
              "50d":"weather-fog",
              "50n":"weather-fog",
            };
            
            if(/^\d\d[nd]+$/.test(code)){
                return(owm_short_mapping[parseInt(code)])
            } else if (/^\d\d\d$/.test(code)) {
                return(owm_mapping[parseInt(code)])
            } else return(owm_mapping[parseInt(code)])
          }
        name: absorb_it_nspanel_convertWeatherCodeToIcon

Hi ,

Thanks for sharing this. I tried to setup in my openhab 3.0 version. I m getting this error in the rules.

2023-12-19 01:13:46.104 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '682865ad07' failed: <eval>:1:58 Expected , but found =
function absorb_it_nspanel_timeUpdate(target, patternTime = 'HH:mm', patternDate = 'dd-MM-yyyy') {
                                                          ^ in <eval> at line number 1 at column number 58

Do I need any particular version of JS ?

Thanks!

Hi,

interesting, I had to check this. I am using this on openHAB 4 for all my work. openHAB 3 uses ECMAScript 5.1, which does not support default values of functions yet. I will get rid of those default values during the next days to get rid of this specific problem. There are some further changes required (let vs. var for variable declarations and maybe more), I will keep you updated about the status of these changes here.

Thanks for the feedback, regards, Rene

Hi Rene,

I have it working - just starting to play with it. Great work!

Mike

Thanks for the reply.
Adding following line fixed the issue

application/javascript;version=ECMAScript-2021

This looks promising. I m using node-red to manage nspanel but it is not flexible. Also, lately I m trying to move away from node-red and focus only on openhab rules and use node-red for complex rules.

Will keep you posted if i find any issue.

Thanks !

Hi Amin,

I found in another post that you can define the javascript engine which is used for rules. But can you really work with blockly and create scripts using the newer javascript engine in openHAB 3?

Best regards, Rene

Hi Rayn,

great idea and thanks for the implementation as well. Added this for the next release, expected today+Xd.

Thanks again and best regards, Rene

Hi Rene,

I was able to update the time on the screen but it looks like not everything is working. I see rule engine crashing in the logs and I need to restart entire system.

Looking at the changes to update the JS version, I m actually migrating to OH4 right now. I have few days off and was thingking to update it and now I got another excuse to update to newer verison :slight_smile:

Will keep you posted how it goes. Hope it is not going to break entire system. My last update was OK so I m expecting this one more stable :slight_smile:

Hi,

just updated the library to version 0.3.

One major issue was the refresh handling of popup Pages. If you modify some setting (like a switch or a selector) on some popup page, you like to have this page refreshed to indicate this change on the display as well. This worked for normal pages with version 0.2, but was broken with popup Pages. Should now be fixed.

The handling of the returnValue of some selector Pages (like entity Selector, Fan or Thermo popup) was really difficult. Blockly uses list indices starting from 1, javascript from 0. Cleaned up this mess but broke backwards compatibility for those selector returnValues. You are now getting some index ranging from 1 to max of options and you even get the selected option itself via returnMode variable.

Added, as suggested and implemented by Rayn, a conversion for OpenWeatermap Weather icons.

… and a lot of minor :slight_smile: fixes …

Enjoy and keep me updated for suggestion and issues. Regards, Rene

1 Like

No. I don’t think that’s feasible. The Blockly implementation was basically rewritten so the blocks render to JS Scripting using the helper library.

But you can make Nashorn JS work with the newer JS engine. So you could implement this in the older JS and using the info on the link above create code that will work in both.

Hi,

not sure that I got this right: By installing Nashorn JS I will add the old JS environment. So far so good - I still have Nashorn JS on my system installed.

But how should I be able to write a blockLibrary with the old JS implementation? If I have two possible environments where do I select which JS version is used by the blockLibrary? (sorry, I’m really new into hacking openHAB)

Regards, Rene

Nashorn style JS will run on the newer GraalVM JS Scripting with a little bit of work. So you can write code that will run on either engine.

At a high level:

// Get the JSR223 runtime assigned to runtime so we don't blow away the
// GraalVM JS helper library
var runtime = (typeof(require) === "function") ? require('@runtime') : this;

// At this point all code must be Nashorn style working with the raw OH JSR223 APIs
// see https://www.openhab.org/docs/configuration/jsr223.html

// for example, commanding an Item
runtime.events.sendCommand("NameOfItem", "Command");

// instead of
// items.NameOfItem.sendCommand("Command");

You don’t. On OH 3 it will be Nashorn JS. On OH 4 it will be GraalVM JS. All you can do is make sure the code your Blocks render to can run on either engine unchanged without breaking the code that the standard blocks produce.

Alternatively you can create and maintain two versions, one for OH 3 and one for OH 4, or choose not to support OH 3 at all.

The problem is the code that the standard Blockly blocks render to will only run on Nashorn or GraalVM JS, not both. And you cannot choose which version of JS is used. On OH 3, Nashorn JS is the only JS that Blockly supports. On OH 4 GraalVM JS is the only JS tghat Blockly supports.

Ok, thanks for the clarification. Makes it a little more complicated to maintain, lets see if I can find some suitable way.

Regards, Rene

Hi @rene_rostock , i m trying to set up first call back but panel is not showing the screensaver. I can only see dim and time out set out in logs. No screensaver info.

Do you have working example ?

This is my first callback and device is starting. Event sent by panel is startup.

Thanks

Maybe it is helpful to check out MQTT communication to trace the issue. This is how it looks like on my own device (mosquitto_sub -v -h squid -t “#” | grep C1D1FC):

tele/nxpanel_C1D1FC/RESULT {"CustomRecv":"event,startup,53,eu"}
cmnd/nxpanel_C1D1FC/CustomSend timeout~40
cmnd/nxpanel_C1D1FC/CustomSend dimmode~50~100
stat/nxpanel_C1D1FC/RESULT {"CustomSend":"Done"}
cmnd/nxpanel_C1D1FC/CustomSend pageType~cardQR
cmnd/nxpanel_C1D1FC/CustomSend entityUpd~WIFI QR~X~nspanel1_cardPower~~25388~~~X~nspanel1_cardThermo~~25388~~~WIFI:S:SSID;T:WPA;P:PASSWORD;;~x~~~~~~x~~~~~
stat/nxpanel_C1D1FC/RESULT {"CustomSend":"Done"}
stat/nxpanel_C1D1FC/RESULT {"CustomSend":"Done"}
stat/nxpanel_C1D1FC/RESULT {"CustomSend":"Done"}

So your callback seems to recognize the startup because it returns timeout and dimmode. The problem should lie in your startup Call Script “682865ad07”. Next step to debug would be to open the Script page of “682865ad07” and run this independently. It should send some Message to the panel, like “pageType~cardQR” in the example above and you should see the page you like to have.
Be aware that the initial call might be taken a really long time (up to a few seconds), dependent on your hardware. Any following call is way faster than.

Have a look into the Example Callback from Documentation.

Feel free to come back for further questions, best regards, Rene

Thanks for reply. Ok got it. But how to send screensaver pagetype? There is no such card.

I m trying to show screensaver page when it panel starts first time.

My assumption was using callback block will do this.

No, callback is the main unit required to handle all the MQTT messages and show pages, popup and the like.
If you directly like to display the screensaver Page, just tell the callback by sending “loadScreensaver” to your NSPanel Item. You can also do this as a Run Statement directly in your NSPanel Callback.


(not tested live, but this is how it should work)

I might change this to display the screensaver if no Startup action is given, just to indicate that something is working - thanks for pointing that out. Best regards, Rene

After some trials I decided not to support openHAB 3 for now. The major issue for now was the missing variable cache, which would require some different implementation and testing on this older platform. Just hope that people will move forward to openHAB 4.

Regards, Rene