A second ON command doesn't work

Hi,

I want to control a motor (for a blind) with alexa. I have build an item, a thing, a python script, a sitemap and the following rules (big thanks to rlkoshak and Josar):

rule "Motor 1"
when
    // FENSTER means window
	Item FENSTER changed
then
	logInfo("Jalousie", "FENSTER changed -> FENSTER.state: " + FENSTER.state.toString + " MOTOR_STATE: " + MOTOR_STATE.state.toString)
	MOTOR_STATE.postUpdate(FENSTER.state.toString)
	MOTOR.sendCommand(FENSTER.state.toString)
end

rule "Motor 2"
when
	Item MOTOR_STATE changed
then
	logInfo("Jalousie", "MOTOR_STATE changed -> FENSTER.state: " + FENSTER.state.toString + " MOTOR_STATE: " + MOTOR_STATE.state.toString)
	MOTOR.postUpdate(MOTOR_STATE.state.toString)
	MOTOR.sendCommand(MOTOR_STATE.state.toString)
end

That works as expected.

BUT: The blind can manually changed from open to closed and reverse. So, when I send a command ON and state is ON, it should start the script again.
But it didn’t. So I changed the rules to …

rule "Motor ON"
when
	Item FENSTER received command ON
then
	logInfo("Jalousie", "FENSTER changed -> FENSTER.state: " + FENSTER.state.toString + " MOTOR_STATE: " + MOTOR_STATE.state.toString)
	logInfo("Jalousie", "FENSTER received command: " + receivedCommand.toString)
	MOTOR_STATE.postUpdate(FENSTER.state.toString)
	MOTOR.sendCommand(ON)
end

rule "Motor OFF"
when
	Item FENSTER received command OFF
then
	logInfo("Jalousie", "FENSTER changed -> FENSTER.state: " + FENSTER.state.toString + " MOTOR_STATE: " + MOTOR_STATE.state.toString)
	logInfo("Jalousie", "FENSTER received command: " + receivedCommand.toString)
	MOTOR_STATE.postUpdate(FENSTER.state.toString)
	MOTOR.sendCommand(OFF)
end

rule "Motor State"
when
	Item MOTOR_STATE changed
then
	logInfo("Jalousie", "MOTOR_STATE changed -> FENSTER.state: " + FENSTER.state.toString + " MOTOR_STATE: " + MOTOR_STATE.state.toString)
	MOTOR.postUpdate(MOTOR_STATE.state.toString)
	MOTOR.sendCommand(MOTOR_STATE.state.toString)
end

The events.log shows:
2018-03-28 20:34:04.603 [ome.event.ItemCommandEvent] - Item ‘MOTOR’ received command OFF
2018-03-28 20:34:04.612 [vent.ItemStateChangedEvent] - MOTOR_STATE changed from to OFF
2018-03-28 20:34:04.653 [ome.event.ItemCommandEvent] - Item ‘MOTOR’ received command OFF
2018-03-28 20:34:04.659 [vent.ItemStateChangedEvent] - MOTOR changed from to OFF
2018-03-28 20:34:12.974 [ome.event.ItemCommandEvent] - Item ‘FENSTER’ received command ON
2018-03-28 20:34:13.002 [vent.ItemStateChangedEvent] - FENSTER changed from OFF to ON
2018-03-28 20:34:13.062 [vent.ItemStateChangedEvent] - MOTOR_STATE changed from OFF to ON
2018-03-28 20:34:13.065 [ome.event.ItemCommandEvent] - Item ‘MOTOR’ received command ON
2018-03-28 20:34:13.111 [vent.ItemStateChangedEvent] - MOTOR changed from OFF to ON
2018-03-28 20:34:13.116 [ome.event.ItemCommandEvent] - Item ‘MOTOR’ received command ON
2018-03-28 20:34:22.047 [ome.event.ItemCommandEvent] - Item ‘FENSTER’ received command ON
2018-03-28 20:34:22.113 [ome.event.ItemCommandEvent] - Item ‘MOTOR’ received command ON
2018-03-28 20:34:27.690 [vent.ItemStateChangedEvent] - MOTOR changed from ON to
2018-03-28 20:34:27.696 [vent.ItemStateChangedEvent] - MOTOR_STATE changed from ON to
2018-03-28 20:34:27.721 [ome.event.ItemCommandEvent] - Item ‘MOTOR’ received command

The openhab.logs shows

//rule “Motor OFF”
2018-03-28 20:34:04.590 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER received command: OFF

//rule “Motor Stater§”
2018-03-28 20:34:04.638 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: OFF MOTOR_STATE: OFF

//rule “Motor OFF”
2018-03-28 20:34:13.017 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER changed -> FENSTER.state: ON MOTOR_STATE: OFF
2018-03-28 20:34:13.028 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER received command: ON

