• 10 dec 2017: forum version update. In case of issues use this topic.
  • 30 nov 2017: pilight moved servers. In case of issues use this topic.
Hello There, Guest! Login Register


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Start command/script on pulse receive
#1
Hi,

I've been looking through the forum and wiki, but I can't find a way to let pilight start a command when it receives a pulse from an elro remote, for example. Is this possible yet?
 
Reply
#2
Alter one of these to your liking: https://github.com/pilight/pilight/tree/master/clients
 
Reply
#3
@curlymo:

i'm using a python daemon for the receiver that i think i improved a little bit:

Code:
#!/usr/bin/env python

from signal import *
import sys
import os
import socket
import time
from time import sleep
import json
import logging
import daemon
from datetime import datetime, timedelta
from subprocess import Popen, PIPE

wallRemoteId = XXXXXXX

def bash_command(cmd):
    Popen(['/bin/bash', '-c', cmd])

def clean(*args):
    s.close()
    logger.info('Stopped daemon')
    sys.exit(0)
    
for sig in (SIGABRT, SIGILL, SIGINT, SIGSEGV, SIGTERM):
    signal(sig, clean)

# create logger
logger = logging.getLogger('rfcontrol.py')
logger.setLevel(logging.DEBUG)

# create filehandler
fh = logging.FileHandler('/var/log/rfcontrol.log')
fh.setLevel(logging.DEBUG)

# create streamhandler
sh = logging.StreamHandler()
sh.setLevel(logging.ERROR)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%d.%m.%Y %H:%M:%S')

# add formatter to fh
fh.setFormatter(formatter)
sh.setFormatter(formatter)

# add fh to logger
logger.addHandler(fh)
logger.addHandler(sh)

while True:
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(('127.0.0.1', 5000))
        s.settimeout(1)
        s.send('{"message":"client receiver"}\n')
        logger.info('Started daemon')
        if s.recv(1024) == '{"message":"accept client"}\n':
            logger.info('Connected to pilight')
            starttime = datetime.now()
            oldstate = 'none'
            while True:
                try:
                    buffer = s.recv(1024);
                except socket.timeout, ex:
                    err = ex.args[0]
                    if err == 'timed out':
                        sleep(1)
                        #logger.debug('Connection to pilight timed out, will retry later')
                        continue
                    else:
                        logger.error(ex)
                        break
                except socket.error, ex:
                    # Something else happened, handle error, exit, etc.
                    logger.error(ex)
                    break
                else:
                    if len(buffer) == 0:
                        logger.error('Connection orderly shutdown by pilight')
                        break
                    else:
                        for f in iter(buffer.splitlines()):
                            j = json.loads(f)
                            if ( j['code']['id'] == wallRemoteId and j['origin'] == 'receiver' and j['protocol'] == 'archtech_switches' ) :
                                acttime = datetime.now()
                                deltatime = acttime - starttime
                                actstate = j['code']['state']
                                if ( actstate != oldstate): #deltatime.total_seconds() > 3 or actstate != oldstate ):
                                    starttime = acttime
                                    deltatime = timedelta(0)
                                    ##DO WHATEVER YOU WANT TO DO HERE (I.E. bash_command("/home/pi/mybashscript.sh") )
                                    logger.info("Wall switch toggled")
                                oldstate = actstate
                                logger.debug('Wall switch %s: %s detected action %s after %s s',j['code']['id'],j['code']['state'],j['repeats'],deltatime.total_seconds())
    except Exception, ex:
        logger.error(ex)
        sleep(10)

but still i'm not sure if it wouldn't be good to implement a program in plight that is closer connected to the daemon (i had to catch a lot of exceptions and sometimes the connection somehow breaks and therefore it must be restarted, furthermore the way i solved id constantly keeps rechecking for new data).

