My first Rule - light on and off every 10 seconds (can't make most basic rule work)

I am two months into openHAB and I can’t make the most basic rule work. Here is the rule I need help with, and at bottom of this post, I describe what I have done so far and my understanding and frustration.

// My first rule - SonOff switch in the gazebo
// On 5 seconds  off 5 seconds

rule  "SonOff_152_On"
   Time cron "0/10 0 0 ? * * *" 
   //Every 10 seconds starting at second 00, at minute :00, at 00am, of every day 

rule  "SonOff_152_Off"
   Time cron "5/10 0 0 ? * * *"
   //Every 10 seconds starting at second 05, at minute :00, at 00am, of every day
  1. openHABian on headless Rasberry, PuTTY, VS-IDE
  2. I have several SonOff switches hacked and working fine with simple url calls from my Firefox browser.
  3. Using HTTP binding, I have my SonOffs switches working properly ON/OFF from the Basic UI
  4. In this example, my Switch item = “SonOff_152”
  5. I used the Cron builder to generate time code
  6. I get this Log error is --> Configuration model ‘gazebo.rules’ is either empty or cannot be parsed correctly!
  7. I’m not sure what all the colors mean in the VS editor
    DISCUSION: I’m at a point where I’m in over my head. Reading the Rules documentation makes little sense because I don’t understand the terminology and don’t know how to ask questions.
    How are rules activated, by restarting the server?
    Do I need to “import” a Cron library? (similar to Arduino “include”… ??)
    Unfortunately I can not access the “Demo setup” rules because I installed the “Standard” . How do I view the setup demo (rule) examples from the Standard installation???
    Is there a single comprehensive programming reference manual (like Arduino) that lists ALL of the openHAB calls and functions (or whatever they are called, like “sendCommand”, “now.plusSeconds”, “contactNum”, “.calemdar.timeInMillis” , “java.util.Date” . “PointType” these are just some of the strange looking (dot) word things that I am not sure if they are like functions, commands, or whatever. and whether imports are needed to make some work, and whether some are built in or whether they are pure Java or openHAB extensions. I’ve programmed in Fortran, Basic, C++, and many other languages but not Java. Sooooo confused at this point… if there were just a reference manual with all the commands I could figure it out, like when I see a funny looking word in an example I could look it up. It appears that stuff is scattered all over the place and hard to separate the Java from OpenHAB. If I had straight forward reference manual with examples I could figure anything out.


I always get that error when loading rules, so I don’t think it is an issue. I believe it has something to do with spaces or tabs or something, but it doesn’t actually break rule functionality, at least for me.

As for your issue:

  • Use logInfo to log when you enter the rule. That way you can see if it fires, and see where the issue is.
logInfo("System","Rule 1 activated.")
  • Also check whether the log shows if OH sent an ON command to your Sonoff device. It should log any sendCommand calls by default.

Try going even simpler…

rule "My first rule"
   Time cron "0/10 0 0 ? * * *"
   //Every 10 seconds starting at second 00, at minute :00, at 00am, of every day 
    logInfo("Test","My first rule just ran")

Now tail the openhab.log and you should see the log entry every 10s. If that works, then add in your command with another logInfo after it, and see if the rule still runs.

OK, so maybe you don’t need to make the rule simpler, but just a valid rule file! If you have LSP enabled in VS Code, then it must be showing you some problems. Select View> Problems if they are not displaying.

Rule files (and others) are monitored by OH. When a change is detected, OH will reload the file. When you save a rule file, it is almost immediately active with the changes.

Nope. Quartz scheduler is available in the rules DSL.

There are many ways to do this, but try here.

If the manual, tutorial, and examples here and in the rest of the forum aren’t enough, read through the documentation for Xtend, which is mentioned here.

Hello @highvoltage,

The rules seems to be correct.
If you are accessing the rules-file via samba, then there is this error every time you Change the file and save it. It is because the saving process of samba, when openhab notice the Change, samba is not finished writing and therefore openhab can’t read the file. Normally this error is followed by two more logs that the rule file is loaded…

The next thing is your cron Expression is working every night at 0:00 am. That means starting at 0:00 am until 0:01 am your rule Triggers…

For testing purpose I would Change the cron Expression to “0/10 * * ? * * *” then it should be triggered every ten seconds…

For advanced use I would create only one rule for this switching:

rule "SonOff_152"
  Time cron "0/5 0 0 ? * * *"
  if (SonOff_152.state == ON) {


Change your cron expression to:

Time cron "0/10 * * ? * * *"


I’m an OpenHab user since 5 days ago and newly in to home automaton. I’m also looking to integrate all my sonoff wall switches in to OpenHab, currently they are still on the original eWelink firmware until I’m confident that I can flash them with Tamota or other firmware and integrate them in to my OpenHab sitemap, items and rules files.

So I’m following this topic with great interest and also kindly ask you if you can share some information on the firmware choice that you made for the sonoff’s and the next steps to get then controlled in OpenHab environment.

Thanx in advance for any help you or others can give me

I agree with Vincent. Your cron expression doesn’t do what you think it does. “0/10 0 0 ? * * *” means every ten seconds starting at second 0 on minute 00 on hour 00 any day, month, or year.

So the cron expression as written will only execute six times between 00:00 and 00:01.

I highly recommend using a cron expression builder if you are not familiar with the syntax.

I think you are missing the correct interpretation of the starting at. Starting at only applies when you have a / (e.g. 0/10 is every ten seconds starting at second 00). Since you don’t have a / for the minutes and hours you don’t have a starting at, you have a “Specific minute/hour”.

That is usually caused when you edit your files over a samba share or using certain text editors. So long as you see a Loading model gazebo.rules following that without other errors everything is fine.

As soon as you see that Loading model log statement the rule is active and will run.


You need to install the demo setup. I think you can do this by changing addons.cfg to use package=demo.

No. There is the Rules docs and Xtend Expressions docs.

Also, when you use VSCode with the openHAB extension you also get automatic completion. So you can type in the name of an object or variable and it will tell you all the methods on that object.

This dot word thing is standard OO syntax and applies across pretty much every OO language I can think of except maybe Objective Lisp. It even applies to C++ when referencing the functions or data members of a Class or Struct.

Imports are almost never needed. You only need imports if you want to use a class that is not in java.lang.* or core openHAB classes.

No, it has to do with the fact that when editing a file over samba two file events get generated when you save a file, one when you are about to save the file and one when saving the file is done. OH uses the file events to know when to reload the file so it gets the first event and tries to read in the file while it is being written resulting in a bad file read. Then it tries again on the second event and reads successfully.

I stand corrected.

My SonOff sketch below. Solder header to board and flash with Arduion IDE, see instructions here --> I used the green on-board LED to blink, showing that the loop is running and GPIO14 (available on the header, with outboard resistor and LED for testing only, then removed for production). I soldered short leads with header plug across the push button for connection to a standard wall light switch for manual operation (change of state triggers, not “on” and “off” as marked on wall switch)… You could attach your wall switch to GPIO14 after the programming cable is removed. Good luck.

  SonOff(TM) ESP8266 WiFi smart power switch "hack",
  (v2) Added "at device" over ride, (toggle) BUTTON.
  (v3) Fix relay ON after initialization
  (v4) Revised to act like a "3 way switch" (external switch soldered to button)
  (v5) Adds blinking (loop running) LED and adds GPIO14 (outboard optional) LED to mimic relay for testing
  Mar 16, 2018 (v5)
  Mar 13, 2018 (v4)
  Mar 1, 2018  (v3)
  Dec 21, 2016 (v2)
  By sparkgap  
  This Shetch is based on....
  Remote (Ham Radio) Antenna Switch by KE2ZT, Published in QST Sept 2016, pg42
  Relay and status LED are activated by addresssing URLs w/ browser as follows:     //Switch ON    //Switch OFF  // To poll switch status
  These IPs and ports must match your router configuration.
  To activate from the internet side of your router,
  replace the above IPs with the IP address of your router.
  If you do not have a
  dedicated IP address your IP may change after power loss.

  ------- programming cable ---------
  CAUTION - Disconnect A/C mains before attaching Ribbpn Cable
  Programming Header Pinout is as follows:
  X  GPIO14
  X  GND
  X  TX  (GPIO1)
  X  RX  (GPIO13)
  X  3.3V (pin closest to the Reset Button)
  ------- uploading ------
  IDE - Select Generic ESP8266 Module (load board from Git if not already done)
  IDE - Flash Mode = DOUT  (required for Sonoff v1.1)
  IDE - Flash Size = 1M/(64)
  Disable McAfee Real time Scan
  Hold reset button down, power-up, release reset, then upload.
  ------- GPIO use ---------
  Relay .......... GPIO12
  LED ............ GPIO13 (green onboard LED - blinks to show loop is running
  LED2............ GPIO14 (optional outboard LED - mimics relay for testing)
  Reset Button ... GPIO0
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiClient.h>

const char* ssid = "craftyglass";
const char* password = "hamradio";

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(8882);   // Assign a unique port number in your router <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// This is where we define the pins mapped to relay switches
#define LED 13 // GPIO13
#define LED2 14 // GPIO14
#define RELAY 12 // GPIO12
#define BUTTON 0 // GPIO0
// This is where relay action may be inverted.
#define LED_ON 0
#define LED_OFF 1
#define RELAY_SELECT 1
int pollVar;   // Status 1=on  2=off

long snapshot = millis();     // BUTTON setup
long settle_time = 200;       // BUTTON setup
int busy = false;             // BUTTON setup
int last_was_push = false;    // BUTTON setup
int action_counter = 1;       // BUTTON setup
int illuminated = false;      // LED blink
long timestamp = millis();     // LED blink

void setup() {

  // prepare GPIOs
  pinMode(LED, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(RELAY, OUTPUT);
  pinMode(BUTTON, INPUT);

  // deselect RELAY upon bootup
  digitalWrite(RELAY, RELAY_DESELECT);
  digitalWrite(LED2, 0);
  pollVar = 2;
  Serial.println("Relay is deselected");

  // Connect to WiFi network
  Serial.print("Connecting to ");

  WiFi.begin(ssid, password);
  IPAddress ip(192, 168, 1, 152);   // Assign a unique IP address in your router <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  IPAddress gateway(192, 168, 1, 1);
  IPAddress subnet(255, 255, 255, 0);
  WiFi.config(ip, gateway, subnet);

  while (WiFi.status() != WL_CONNECTED) {
  Serial.println("WiFi connected");

  // Start the server
  Serial.println("Server started");

  // Print the IP address
  Serial.println("The Receiver is now Connected..");
  Serial.print("Button quiescent state is  ");
  Serial.println( digitalRead (BUTTON));  // should be 1

void loop() {
  // Button Debouncing and Button Action
  // Connect wall light Switch across push button
  // Acts like what is called a "3 way Switch" (WiFI or Local)
  if (digitalRead (BUTTON) == 0 && last_was_push == false && busy == false)
    { last_was_push = true;
      busy = true;
      Serial.println("Transition to Push");
  if (digitalRead (BUTTON) == 1 && last_was_push == true && busy == false)
    { last_was_push = false;
      busy = true;
      Serial.println("Transition to Unpush");

  if ( millis() - snapshot > settle_time && busy == true )  // Timeout
    { if (pollVar == 2) 
          {  digitalWrite(RELAY, RELAY_SELECT);
             digitalWrite(LED2, 1) ;
             pollVar = 1;
          { if (pollVar == 1) 
             { digitalWrite(RELAY, RELAY_DESELECT);
               digitalWrite(LED2, 0) ;
               pollVar = 2;
          Serial.print("Action Count = ");
          action_counter = action_counter + 1;
          snapshot = millis();
          busy = false;

  // ***************************************************
  // Add LED BLINK
  // ***************************************************

  if ( millis() - timestamp > 500 && illuminated == false )
        { digitalWrite(LED, LED_ON);
          illuminated = true;
          timestamp = millis();
  if ( millis() - timestamp > 500 && illuminated == true )
        { digitalWrite(LED, LED_OFF);
          illuminated = false;
          timestamp = millis();

  // ****************************************************
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {

// Wait until the client sends some data
Serial.println("new client");
while (!client.available()) {

  // Read the first line of the request
  String req = client.readStringUntil('\r');

  // Match the request

  String val;
  String backColor = "<body bgcolor=\"#000000\" text=\"#FFFFFF\">\r\n";

  if (req.indexOf("/on ") != -1)  //ON test
    digitalWrite(RELAY, RELAY_SELECT);
    digitalWrite(LED2, 1);
    val = "<h1 style=\"color:red;\">Switch is ON</h1>";
    pollVar = 1;

  else if (req.indexOf("/off ") != -1)  //OFF test
    digitalWrite(RELAY, RELAY_DESELECT);
    digitalWrite(LED2, 0);
    val = "<h1 style=\"color:white;\">Switch is OFF</h1>";
    pollVar = 2;

  else if (req.indexOf("/poll ") != -1)   //poll test
    if (pollVar == 1) {
      val = "<h1 style=\"color:red;\"> Switch status is ON</h1>";
    if (pollVar == 2) {
      val = "<h1 style=\"color:white;\"> Switch status is OFF</h1>";

  else {
    Serial.println("invalid request");
    val = "<blink><h1 style=\"color:yellow;\">INVALID REQUEST!!</h1></blink>";

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n";
  s += backColor;
  s += "<h1><center>SOnOff (TM) <br>WiFi actuated Power Switch</h1><center> ";
  s += "<center>" + val + "</center>";
  s += "</body></html>\n";

  // Send the response to the client
  Serial.println("Client disonnected");

  // The client will actually be disconnected
  // when the function returns and 'client' object is detroyed

Is your problem from the first post solved?


Thanx Bill for your detailed reply. I will probably flash the wall dual sonoff switches using Tasmota ota mqtt. But did you have an example of the .items, .rules entries that I need to add in to my OH setup. If I can see some example I will expand on it for all my light switches. Being new in to OH and home automation it’s a step learning curve for me.

Thanx for any further example code for OH 2.


With your purpose “light on and off every 10 seconds”, your rule can be :

rule “SonOff_152”
Time cron “0/10 * * ? * * *”
if (SonOff_152.state == ON) {

YEs. Solved. I was not using/interpreting the Cron builder properly.
Also… thanks for your better code recommendation.