//rule “MOtor State”
2018-03-28 20:34:13.093 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: ON MOTOR_STATE: ON

//rule “Motor ON”
2018-03-28 20:34:22.073 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER changed -> FENSTER.state: ON MOTOR_STATE: ON
2018-03-28 20:34:22.094 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER received command: ON

//rule “Motor State”
2018-03-28 20:34:27.709 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: ON MOTOR_STATE:

As you can see, the motor receices a second ON, but nothing happens. I believe, because the motor.state doesn’t change. I tried something like

when
	Item MOTOR_STATE received command ON/OFF

but that doesn’t works too.

Any help?

Greetings Kaloschke

Did you mean

when
	Item MOTOR_STATE received command

Please also use code fences for the logs!
Post your full setup!

One thing which no one expects is that the item state will not be change when the rule gets triggered from received command. Thats said, you have to use the implicit variable triggeringItem to get the state.

when
    Item FENSTER received command 
then
    logInfo("Jalousie","FENSTER status:" + triggeringItem.state)
end

I think you use the exec binding for the script, why don’t you reset the motor state after skript execution is done? I don’t think what you want is to have the script running multiple times in paralle?

So if you post you setup, and explain what is your goal we might find neat and tidy solution.

Good point. Rules that trigger from a command but then examine the same Items state usually go wrong. You must NOT assume a state change resulting from a command is instantaneous.

See also

Have you tried?

rule "Motor State"
when
	Item MOTOR_STATE received update
then
	logInfo("Jalousie", "MOTOR_STATE changed -> FENSTER.state: " + FENSTER.state.toString + " MOTOR_STATE: " + MOTOR_STATE.state.toString)
	MOTOR.postUpdate(MOTOR_STATE.state.toString)
	MOTOR.sendCommand(MOTOR_STATE.state.toString)
end

Cannot sent my reply. Get always Bad Gateway 502

OK, I have documented my project, but I cannot post it her. Perhaps it’s to long.
So here is a short version. I returned to my first version

rule "Motor 1"
when
	Item FENSTER received command
then
	logInfo("Jalousie", "FENSTER status: " + triggeringItem.state)
	MOTOR_STATE.postUpdate(FENSTER.state.toString)
	MOTOR.sendCommand(FENSTER.state.toString)
end

rule "Motor 2"
when
	Item MOTOR_STATE changed
then
	logInfo("Jalousie", "MOTOR_STATE changed -> FENSTER.state: " + FENSTER.state.toString + " MOTOR_STATE: " + MOTOR_STATE.state.toString)
	MOTOR.postUpdate(MOTOR_STATE.state.toString)
	MOTOR.sendCommand(MOTOR_STATE.state.toString)
end

and it works!
But: I habe to wait to perform for the second same command longer than 10 seconds.
Here is the openhab.log

2018-03-29 17:28:48.998 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: OFF MOTOR_STATE: OFF
2018-03-29 17:28:58.051 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER status: ON
2018-03-29 17:28:58.116 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: ON MOTOR_STATE: ON
2018-03-29 17:28:59.801 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: ON MOTOR_STATE: 
2018-03-29 17:29:05.847 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER status: ON
2018-03-29 17:29:05.897 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: ON MOTOR_STATE: ON
2018-03-29 17:29:12.930 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER status: ON
2018-03-29 17:29:20.730 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER status: ON
2018-03-29 17:29:38.372 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER status: ON
2018-03-29 17:29:59.893 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: ON MOTOR_STATE: 
2018-03-29 17:30:07.928 [INFO ] [ipse.smarthome.model.script.Jalousie] - FENSTER status: ON
2018-03-29 17:30:07.977 [INFO ] [ipse.smarthome.model.script.Jalousie] - MOTOR_STATE changed -> FENSTER.state: ON MOTOR_STATE: ON

As one can see, in the middle are commands, that are not processed.
Any ideas, why this happens?

My home.items

Switch FENSTER "Jalousie"  ["Switchable"] 
String MOTOR { channel="exec:command:motor_control:input", channel="exec:command:motor_status:output", autoupdate="false" }
String MOTOR_STATE "Jalousiestellung" { channel="exec:command:motor_status:output"}

my thing

Thing exec:command:motor_control [ command="/etc/openhab2/scripts/motoren.py %2$s", interval=0, autorun=true ]
Thing exec:command:motor_status [ command="/etc/openhab2/scripts/motoren.py status", interval=60, timeout=5 ]

my sitemap

sitemap home label="Fenster"
{
	Frame label="Jalousiesteuerung" {
		Switch  item=FENSTER mappings=[ON="Zu", OFF="Auf"]
	}
}

And the script to control the motor for the blind. I have no sensors for the endposition.
So I use a circuit, which stops the motor, when the current rises.

