OH3: Cannot reference the field 'Const_Email_Admin' before it is defined

  • openHABian 3.4.1 on rPi4 with 4GB

I have a bunch of rules that send an email to me.
However, I want to make this more manageable, so that it can b changed in one location.

My idea was to create an string item Const_Email_Admin with the email address, and then use a global value on top of the respective rules, like so:

val String EMAIL_ADMIN = Const_Email_Admin.state.toString()

However, I get an error:

Cannot reference the field 'Const_Email_Admin' before it is defined

… and am a loss what this means, more so why it says that.

Any hints appreciated.

This seems to imply that this does not work as a matter of principle.

Is the solution then having to put it into the respective rules which send email?
Is that it?
Maybe I was too smart for myself :slight_smile:

This works:

            mailActions.sendMail
            (
                Const_Email_Admin.state.toString(),
                "Alert: " + DEVICE_NAME + " weirdly switched OFF",
                "This plug seemingly switched OFF while supposed to be always ON."
            )

In case one wonders why that weird message is there…
I have SmartPlugs which seem to occasionally switch themselves OFF. I have a switch item which forces a plug state. If this is ON, a change of the plug to OFF will check against the ‘forced’ state and corrects it. Seems to work so far (for ten months.)

not sure if i got you completely… so maybe you can post your complete rule?

but this should work…:

rule "Send Notification when Text changed"
when
    Item Notification received update
then
    if(!Notification.state.toString().isEmpty() && (now.getHour() >= 8 && now.getHour() <= 22) )
    {
        sendNotification(Receivers.state.toString(), Notification.state.toString())
    }
end

rule "SYSTEM_START_RULE"
when
	System started 
then
	postUpdate(Receivers, "foo@bar.com")
end

I may not have been clear enough?!

I was initially assigning an item state to a global constant.
That produced an error.

I then created a string item, which holds an email address.

This string item’s state was then used to as the first parameter for the mailAction.
This is the solution to the initial problem. The rule snippet shown works.

Not sure, how I could explain it better.

Hello,
I think that there is no item definition like this

String	Const_Email_Admin	"E-Mail address of the admin"

and if so you have fill the item with the initial E-Mail address, after that you can use it with your global constant. If you use an item you should persist it.

For my understanding it is easier to set the global value direct with

val String EMAIL_ADMIN = "admin@provider.xyz"

BR

Exactly what I want to avoid… having to update 30+ locations in rules when the email address changes. :slight_smile:

My solution works!

Use a string item (Const_Email_Admin) with the email address as payload, and use it like this (and stated before):

    mailActions.sendMail
    (
        Const_Email_Admin.state.toString(),
        "Alert: " + DEVICE_NAME + " weirdly switched OFF",
        "This plug seemingly switched OFF while supposed to be always ON."
    )

… and in case the email address needs to be changed, updated the string item (Const_Email_Admin) and be done with it.

Drat, I list my long reply. Here’s a shortened one.

Global variables only get populated when the. rules file is loaded. At this time:

  • Items are still being loaded so the Item may not yet exist
  • restoreOnStartup is still processing so if the Item exists it may not have a usable state
  • Changes in the Item’s state that happen after the .rules file is loaded won’t change the name of the global variable.

For all these reasons you should never use the state of an Item to populate a global variable in a .rules file.

In this case it just saves a few characters anyway. It doesn’t make your rules logically any simpler.

You have three choices:

  1. Just use the Item in your rules. That will pull the Item’s state on demand and will always return the latest state.

  2. Create a global lambda that returns the Item’s state on demand.

  3. Centralize your email code in a Rules DSL Script called using callScript or using /design-pattern-separation-of-behaviors (just rewritten for OH 4) and then your email address will only be used in one place anyway and this whole problem goes away. This has the added benefit that you can change to Telegram or add logic to send different ways based on the time of day and presence, for example.

Frankly, for something like this 2 is kind of asinine and I don’t recommend it. 1 and 3 though are good options.

In the other rules languages you have a fourth option to put the email variable into a personal library and import it into your roles instead of using an Item.

Thanks for the detailed reply.
As indicated in my O.P., I have chosen your choice #1, which works as expected and nicely.

My idea behind it all was to have single place where I can change an admin email address, that is available in all rules referencing it. :slight_smile: