How to send text to sensor

Post Reply
gerardvs
Posts: 122
Joined: Sunday 04 January 2015 1:01
Target OS: Raspberry Pi
Domoticz version: latest-1
Location: /dev/null
Contact:

How to send text to sensor

Post by gerardvs » Wednesday 20 December 2017 21:39

Hi All,

Does anyone has some thoughts about the following?

I have a mysensors node with a LCD screen (Nokia 5110) which works fine but I want to display some text from Domoticz. Therefore I create some V_TEXT/S_INFO children (one for each lcd line). These work ok as long as the mysensors node pulls the data from Domoticz.

I've read only pulling is possible and that's what I have done so far, but pulling several lcd lines every few seconds is generating unwanted traffic.

Therefore the question; Is it possible to push the data from Domoticz to mysensors, or is there a better method to omit high frequency pulling data?

Thanks in advance,
--Gerard

gerardvs
Posts: 122
Joined: Sunday 04 January 2015 1:01
Target OS: Raspberry Pi
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: How to send text to sensor

Post by gerardvs » Sunday 24 December 2017 23:25

In case somebody is interested...

I solved it by adding and misusing an extra V_STATUS/S_BINARY device which is triggered from Domoticz by a small script and therefore the node "knows" it should request the TEXT data from Domoticz.

Not the most beautiful solution but it works for now. Hopefully in the near future Domoticz will send a message when a text device is updated.

Inso
Posts: 6
Joined: Thursday 12 October 2017 23:41
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: How to send text to sensor

Post by Inso » Friday 29 December 2017 1:15

