LocalEventPoster - SmartApp Events to Local Syslog via HTTP

SmartThings Community-

Here’s a SmartApp to send syslog to a local PHP page via HTTP.
You will need a linux box running Apache + PHP on your local net to receive the data.

I was an Iris user until a few weeks back. I had all my Iris events flowing into AlienVault and then into ElasticSearch. I put the PHP page (code embedded in comments below) on my AV server and had rsyslog route as appropriate.

Enjoy!

RusFM

// ----------------------------------------------------------------------------
// LocalEventPoster
// ----------------------------------------------------------------------------
//
// Sends events to a local web server for processing.
// SSL is not supported unfortunately.
//
// An example receiver in PHP (SmartThingsReceiver.php) that dumps the posted data to syslog-
//
//    <?php
//    $data = '';
//    foreach( $_POST as $key => $value ) {
//        $data .= $key . '=' . $value . '| ';
//    }
//    $data = rtrim( $data, '| ' );
//    openlog( "SmartThings", 0, LOG_USER );
//    syslog( LOG_INFO, $data );
//    closelog();
//    ?>
//
// If you run this in AlienVault or any other app that redirects HTTP to HTTPS
// then you will need to create an exception to Apache's mod_rewrite rules so
// the request is not redirected to SSL/443.  It will look something like-
//    RewriteCond %{REQUEST_URI} !.*smartthingsreceiver.* [NC]
//
// Add something like this to your rsyslog config file so the events go into
// their own log file-
//    if $programname == 'SmartThings' then /var/log/smartthings.log
//    if $programname == 'SmartThings' then stop 


// ----------------------------------------------------------------------------
// definition
// ----------------------------------------------------------------------------

definition (
    name:        "LocalEventPoster",
    namespace:   "RusFM",
    author:      "RusFM",
    description: "Post SmartThings Events to a Local HTTP Listener",
    category:    "My Apps",
    iconUrl:     "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url:   "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    iconX3Url:   "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"
)


// ----------------------------------------------------------------------------
// preferences
// ----------------------------------------------------------------------------

preferences {
    
    // these two capabilities should cover all the devices
    // pity we have to use the ui to select them and cannot programmatically get them
    
    section("Log These Sensors:") {
        input "sensors", "capability.sensor", title: "Which sensors?", multiple: true, required: false
    }
    section("Log These Actuators:") {
        input "actuators", "capability.actuator", title: "Which actuators?", multiple: true, required: false
    }
    
}   // end preferences


// ----------------------------------------------------------------------------
// installed
// ----------------------------------------------------------------------------

def installed() {
    
    log.info( "${app.getName()}.installed: running" )
    
    initialize()
    
}   // end installed


// ----------------------------------------------------------------------------
// updated
// ----------------------------------------------------------------------------

def updated() {

    log.info( "${app.getName()}.updated: logging available sensors and actuators" )
    
    // sensors and actuators refer to the sections in preferences
    sensors.each { device ->
        device.capabilities.each { capability ->
            capability.getAttributes().each { attribute ->
                log.info( "${app.getName()}.updated: sensor,   name=${device.getLabel()}, capability=${capability.getName()}, attribute=${attribute.getName()}" )
            }
        }
    }
    actuators.each { device ->
        device.capabilities.each { capability ->
            capability.getAttributes().each { attribute ->
                log.info( "${app.getName()}.updated: actuator, name=${device.getLabel()}, capability=${capability.getName()}, attribute=${attribute.getName()}" )
            }
        }
    }
    
    unsubscribe()
    initialize()
    
}   // end updated


// ----------------------------------------------------------------------------
// initialize
// ----------------------------------------------------------------------------

def initialize() {

    log.info( "${app.getName()}.initialize: subscribing to available sensors and actuators" )
    
    // sensors and actuators refer to the sections in preferences
    sensors.each { device ->
        device.capabilities.each { capability ->
            capability.getAttributes().each { attribute ->
                log.info( "${app.getName()}.initialize: subscribing to sensor,   name=${device.getLabel()}, capability=${capability.getName()}, attribute=${attribute.getName()}" )
        		subscribe( device, attribute.getName(), genericHandler )
            }
        }
    }
    actuators.each { device ->
        device.capabilities.each { capability ->
            capability.getAttributes().each { attribute ->
                log.info( "${app.getName()}.initialize: subscribing to actuator, name=${device.getLabel()}, capability=${capability.getName()}, attribute=${attribute.getName()}" )
        		subscribe( device, attribute.getName(), genericHandler )
            }
        }
    }
    
}   // end initialize


// ----------------------------------------------------------------------------
// genericHandler
// ----------------------------------------------------------------------------

def genericHandler( event ) {

    // Local address of your web server, SSL is not supported (talk to Samsung)
    // Format is "IP:port"
    def server = "192.168.0.100:80"
    
    // The URL on the above server that will accept the POSTed data and do something with it
    def path = "/ossim/SmartThingsReceiver.php"

    // log.info( "${app.getName()}.genericHandler: ------------------------------" )
    // log.info( "${app.getName()}.genericHandler: ${event}" )

    def theBody = ""
    theBody += "date=${event.date}&"
    theBody += "isoDate=${event.isoDate}&"
    theBody += "name=${event.name}&"
    theBody += "displayName=${event.displayName}&"
    theBody += "device=${event.device}&"
    theBody += "deviceId=${event.deviceId}&"
    theBody += "value=${event.value}&"
    theBody += "unit=${event.unit}&"
    theBody += "isStateChange=${event.isStateChange()}&"
    theBody += "source=${event.source}&"
    theBody += "description=${event.description}&"
    theBody += "descriptionText=${event.descriptionText}"
    
    log.info( "${app.getName()}.genericHandler: theBody = ${theBody}" )
    
    def length = theBody.getBytes().size().toString()
    
    def hubAction = ( new physicalgraph.device.HubAction( [
        method: "POST",
        path: "${path}",
        headers: [
            "Content-Length":"${length}",
            HOST: "${server}",
            "Content-Type":"application/x-www-form-urlencoded",
            "Accept-Encoding":"gzip,deflate"
        ],
        body:theBody
    ] ) )
    
    // log.info( "${app.getName()}.genericHandler: hubAction = ${hubAction}" )
    
    try {
        sendHubCommand( hubAction );
    } catch( ex ) {
        log.error( "${app.getName()}.genericHandler: exception caught, ${ex}", ex )
    }
    
}   // end genericHandler