#!/usr/bin/env python
import RPi.GPIO as GPIO
import sys,time 
GPIO.setwarnings(False) 
GPIO.setmode(GPIO.BCM) 
if len(sys.argv) > 0:
    if sys.argv[1] == "OFF" or sys.argv[1] == "ON":
        MOTOR_GPIO = 2
        GPIO.setup(MOTOR_GPIO, GPIO.OUT)
        GPIO.output(MOTOR_GPIO, GPIO.HIGH)
        time.sleep(1.500)
        GPIO.output(MOTOR_GPIO, GPIO.LOW)
        if sys.argv[1] == "OFF":
            MOTOR_GPIO = 3
            GPIO.setup(MOTOR_GPIO, GPIO.OUT)
            GPIO.output(MOTOR_GPIO, GPIO.HIGH)
            time.sleep(2)
            GPIO.output(MOTOR_GPIO, GPIO.LOW)

So your script drives the shutter always fully up or down?
I asume not, thats why you wan’t to be able to press the button multiple times?
I dont see how status is handled in your script?

I would suggest something like this.

Assuming your circuit will stop down and up movement. Make a script which just set the direction or motor off.
Then you can stop the rollershutter at positions. Or just let it go to full open or close.

Remark: i change the names to highlight nicely in VSCode.

.things

Thing exec:command:motor_control [ command="/etc/openhab2/scripts/justWait.py %2$s", interval=0, autorun=false ]

.items

Rollershutter Fenster "Jalousie [%d %%]" <rollershutter> ["Switchable"] 
Switch Motor_runs { channel="exec:command:motor_control:run" }
String Motor "[%s]" { channel="exec:command:motor_control:input", channel="exec:command:motor_control:output", autoupdate="false" }

.rules

var Timer timerShutter = null  

rule "Motor 1"
when
    Item Fenster received command
then
    logInfo("Jalousie trigger", receivedCommand.toString )
    
    Motor.sendCommand(receivedCommand.toString)
    // This will ensure multiple times triggering of the script, 
    // when state changes to same state, which is not necessary anymore
    Motor_runs.sendCommand(ON)

    // Wait for the command to complete
    // Motor will not be stopped jet only the script execution
    while(Motor_runs.state != OFF){
       Thread::sleep(100)
    }
    logInfo("Jalousie Script result", Motor.state.toString )

    // Set Motor to STOP after some time.
    timerShutter = createTimer(now.plusSeconds(2)) [|
        Motor.sendCommand("STOP")
        Motor_runs.sendCommand(ON)
        timerShutter = null   // reset the timer
    ]
end

.py

#!/usr/bin/env python

import sys,time 

if len(sys.argv) > 0:

    # Set motor off
    if sys.argv[1] == "STOP" : 
        print sys.argv[1]
    # Set motor to drive down
    elif sys.argv[1] == "DOWN" : 
        print sys.argv[1]
    # Set motor to drive Up
    elif sys.argv[1] == "UP":
        print sys.argv[1]
    else: 
        print "Error!"
        print sys.argv[1]

That would be my solution for your setting. Assuming your circuit stops up and down driving riliably.

Sorry. I explained it in more detail in the version, I cound’t post.
I use a motor without contacts to get the position. Instead I use a circuit, which stops the motor when the current rise up in the end position. The command ON closes the blind by running the motor for 2 seconds in the wished direction. Because I can control the blind also manually, the script don’t know the status of the blind. So for the OFF command the motor first try to run in a defined position (closed) and runs then in the other for 3 seconds. I hope I could explain my situation.

The titel of my thread isn’t correct anymore, because I didn’t realize, that I had to wait a certain time until it works again. It’s not so important for my project, but it’s interesting for me, why I have to wait.

Anyway, big thanks to all who want to help me.
Kaloschke

See detailed solution above.

The problem with waiting is caused from the thing autorun=true.
The thing will only run the script when the state changes, so it does not matter if you trigger the rule Motor 1 as you don’t change the input channel. Only after the script finishes and set the input channel to " " Empty you can trigger the thing again.

Thak you for the explanation.
Is there a simple solution for that? Setting autorun=false?

I think the simple solution will not work.
As in your skript are multiple changes of the pin state and also sleeps.
When pressing the button the item is on and can not be set to on again untill the skript execution is finished.

So my suggested solution is shown above, i added a timer to stop the Motor.

I’m sorry. I was blind, but I haven’t seen your solution the days before.
Thank you very much for your extensive help.

Greetings Kaloschke

If you now how long it takes for a whole open or close you could also add the functionality to set the percentage value of the shutter.

For that you can use the stop timer. Assuming it takes 10s then you could post update to the rollershutter instead of the stop to the script. Just incrementing or decrementing the rollershutter. When you have 100 or 0 post stop to the script.
You would need one additional item or privousState to cancel the timer if you stop the shutter manually. This would be a fully working rollershutter.