a simple receiver program similar to the one in lirc would be great (where you can specify that i.e. the on key of switch 3145234 triggers a run of program a.

EDIT:
just checked out the development branch, here is my adapted script:

Code:
#!/usr/bin/env python

from signal import *
import sys
import os
import socket
import httplib
import StringIO
import struct
import re
import time
from time import sleep
import json
import logging
from datetime import datetime, timedelta
from subprocess import Popen, PIPE

wallRemoteId = XXXXXXX #switch number as shown in plight-receive

def discover(service, timeout=2, retries=1):
    group = ("239.255.255.250", 1900)
    message = "\r\n".join([
        'M-SEARCH * HTTP/1.1',
        'HOST: {0}:{1}'.format(*group),
        'MAN: "ssdp:discover"',
        'ST: {st}','MX: 3','',''])

    responses = {}
    i = 0;
    for _ in range(retries):
        i += 1
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, struct.pack('LL', 0, 10000));
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
        sock.sendto(message.format(st=service), group)
        while True:
            try:
                responses[i] = sock.recv(1024);
                break;
            except socket.timeout:
                                break;
            except:
                logger.error('No pilight SSPD connections found!')
                sleep(10)
                break;
    return responses.values()

def bash_command(cmd):
    Popen(['/bin/bash', '-c', cmd])

def clean(*args):
    s.close()
    logger.info('Stopped daemon')
    sys.exit(0)
    
for sig in (SIGABRT, SIGILL, SIGINT, SIGSEGV, SIGTERM):
    signal(sig, clean)

# create logger
logger = logging.getLogger('rfcontrol.py')
logger.setLevel(logging.DEBUG)

# create filehandler
fh = logging.FileHandler('/var/log/rfcontrol.log')
fh.setLevel(logging.DEBUG)

# create streamhandler
sh = logging.StreamHandler()
sh.setLevel(logging.ERROR)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%d.%m.%Y %H:%M:%S')

# add formatter to fh
fh.setFormatter(formatter)
sh.setFormatter(formatter)

# add fh to logger
logger.addHandler(fh)
logger.addHandler(sh)

responses = discover("urn:schemas-upnp-org:service:pilight:1");
if len(responses) > 0:
        locationsrc = re.search('Location:([0-9.]+):(.*)', str(responses[0]), re.IGNORECASE)
        if locationsrc:
                location = locationsrc.group(1)
                port = locationsrc.group(2)
                
                
while True:
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((location, int(port)))
        #socket.setdefaulttimeout(0)
        s.settimeout(1)
        s.send('{"message":"client receiver"}\n')
        logger.info('Started daemon')
        if s.recv(1024) == '{"message":"accept client"}\n':
            logger.info('Connected to pilight')
            starttime = datetime.now()
            oldstate = 'none'
            while True:
                try:
                    buffer = s.recv(1024);
                except socket.timeout, ex:
                    err = ex.args[0]
                    if err == 'timed out':
                        sleep(0)
                        #logger.debug('Connection to pilight timed out, will retry later')
                        continue
                    else:
                        logger.error(ex)
                        break
                except socket.error, ex:
                    # Something else happened, handle error, exit, etc.
                    logger.error(ex)
                    break
                else:
                    if len(buffer) == 0:
                        logger.error('Connection orderly shutdown by pilight')
                        break
                    else:
                        for f in iter(buffer.splitlines()):
                            j = json.loads(f)
                            if ( j['code']['id'] == wallRemoteId and j['origin'] == 'receiver' and j['protocol'] == 'archtech_switches' ) :
                                acttime = datetime.now()
                                deltatime = acttime - starttime
                                actstate = j['code']['state']
                                if ( actstate != oldstate): #deltatime.total_seconds() > 3 or actstate != oldstate ):
                                    starttime = acttime
                                    deltatime = timedelta(0)
                                    #PUT HERE YOUR CODE !! bash_command("/home/pi/myscript.sh")
                                    logger.info("Wall switch toggled")
                                oldstate = actstate
                                logger.debug('Wall switch %s: %s detected action %s after %s s',j['code']['id'],j['code']['state'],j['repeats'],deltatime.total_seconds())
    except Exception, ex:
        logger.error(ex)
        s.close()
        sleep(10)
 
Reply
#4
An event system is still in the planning, but first the daemon must work the way i want it.
 
Reply
#5
I have edit, with the help of www, the relay.c code. See line 106 108 112 114 .
After do a make install
Now i can start a bash script with the webgui with the relay protocoll.
It's simple but it works, but i am not a SW man.
Maybe some one will adjusting the code with a new name ?