Maybe I´m totally wrong (new to all of this^^), just an idea:
DZvents has a trigger for the device status. (https://www.domoticz.com/wiki/DzVents:_ ... ce_changes)
And you are able to send all kind of stuff to the devices using JSON (https://www.domoticz.com/wiki/Domoticz_ ... ext_sensor)
So maybe there´s a "clean" way to send your text message changes appropriate..

gerardvs
Posts: 122
Joined: Sunday 04 January 2015 1:01
Target OS: Raspberry Pi
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: How to send text to sensor

Post by gerardvs » Friday 29 December 2017 19:21

The problem is not updating the text value to or within Domoticz but sending the data to the (my)sensor.
It is a shortcoming of Domoticz. When the text value is updated Domoticz doesn't send the data to the mysensors gateway. However for a V_STATUS device Domoticz does send data to the gateway. That's why I use this device to inform the sensor so it can retrieve the text values from Domotics.

But, thanks for thinking with me ;)

blauwebuis
Posts: 349
Joined: Wednesday 21 December 2016 10:11
Target OS: Raspberry Pi
Domoticz version: current
Contact:

Re: How to send text to sensor

Post by blauwebuis » Monday 05 February 2018 14:07

How do you change the text data in Domoticz? I have a MySensors node that periodically checks domoticz for a password. But I don't know how to change that text value inside domoticz.

I tried creating a user variable and then setting that variable as the text via Blockly. But blockly says I can only read the value of a utility, and not set it :-(

User avatar
emme
Posts: 835
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: How to send text to sensor

Post by emme » Monday 05 February 2018 15:02

I'm well interested into the mysensor LCD and how you create it...

I'm willing to create an epaper display with the status of the system (a rolling text containing some information pulled or pushed from domoticz)
but so far I has no idea how to compute it...

Would you mind to share the sketch with few pics of your device?

ciao
M
That's one small step for a programmer, one giant leap for me!
- - - - -
rPI 3b+ zWave + rfxComm + nodeMcu + mySensors

gerardvs
Posts: 122
Joined: Sunday 04 January 2015 1:01
Target OS: Raspberry Pi
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: How to send text to sensor

Post by gerardvs » Sunday 11 February 2018 0:26

Buona sera,

Sure, I would happily share some info on how I did this. It can take a while to gather things readable together. I'm starting up after some weeks of illness so the code is as messy as me.....

What I did is on the Mysensors side:
- created some V_TEXT/S_INFO children (I use 3 lcd lines but you could use more or less)
- created 1 V_STATUS/S_BINARY child (This is used to trigger the ms node to request the V_TEXT data)
- Listen for message.type == V_STATUS and message.sensor is the correct one
- If message.getbool() == true then start requesting lcd sensors from domoticz like request(id,V_TEXT)
- Listen for lcd message.sensor id's and do a message.getString()
- If lcd updates are received, update the lcd
- After updating the lcd I send a message to domoticz to set the trigger switch to off

On Domoticz, with a small lua script update the text devices with the required text. I extract some temperature, humidity and other weather info and put it on the text devices. When some data is changed I set the (trigger) switch to on so that the Mysensors node is informed so that it can request the data.

Be aware that if you use the nrf24 the maximum message size is rather small (a bit less than 32 bytes) so you might use some more devices or use a buffer on the Mysensors node to shift in the data.

So hopefully you can do something with this info. Otherwise I can make in the future a simple proof of concept and present all the code here.

--Gerard

SHadley1138
Posts: 52
Joined: Thursday 10 March 2016 15:03
Target OS: Raspberry Pi
Domoticz version:
Contact:

Re: How to send text to sensor

Post by SHadley1138 » Sunday 11 February 2018 0:32

Would you mind sharing your code? Sounds like you have it nailed

gerardvs
Posts: 122
Joined: Sunday 04 January 2015 1:01
Target OS: Raspberry Pi
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: How to send text to sensor

Post by gerardvs » Sunday 18 February 2018 21:28

No time to optimize the code but here it is...

On the Arduino Nano the following code is running:

Code: Select all

/**
  File: LCDemo  A Mysensors demo project for interaction with Domoticz
  Hardware:   Arduino NANO
  Functions:  Show 3 lines on LCD (Nokia 5110) with text from Domoticz
              Control backlight of LCD by Domoticz switch
              PIR sensor on interrupt pin as motion sensor on Domoticz
              LDR sensor on analog port to show light level on Domoticz
              obsolete: change contrast of LCD with Domoticz slider (does work but not usefull)
              Uses Domoticz switch to trigger LCD updates (CHILD_ID_STAT)

  By: Gerard - 2017
*/


#define SKETCH_NAME        "LCDemo"
#define SKETCH_VERSION     "1.8.2"
#define MESSAGEWAIT 500


// Nokia 5110 LCD - 84 x 48 pixels
#include <LCD5110_Graph.h>
//LCD5110 myGLCD(7, 6, 5, 3, 4);
LCD5110 myGLCD(7, 6, 5, 18, 4);   // pin 3 has moved to 18(A5) because we need interrupt pin 3
extern uint8_t SmallFont[];       // 6x8 pixels  max 14 chars x 5 lines
extern unsigned char TinyFont[];  // 4x6 pixels  max 21 chars X   lines
String lcdLine[5];


#define PIR_PIN 3                   // PIR sensor
#define LIGHT_SENSOR_ANALOG_PIN A0  // LDR sensor
#define RELAY_PIN  8                // Actually not a relay anymore but the LCD backlight now
#define RELAY_ON   1                // GPIO value to write to turn on attached relay
#define RELAY_OFF  0                // GPIO value to write to turn off attached relay


#define MY_DEBUG
#define MY_RADIO_NRF24
#define MY_NODE_ID 10
//#define MY_REPEATER_FEATURE
#include <MySensors.h>

#define CHILD_ID_RELAY  0
#define CHILD_ID_LCD1   1   // LCD line 1
#define CHILD_ID_LCD2   2   // LCD line 2
#define CHILD_ID_LCD3   3   // LCD line 3
#define CHILD_ID_DIMMER 4
#define CHILD_ID_LDR    5
#define CHILD_ID_PIR    6
#define CHILD_ID_STAT   7   // test with v_status s_binary to trigger request lcd line info

MyMessage textMsg1(CHILD_ID_LCD1, V_TEXT);
MyMessage textMsg2(CHILD_ID_LCD2, V_TEXT);
MyMessage textMsg3(CHILD_ID_LCD3, V_TEXT);
MyMessage dimmerMsg(CHILD_ID_DIMMER, V_DIMMER);
MyMessage lightMsg(CHILD_ID_DIMMER, V_LIGHT);
MyMessage LdrMsg(CHILD_ID_LDR, V_LIGHT_LEVEL);
MyMessage PirMsg(CHILD_ID_PIR, V_TRIPPED);
MyMessage StatMsg(CHILD_ID_STAT, V_STATUS);


static const uint64_t UPDATE_INTERVAL = 60000;
unsigned long currentMillis = 0;
volatile unsigned long previousMillis = 0;
volatile bool pirEvent = true;

static int16_t currentLevel = 0;  // Current dim level...
bool lcdUpdate  = false;
bool lcdUpdate1 = false;
bool lcdUpdate2 = false;
bool lcdUpdate3 = false;

bool lastPir = false;
int LightLevel = 0;
int PreviousLightLevel = 0;
bool domoTrigger = false;
bool runOnce = true;



void before()
{
  pinMode(RELAY_PIN, OUTPUT);
  //digitalWrite(RELAY_PIN, loadState(sensor)?RELAY_ON:RELAY_OFF);
  digitalWrite(RELAY_PIN, RELAY_ON); // for now force backlight on
}

void setup()
{
  lcdLine[0][0] = 0;
  lcdLine[0] = SKETCH_NAME;
  lcdLine[0].concat(" ");
  lcdLine[0].concat(SKETCH_VERSION);
  lcdLine[1] = "--------------";
  lcdLine[2] = "--------------";
  lcdLine[3] = "--------------";
  lcdLine[4] = "..............";

  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);
  myGLCD.clrScr();
  myGLCD.print(lcdLine[0], CENTER, 0);
  myGLCD.update();
  myGLCD.setContrast(70);
  request(CHILD_ID_RELAY, V_STATUS);
  wait(MESSAGEWAIT);
  request(CHILD_ID_DIMMER, V_DIMMER );
  wait(MESSAGEWAIT);
  request(CHILD_ID_LCD1, V_TEXT);
  wait(MESSAGEWAIT);
  request(CHILD_ID_LCD2, V_TEXT);
  wait(MESSAGEWAIT);
  request(CHILD_ID_LCD3, V_TEXT);

  pinMode(PIR_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(PIR_PIN), pirChange, CHANGE);

  pinMode(LIGHT_SENSOR_ANALOG_PIN, INPUT_PULLUP);
  LightLevel = (1023 - analogRead(LIGHT_SENSOR_ANALOG_PIN)) / 10.23;
  PreviousLightLevel = 0;
}

void presentation()
{
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo(SKETCH_NAME, SKETCH_VERSION, true);
  Serial.print(F("NodeID: "));
  Serial.println(getNodeId());

  present(CHILD_ID_RELAY, S_BINARY, "RelayP8");
  wait(MESSAGEWAIT);
  present(CHILD_ID_LCD1, S_INFO, "LCD_line1", true);    // new S_type 20150905 (not known by domoticz)
  wait(MESSAGEWAIT);
  present(CHILD_ID_LCD2, S_INFO, "LCD_line2", true);
  wait(MESSAGEWAIT);
  present(CHILD_ID_LCD3, S_INFO, "LCD_line3", true);
  wait(MESSAGEWAIT);
  present(CHILD_ID_DIMMER, S_DIMMER );
  wait(MESSAGEWAIT);
  present(CHILD_ID_LDR, S_LIGHT_LEVEL, "LDR");
  wait(MESSAGEWAIT);
  present(CHILD_ID_PIR, S_MOTION, "PIR");
  wait(MESSAGEWAIT);
  present(CHILD_ID_STAT, S_BINARY, "LCD_Trigger");
}


void loop()
{
  if (runOnce) {
    send(textMsg1.setSensor(CHILD_ID_LCD1).set("lcd1 waiting"));  // initialize the V_TEXT at controller for sensor to none (trick for Domoticz)
    wait(MESSAGEWAIT);
    send(textMsg2.setSensor(CHILD_ID_LCD2).set("lcd2 waiting"));
    wait(MESSAGEWAIT);
    send(textMsg3.setSensor(CHILD_ID_LCD3).set("lcd3 waiting"));
    runOnce = false;
  }

  if (lcdUpdate1 && lcdUpdate2 && lcdUpdate3) {  // check if all 3 lcd lines are received before update entire display
    lcdUpdate = true;
  }
  
  unsigned long currentMillis = millis();
  if ((currentMillis - previousMillis >= UPDATE_INTERVAL) || pirEvent || domoTrigger || lcdUpdate) {
    previousMillis = currentMillis;

    // Handle PIR sensor
    if (pirEvent) {
      bool pirTripped = digitalRead(PIR_PIN) == HIGH; // reading twice has not much use. To be optimised...
      Serial.print("PIR:"); Serial.println(pirTripped);
      myGLCD.invert(pirTripped);
      send(PirMsg.setSensor(CHILD_ID_PIR).set(pirTripped ? "1" : "0"));
      pirEvent = false;
    }

    // Handle LCD triggers
    if (domoTrigger) {            // evidently received a trigger from Domoticz so send requests until all lines are received
      if (lcdUpdate1 == false) {
        request(CHILD_ID_LCD1, V_TEXT);
        wait(MESSAGEWAIT);
      }
      if (lcdUpdate2 == false) {
        request(CHILD_ID_LCD2, V_TEXT);
        wait(MESSAGEWAIT);
      }
      if (lcdUpdate3 == false) {
        request(CHILD_ID_LCD3, V_TEXT);
        wait(MESSAGEWAIT);
      }
      if (lcdUpdate1 && lcdUpdate2 && lcdUpdate3) {
        domoTrigger = false;
        send(StatMsg.setSensor(CHILD_ID_STAT).set("0"));  // reset trigger switch on Domoticz
      }
    }

    // Handle LDR sensor data
    LightLevel = (1023 - analogRead(LIGHT_SENSOR_ANALOG_PIN)) / 10.23;
    Serial.print("Lux:"); Serial.println(LightLevel);

    if (LightLevel != PreviousLightLevel) {
      send(LdrMsg.setSensor(CHILD_ID_LDR).set(LightLevel));
      lcdLine[4] = "Lux: ";
      lcdLine[4].concat(LightLevel);
      lcdUpdate = true;
      PreviousLightLevel = LightLevel;
    }

    // Update the LCD if required
    if (lcdUpdate ) {
      myGLCD.clrScr();
      myGLCD.print(lcdLine[0], LEFT, 0);
      myGLCD.print(lcdLine[1], LEFT, 10);
      myGLCD.print(lcdLine[2], LEFT, 20);
      myGLCD.print(lcdLine[3], LEFT, 30);
      myGLCD.print(lcdLine[4], LEFT, 40);
      myGLCD.update();
      lcdUpdate = false;
      lcdUpdate1 = false; lcdUpdate2 = false; lcdUpdate3 = false;
    }
  }
}


//
// PIR interrupt routine
//
void pirChange()
{
  pirEvent = true;
  previousMillis = 0;
}


//
// Callback routine for receiving messages 
//
void receive(const MyMessage & message)
{
#ifdef MY_DEBUG
  Serial.print("RX:"); Serial.print(message.sensor); Serial.print(", Message: "); Serial.println(message.getString());
#endif
  // check incoming LCD line text
  switch (message.sensor) {
    case 1:
      lcdLine[1] = message.getString();
      lcdUpdate1 = true;
      break;
    case 2:
      lcdLine[2] = message.getString();
      lcdUpdate2 = true;
      break;
    case 3:
      lcdLine[3] = message.getString();
      lcdUpdate3 = true;
      break;
    default:
      //lcdLine[4] = message.getString();
      break;
  }
  
  // Check for Trigger
  if ((message.type == V_STATUS) and (message.sensor == CHILD_ID_STAT)) {
    // force lcd line get from domoticz update
    if (message.getBool() == true) {
      domoTrigger = true;
      Serial.println("lcd update from Domoticz");
    }
  }


  // Backlight on or off
  if ((message.type == V_STATUS) and (message.sensor == CHILD_ID_RELAY)) {
    // Change relay state
    digitalWrite(RELAY_PIN, message.getBool() ? RELAY_ON : RELAY_OFF);
    // Store state in eeprom
    //saveState(message.sensor, message.getBool());
    // Write some debug info
    Serial.print("Incoming change for sensor:");
    Serial.print(message.sensor);
    Serial.print(", New status: ");
    Serial.println(message.getBool());
  }

  // Obsolete code and to be removed.  Was used to control LCD contrast.
  if (message.type == V_LIGHT || message.type == V_DIMMER) {
    //  Retrieve the power or dim level from the incoming request message
    int requestedLevel = atoi( message.data ) ;

    // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
    requestedLevel *= ( message.type == V_LIGHT ? 80 : 1 );

    // Clip incoming level to valid range of 0 to 100 (50-80)
    requestedLevel = requestedLevel > 80 ? 80 : requestedLevel;
    requestedLevel = requestedLevel < 0   ? 50   : requestedLevel;

    Serial.print( "Changing level to " );
    Serial.print( requestedLevel );
    Serial.print( ", from " );
    Serial.println( currentLevel );

    //fadeToLevel( requestedLevel );
    //myGLCD.setContrast(requestedLevel);

    // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
    send(lightMsg.set(currentLevel > 0));

    // hek comment: Is this really nessesary?
    send( dimmerMsg.set(currentLevel) );
  }

}
On Domoticz this code creates the following devices:
Image

Within Domoticz the following event is running (no dzVents yet, someone has to rewrite this part)

Code: Select all

commandArray = {}

local m = os.date('%M')

if (m % 5 == 0) then
	print("The 5 minute script interval reached")
    s = otherdevices_lastupdate['LCD_Trigger']

    year = string.sub(s, 1, 4)
    month = string.sub(s, 6, 7)
    day = string.sub(s, 9, 10)
    hour = string.sub(s, 12, 13)
    minutes = string.sub(s, 15, 16)
    seconds = string.sub(s, 18, 19)
    t1 = os.time()
    t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
    difference = (os.difftime (t1, t2))

    sTemp, sHumidity = otherdevices_svalues['msTempHum']:match("([^;]+);([^;]+)")
    sSchuurTemp, sSchuurHumidity = otherdevices_svalues['Buienradar - Barometer']:match("([^;]+);([^;]+)")
    regen = math.floor(tonumber(otherdevices_svalues['Rain2Come - Rain2Come']))

    ttlcd1 = otherdevices_idx['LCD_line1']
    ttlcd2 = otherdevices_idx['LCD_line2']
    ttlcd3 = otherdevices_idx['LCD_line3']
    ttTrig = otherdevices_idx['LCD_Trigger']

    commandArray[1] = { ['UpdateDevice'] = ttlcd1..'|0|'..'Regen: '..regen }
    commandArray[2] = { ['UpdateDevice'] = ttlcd2..'|0|'..'T:'..sSchuurTemp..' H:'..sSchuurHumidity..'%'}
    commandArray[3] = { ['UpdateDevice'] = ttlcd3..'|0|'..'T:'..sTemp..' H:'..sHumidity..'%' }
    if (difference > 120) then
        commandArray[4] = { ['LCD_Trigger'] = "On" }
    end
end

return commandArray
Just for illustration, the devices on the domo panel
Image


Hopefully this helps a bit.
--Gerard

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests