A State Triggered Action!

In a Create a Time Triggered Action we were able to schedule an Mqtt Message (the action) to be sent at a given time or interval. This example shows how to take an action based on an incoming message. I’ve highlighted my criteria in green and my action in red

When I receive a moisture low message AND it is after 6pm AND watering is off I want to start watering my plants.

Incoming Message (from sensor)

Incoming messages from my sensor have a topic of mysensors_out/92/0/1/0/37.  The payload contains the moisture level, anything above 100 is ok, anything below 100 is ‘dry’.

Outgoing Message (to sensor)

In order to turn on my pump I send a message to the mysensors_in/10/6/1/0/2 topic. The payload contains the number of minutes that the pump should be on.

So lets have a first go at implementing our logic. This won’t include ‘debounce’ and detecting whether watering is off. We’ll get this one working first and then look at implementing the other bits. We’ll use our standard after_mqttcogs_msg_in Action Hook.

add_action('after_mqttcogs_msg_in', 'moisture_msg_in', 10, 3);

function moisture_msg_in($utc, $topic, $payload)
{
	//this is not the sensor you are looking for, move along
	if ($topic != 'mysensors_out/92/0/1/0/37') {
		return;
	}

	//it is not dry, move along
	$payload = (int) $payload;
	if ($payload>=100) {
		return;
	}

	//it is not after 6pm, move along
	$dtm = new DateTime();
	$dtm->setTimezone(new DateTimeZone('Europe/London'));
	if ((int)$dtm->format('H'))<18) {
		return;
	};

	//it is after 6pm, it's dry so turn the water on!
	
	$outtopic = 'mysensors_in/10/6/1/0/2';
	$outpayload = 1;

	$mqttcogs = new MqttCogs_Plugin();
	$mqttcogs->sendMqtt('moisture_msg_in', $outtopic, $outpayload, 1, 0, '');
}

All pretty easy so far. We are left with one final criteria to check. We need to decide whether the watering is currently ‘on’ or ‘off’.

MqttCogs provides some neat function calls so that you can easily query the Mqtt data stored in the database. For this case, we’ll simply find the last mysensors_out/10/6/1/0/2 message from the device and look at it’s payload. A payload set to ‘0’ means that watering is ‘off’. A positive payload means watering is on.

//watering is currently active, move along
	$rows = $this->getLastN('data', 'mysensors_out/10/6/1/0/2', 1, 'DESC');
	//check there is a last record and if it's payload is not
	//zero then we are watering
	if ((count($rows)==1) && ($rows['payload'] > 0)) {
		return;
	}

So here is the final version. This includes a check for all the criteria at the top of the post and some simple error handling to email me when watering is on/buffered or we fail for some reason.

add_action('after_mqttcogs_msg_in', 'moisture_msg_in', 10, 3);
function moisture_msg_in($utc, $topic, $payload)
{
    $debug = false;
    
	//this is not the sensor you are looking for, move along
	if ($topic != 'mysensors_out/92/0/1/0/37') {
		return;
	}

	//it is not dry, move along
	$payload = (int) $payload;
	if ((!$debug) && ($payload>=100)) {
		return;
	}

	//it is not after 6pm local time, move along
	$dtm = new DateTime();
	$dtm->setTimezone(new DateTimeZone('Europe/London'));
	if ((!$debug) && ((int)$dtm->format('H'))<18) {
		return;
	};

    //watering is currently active, move along
	$rows = $this->getLastN('data', 'mysensors_out/10/6/1/0/2', 1, 'DESC');
	if ((count($rows)==1) && ($rows['payload'] > 0)) {
		return;
	}
    
	//it is after 6pm, it's dry and watering is off - so turn the water on!
	$outtopic = 'mysensors_in/10/6/1/0/2';
	$outpayload = 1;

	$mqttcogs = new MqttCogs_Plugin();
	$error = new stdClass();

	//note that this function returns
	// true (message ok or buffered) or 
	// false for error
	// I just use the $error object though...
	$mqttcogs->sendMqtt('moisture_msg_in', $outtopic, $outpayload, 1, 0, $error);
    
	switch($error->status) {
		case 'ok':
			wp_mail( 'test@test.com', 'Watering on (sent)', 'Moisture is: '.$outpayload ); 
		break;
		case 'buffered':
			wp_mail( 'test@test.com', 'Watering on (buffered)', 'Moisture is: '.$outpayload ); 
		break;
		case 'error':
			wp_mail( 'test@test.com', 'Watering FAIL', $error->errors[0].reason); 	
		break;
	}
}



No Comments


You can leave the first : )



Leave a Reply

Your email address will not be published. Required fields are marked *