Code:
/*
    Copyright (C) 2013 CurlyMo

    This file is part of pilight.

    pilight is free software: you can redistribute it and/or modify it under the
    terms of the GNU General Public License as published by the Free Software
    Foundation, either version 3 of the License, or (at your option) any later
    version.

    pilight is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with pilight. If not, see    <http://www.gnu.org/licenses/>
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#include "../../pilight.h"
#include "common.h"
#include "log.h"
#include "protocol.h"
#include "hardware.h"
#include "relay.h"
#include "gc.h"
#include "wiringPi.h"

void relayCreateMessage(int gpio, int state) {
    relay->message = json_mkobject();
    json_append_member(relay->message, "gpio", json_mknumber(gpio));
    if(state == 1)
        json_append_member(relay->message, "state", json_mkstring("on"));
    else
        json_append_member(relay->message, "state", json_mkstring("off"));
}

int relayCreateCode(JsonNode *code) {
    int gpio = -1;
    int state = -1;
    char *tmp;
    char *hw_mode;
    char *def = NULL;
#ifdef HARDWARE_433_GPIO
    int gpio_in = GPIO_IN_PIN;
    int gpio_out = GPIO_OUT_PIN;
#endif    
    int free_hw_mode = 0;
    int free_def = 0;
    int have_error = 0;

    relay->rawlen = 0;
    if(protocol_setting_get_string(relay, "default", &def) != 0) {
        def = malloc(4);
        free_def = 1;
        strcpy(def, "off");
    }
    
    if(json_find_string(code, "gpio", &tmp) == 0)
        gpio=atoi(tmp);
    if(json_find_string(code, "off", &tmp) == 0)
        state=0;
    else if(json_find_string(code, "on", &tmp) == 0)
        state=1;
    
    if(settings_find_string("hw-mode", &hw_mode) != 0) {
        hw_mode = malloc(strlen(HW_MODE)+1);
        strcpy(hw_mode, HW_MODE);
        free_hw_mode = 1;
    }

#ifdef HARDWARE_433_GPIO
    settings_find_number("gpio-receiver", &gpio_in);
    settings_find_number("gpio-sender", &gpio_out);
#endif
    
    if(gpio == -1 || state == -1) {
        logprintf(LOG_ERR, "relay: insufficient number of arguments");
        have_error = 1;
        goto clear;
    } else if(gpio > 20 || gpio < 0) {
        logprintf(LOG_ERR, "relay: invalid gpio range");
        have_error = 1;
        goto clear;
#ifdef HARDWARE_433_GPIO
    } else if(strstr(progname, "daemon") != 0 && strcmp(hw_mode, "gpio") == 0 && (gpio == gpio_in || gpio == gpio_out)) {
        logprintf(LOG_ERR, "relay: gpio's already in use");
        have_error = 1;
        goto clear;
#endif
    } else {
        if(strstr(progname, "daemon") != 0) {
            if(strcmp(hw_mode, "none") != 0) {
                if(wiringPiSetup() < 0) {
                    logprintf(LOG_ERR, "unable to setup wiringPi") ;
                    return EXIT_FAILURE;
                } else {
                    pinMode(gpio, OUTPUT);
                    if(strcmp(def, "off") == 0) {
                        if(state == 1) {
                            system("/home/pi/./buitenlampon.sh");
                        } else if(state == 0) {
                            system("/home/pi/./buitenlampoff.sh");  
                        }
                    } else {
                        if(state == 0) {
                            system("/home/pi/./buitenlampon.sh");
                        } else if(state == 1) {
                            system("/home/pi/./buitenlampoff.sh");                 }
                    }
                }
            }
            relayCreateMessage(gpio, state);
        }
        goto clear;
    }

clear:
    if(free_hw_mode) sfree((void *)&hw_mode);
    if(free_def) sfree((void *)&def);
    if(have_error) {
        return EXIT_FAILURE;
    } else {
        return EXIT_SUCCESS;
    }
}

void relayPrintHelp(void) {
    printf("\t -t --on\t\t\tturn the relay on\n");
    printf("\t -f --off\t\t\tturn the relay off\n");
    printf("\t -g --gpio=gpio\t\t\tthe gpio the relay is connected to\n");
}

void relayInit(void) {

    protocol_register(&relay);
    protocol_set_id(relay, "relay");
    protocol_device_add(relay, "relay", "Control connected relay's");
    relay->devtype = RELAY;

    options_add(&relay->options, 't', "on", no_value, config_state, NULL);
    options_add(&relay->options, 'f', "off", no_value, config_state, NULL);
    options_add(&relay->options, 'g', "gpio", has_value, config_id, "^([0-9]{1}|1[0-9]|20)$");

    protocol_setting_add_string(relay, "default", "off");
    protocol_setting_add_string(relay, "states", "on,off");
    protocol_setting_add_number(relay, "readonly", 0);
    
    relay->createCode=&relayCreateCode;
    relay->printHelp=&relayPrintHelp;
}

Ben
 
Reply
#6
Hi. I was looking for some eventing with pilight too but couldn't find any, so I whipped up my own. You're free to use it if you want:

https://github.com/abultman/PiAutomator

It's a simple processor that can take inputs, apply rules and then trigger some outputs. I'm running it locally at the moment to react to humidity in the bathroom, to run certain lights on a schedule and to detect outside light levels

OBTW. Should this be considered spam or something, feel free to delete.
 
Reply
#7
Rainbow 
Bultje76,

"I" don't think it's spam Wink but I like pilight Wink Maybe it's an idea to create a forum topic where people can post there usage and custom scripts. This way there can be discussion about idea's/requests and it's also a good way to see what people are interested in.

@CurlyMo, could that be an idea, cause I am lately following the complete forum and there are more and more people creating addon's , custom edits etc.

Bultje76, you write "supports adding pilight as both inputs and receivers", does that mean it reads all incoming signals that pilight receives ?
Maybe (if CurlyMo likes the idea) you can integrate your project into the pilight project git ?
 
Reply
#8
The new website will have a dedicated page with a list of all progs and apps. The new topic has been created as well.

Of course i like the idea of integration, but only if it's written in proper C code, is modular, and future proof. I also discussed in some topic my requirements for such event program. I'm going to work on it as soon as i finished pilight in it's core as i want it.
 
Reply
#9
Quote:Bultje76, you write "supports adding pilight as both inputs and receivers", does that mean it reads all incoming signals that pilight receives ?

It can, yes. Currently the only thing it reacts to from pilight for me locally is DHT22 sensor readings, but it should work just as well with other signals from, say, remote control events.

I have a receiver on order that I plan to use for exactly that. Any signals sent from remotes in the house will be received by pilight and then the signal will be passed along throught the API to PiAutomator. Based on rules configuration, it can then perform actions like: Turn light on, Send email, Some other crazy thing.
 
Reply
#10
Nice! Think alot of people appreciate your work!
 
Reply
  


Possibly Related Threads...
Thread Author Replies Views Last Post
  pilight-receive terminates zackdvd 8 1,651 12-30-2017, 09:07 PM
Last Post: curlymo
  pilight nightly does not start up, no log entries PT-Biker 4 1,661 06-09-2017, 06:34 AM
Last Post: PT-Biker
  pilight-daemon fails to start 2 of 3 times tietze111 4 1,734 12-11-2016, 09:06 PM
Last Post: tietze111
  Relation between raw-output and pulse length TheWheel 9 4,603 12-11-2016, 12:29 PM
Last Post: andies
  pilight-receive not recognizing kaku remote Michel 1 1,730 01-23-2016, 09:27 PM
Last Post: wo_rasp
  Running script one time. yabapolido 8 4,866 12-03-2015, 01:48 PM
Last Post: Prutsky
  pilight does not start tihe 6 5,285 11-14-2015, 12:49 PM
Last Post: tihe
  Error message when start of pilight failed. Landixus 8 7,206 07-25-2015, 06:53 PM
Last Post: curlymo
  pilight-receive tobid 9 3,805 05-26-2015, 04:44 PM
Last Post: pilino1234
  Execute python script from Generic Switch? panton 4 3,317 04-28-2015, 07:58 AM
Last Post: curlymo

Forum Jump:


Browsing: 1 Guest(s)