The approach to differentiate the message did not work for my purpose:
- commands sent from Fhem are a set message
- requests return as set message
- Status message of the node (set message) returns as set message with Ack
I.e. all are set messages (no differentiation possible)
Because I use a counter to limit the resending of the status message from the node I used this counter to get to the destination.
In short: If the reception was successful the counter goes to 0, the request to <0 and the send to >0.
Here is my sketch, it is for switching several time controlled relays, for clarity I have removed the debug messages:
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2018 Sensnology AB
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*******************************
*
* DESCRIPTION
* The RS485 Gateway prints data received from sensors on the serial link.
* The gateway accepts input on seral which will be sent out on
* the RS485 link.
*
* Wire connections (OPTIONAL):
* - Inclusion button should be connected between digital pin 3 and GND
* - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
*
* LEDs (OPTIONAL):
* - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received
* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
* - ERR (red) - fast blink on error during transmission error or receive crc error
*
* If your Arduino board has additional serial ports
* you can use to connect the RS485 module.
* Otherwise, the gateway uses AltSoftSerial to handle two serial
* links on one Arduino. Use the following pins for RS485 link
*
* Board Transmit Receive PWM Unusable
* ----- -------- ------- ------------
* Teensy 3.0 & 3.1 21 20 22
* Teensy 2.0 9 10 (none)
* Teensy++ 2.0 25 4 26, 27
* Arduino Uno 9 8 10
* Arduino Leonardo 5 13 (none)
* Arduino Mega 46 48 44, 45
* Wiring-S 5 6 4
* Sanguino 13 14 12
*
*/
#define SN "MultiTimerRelay"
#define SV "1.0"
// Enable debug prints to serial monitor
#define MY_DEBUG
// Enable RS485 transport layer
#define MY_RS485
// Define this to enables DE-pin management on defined pin
//#define MY_RS485_DE_PIN 2
// Set RS485 baud rate to use
#define MY_RS485_BAUD_RATE 19200
// Enable this if RS485 is connected to a hardware serial port
#define MY_RS485_HWSERIAL Serial
#define MY_NODE_ID 2 // Id of the Node
#define MY_TRANSPORT_WAIT_READY_MS 30000 //loop is beginning at 3000ms whitout connection
#include <MySensors.h>
//++++++++ Relays +++++++++
#define RELAY_ON 1 // switch around for ACTIVE LOW / ACTIVE HIGH relay
#define RELAY_OFF 0
#define noRelays 3 // min 2
const int relayPin[] = {7, 8, 9}; // switch around pins to your desire
uint32_t relayTime[] = {0, 0, 0}; // on time for Relay to set from Fhem
volatile uint32_t startTime[] = {0, 0, 0}; // time to switch Relay on
int relayAckCountR[noRelays]; // ACK retry counter relay
int relayAckCountT[noRelays]; // ACK retry counter time
const uint32_t timeFactor = 1000UL; // to send minutes = 60000UL or seconds = 1000UL; UL says compiler is unsigned long!!!
class Relay // relay class, store all relevant data (equivalent to struct)
{
public:
int relayPin; // physical pin number of relay
boolean relayState; // relay status (also stored in EEPROM)
uint32_t relayTime; // on time for Relay
uint32_t startTime; // time to switch Relay on
int relayAckCountR; // ACK retry counter relay
int relayAckCountT; // ACK retry counter time
};
Relay Relays[noRelays];
MyMessage msgRelay[noRelays];
MyMessage msgTime[noRelays];
void before()
{
}
void presentation()
{
// Send the sketch version information to the gateway and Controller
sendSketchInfo(SN, SV);
//++++++++ Relays +++++++++
for (int i = 0; i < noRelays; i++)
{
present(i, S_DIMMER); // present sensor to gateway
wait(20);
}
}
void setup()
{
//++++++++ Relays +++++++++
for (int i = 0; i < noRelays; i++) {
Relays[i].relayPin = relayPin[i]; // assign physical pins
Relays[i].startTime = startTime[i]; // assign time to switch relay on
Relays[i].relayTime = relayTime[i]; // assign time for relay on
msgRelay[i].sensor = i; // initialize messages
msgRelay[i].type = V_STATUS;
msgTime[i].sensor = i;
msgTime[i].type = V_PERCENTAGE;
pinMode(Relays[i].relayPin, OUTPUT);
Relays[i].relayState = RELAY_OFF; // set all relaysState off
digitalWrite(Relays[i].relayPin, Relays[i].relayState ? RELAY_ON : RELAY_OFF); // write all relays off
//send(msgRelay[i].set(Relays[i].relayState ? true : false));
wait(20);
}
for (int i = 0; i < noRelays; i++)
{
request(i, V_STATUS); // Set relay to last known state
Relays[i].relayAckCountR = -1; // for the control of the request
wait(100);
request(i, V_PERCENTAGE); // Set relay to last known state
Relays[i].relayAckCountT = -1; // for the control of the request
wait(100);
}
}
void loop()
{
//++++++++ Relays +++++++++
uint32_t currentTime = millis();
//Zeitsteuerung der Relays
for (byte i = 0; i < noRelays; i++) {
if ( Relays[i].relayState == RELAY_ON && (currentTime - Relays[i].startTime > Relays[i].relayTime)) {
digitalWrite(Relays[i].relayPin, !Relays[i].relayState ? RELAY_ON : RELAY_OFF);
Relays[i].relayState = !Relays[i].relayState;
send(msgRelay[i].set(Relays[i].relayState ? true : false), true); // Send value to gw with ACK
Relays[i].relayTime = 0;
Relays[i].relayAckCountR = 3;
wait(100);
send(msgTime[i].set(Relays[i].relayTime), true); // Send value to gw with ACK
Relays[i].relayAckCountT = 3;
wait(100);
}
}
for (int i = 0; i < noRelays; i++) {
if (Relays[i].relayAckCountR < 0) {
wait(200);
request(i, V_STATUS); // Set relay to last known state
Relays[i].relayAckCountR = 0;
wait(100);
}
if (Relays[i].relayAckCountT < 0) {
wait(200);
request(i, V_PERCENTAGE); // Set relay to last known state
Relays[i].relayAckCountT = 0;
wait(100);
}
if (Relays[i].relayAckCountR > 0) {
wait(200);
send(msgRelay[i].set(Relays[i].relayState ? true : false), true); // Send value to gw with ACK
wait(100);
}
if (Relays[i].relayAckCountT > 0) {
wait(200);
send(msgTime[i].set(Relays[i].relayTime), true); // Send value to gw with ACK
wait(100);
}
}
}
void receive(const MyMessage &message) {
//++++++++ Relays +++++++++
if (message.type == V_STATUS && Relays[message.sensor].relayAckCountR <= 0) {
Relays[message.sensor].relayAckCountR = 0;
if (message.sensor < noRelays) { // check if message is valid for relays..... previous line [[[ if (message.sensor <=noRelays){ ]]]
Relays[message.sensor].relayState = message.getBool();
digitalWrite(Relays[message.sensor].relayPin, Relays[message.sensor].relayState ? RELAY_ON : RELAY_OFF); // and set relays accordingly
//saveState( message.sensor, Relays[message.sensor].relayState ); // save sensor state in EEPROM (location == sensor number)
}
if (Relays[message.sensor].relayState == RELAY_ON) {
Relays[message.sensor].startTime = millis();
}
}
else if (message.isAck() && message.type == V_STATUS && Relays[message.sensor].relayAckCountR > 0) {
Relays[message.sensor].relayAckCountR = 0;
}
else if (!message.isAck() && message.type == V_STATUS && Relays[message.sensor].relayAckCountR > 0) {
Relays[message.sensor].relayAckCountR--;
}
else if (message.type == V_PERCENTAGE && Relays[message.sensor].relayAckCountT <= 0) {
if (message.sensor < noRelays) { // check if message is valid for relays..... previous line [[[ if (message.sensor <=noRelays){ ]]]
Relays[message.sensor].relayTime = (message.getByte() * timeFactor); // calculate to millis
}
}
else if (message.isAck() && message.type == V_PERCENTAGE && Relays[message.sensor].relayAckCountT > 0) {
Relays[message.sensor].relayAckCountT = 0;
}
else if (!message.isAck() && message.type == V_PERCENTAGE && Relays[message.sensor].relayAckCountT > 0) {
Relays[message.sensor].relayAckCountT --;
}
}