[SOLVED] Actions

Hey, I’m quite new to OH development and I’m trying to create an action for my binding (similar to the publishMQTT from MQQT).
I implemented the following:

@ThingActionsScope(name = "mybinding")
@NonNullByDefault
public class MyAction implements ThingActions {

    private @Nullable MyHandler handler;

    @RuleAction(label = "@text/actionLabel", description = "@text/actionDesc")
    public void sendMessage(
            @ActionInput(name = "text", label = "@text/actionLabel", description = "@text/actionDesc") @Nullable String text) {
        System.out.println("successful");
    }

    @Override
    public void setThingHandler(@Nullable ThingHandler handler) {
        this.handler = (MyHandler) handler;

    }

    @Override
    public @Nullable ThingHandler getThingHandler() {
        return handler;
    }
}

And my rule:

rule "Test rule"
when
    Item TestSwitch received command
then
   val actions = getActions("mybinding","mybinding:sub:98655a49")
    if(null === actions) {
            logInfo("actions", "Actions not found, check thing ID")
            return
     }
     logInfo("actions", " " + actions)
     actions.sendMessage("TestTest")
end

Actually, the last logInfo returns me the correct type org.openhab.binding.telegram.bot.MyAction@aa871b8, but calling the “sendMessage” returns Rule 'Test rule': 'sendMessage' is not a member of 'org.eclipse.smarthome.core.thing.binding.ThingActions'; line 13, column 6, length 40

This is very strange, it first recognizes the correct type and then it tries to find a method on the super type. What am I doing wrong here?

Your service is registered in the thing handler via Collection<Class> getServices() is it?

Thanks for having a look at this! Yes it’s implemented:

    @Override
    public Collection<Class<? extends ThingHandlerService>> getServices() {
        return Collections.singleton(MyAction.class);
    }

And in the debugger I can also see that it is called.

To use it in a DSL rule you need to add a static method:

    public static void sendMessage(@Nullable ThingActions actions, @Nullable String text) {
        if (actions instanceof MyAction) {
            ((MyAction) actions).sendMessage(text);
        } else {
            throw new IllegalArgumentException("Instance is not an MyAction class.");
        }
    }

https://github.com/openhab/openhab2-addons/blob/master/addons/binding/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/action/MQTTActions.java#L79

Yup. Like in the MQTT binding as reference.

Cheers, David

Thanks, that worked immediately!

I looked at the MQQT example already however I didn’t care much about this static method as it had no special annotations and thought this is some kind of additional method not related to the ESH/OH framework.

I also read https://github.com/eclipse/smarthome/blob/master/bundles/automation/org.eclipse.smarthome.automation.module.core/README.md but this static method wasn’t mentioned there either or is there any other documentation?

But thanks again for your help!

The possibility to use new rule actions in old DSL rules was added hastily just before the OH 2.4 release.
Documentation was of least concern at that point. But now that the documentation is slowly migrated back to openHAB from Eclipse Smarthome, a paragraph should be added. We should maybe comment the method in MQTT as well.

1 Like

I’m trying to us the publishMQTT action and am receiving the following error message:

2020-07-13 13:44:43.066 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Send MQTT Topic': An error occurred during the script execution: index=2, size=2

Based on this thread, I tried copying and inserting the static method, which yields the following warning on the static method line:

2020-07-13 13:57:57.130 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'mqtt.rules' has errors, therefore ignoring it: [20,36]: no viable alternative at input '@'

[20,66]: mismatched input ',' expecting 'end'

Here is the rule (with the copied static method)

rule "Send MQTT Topic"

when Item MQTTActionTrigger received command ON
then
    public static void publishMQTT(@Nullable ThingActions actions, @Nullable String topic, @Nullable String value)
 
    val actions = getActions("mqtt","mqtt:topic:2190008f")
    actions.publishMQTT("cmnd/tasmotas/power")
    actions.publishMQTT("cmnd/tasmotas/power2")
    actions.publishMQTT("cmnd/tasmotas/power3")
end

I have read through various threads and search the forum, but have been unable to figure out the problem.
I am running OpenHABian 2.5.6 on a Pi 4

Did you try your Rule without this line ?

public static void publishMQTT(@Nullable ThingActions actions, @Nullable String topic, @Nullable String value)

I don’t see such a notation in a rule before. But if possible, I think it has to be declared at the top of the Rule-File (outside the rule)

Thanks for sharing your suggestion.

I tried moving the declaration to the top of the .rules file:

public static void publishMQTT(@Nullable ThingActions actions, @Nullable String topic, @Nullable String value)

rule "Send MQTT Topic"

when Item MQTTActionTrigger received command ON
then
 
    val actions = getActions("mqtt","mqtt:topic:2190008f")
    actions.publishMQTT("cmnd/tasmotas/power")
    actions.publishMQTT("cmnd/tasmotas/power2")
    actions.publishMQTT("cmnd/tasmotas/power3")
end

Still an error, but a different one:

2020-07-16 17:24:22.868 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'mqtt.rules' is either empty or cannot be parsed correctly!


I have tried without the declaration, which gives this error:

2020-07-16 17:36:02.978 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Send MQTT Topic': An error occurred during the script execution: index=2, size=2

As a workaround, I created 3 string channels in the Generic MQTT Thing and put the topics in their command fields and created a switch that then triggered sends a blank command. It works, but the publishMQTT method would be much more elegant.

rule "Send MQTT String"

when Item MQTTStringTrigger received command ON
then 
    GenericMQTTThing_TextValueToTriggerAllTasmotats.sendCommand("")
    GenericMQTTThing_Power2ToAllTasmotas.sendCommand("")
    GenericMQTTThing_Power3ToAllTasmotas.sendCommand("")
end 

This thread is about coding bindings.
This is not the same as DSL rules at all.

Just get rid of the public static thing, you only need getActions()

but you do need to give getActions() your broker Thing UID, not a topic.
You supply the topic in publishMQTT()
I really don’t know if payload is optional, either. Trying giving one even if it is empty string.

actions.publishMQTT("cmnd/tasmotas/power", "")
1 Like

Thanks for the suggestions.

Sorry for posting this in the wrong thread. I’m new to OpenHAB and still learning the proper etiquette. In researching my problem I came across this thread that included the publishMQTT method, so I posted without looking at the tags. Is it better to begin a new thread than to append to one that is tangentially related?

At any rate, thanks for your help. The key was that, as you said, I needed to use the broker UID and not the MQTTGeneric Thing UID. Once I changed that, it worked (w/o the declaration).

I also tested whether the empty payload is required and found that it is.

Here is the code that worked:

rule "Send MQTT Topic"

when Item MQTTActionTrigger received command ON
then
 
    val actions = getActions("mqtt","mqtt:broker:7db8ea46")
    actions.publishMQTT("cmnd/tasmotas/power","") 
    actions.publishMQTT("cmnd/tasmotas/power2","")
    actions.publishMQTT("cmnd/tasmotas/power3","")
end

And the log showing that it worked!

2020-07-17 18:57:33.447 [DEBUG] [nhab.binding.mqtt.action.MQTTActions] - MQTT publish to cmnd/tasmotas/power performed

2020-07-17 18:57:33.451 [DEBUG] [nhab.binding.mqtt.action.MQTTActions] - MQTT publish to cmnd/tasmotas/power2 performed

2020-07-17 18:57:33.451 [DEBUG] [nhab.binding.mqtt.action.MQTTActions] - MQTT publish to cmnd/tasmotas/power3 performed


.

1 Like