Skip to content

Commit

Permalink
Add Jython Helper libraries
Browse files Browse the repository at this point in the history
This will should be merged after I have created a separate package for
the helper libraries, as discussed here...
openhab#7208 (comment).
For now, this was built to test using the helper libraries as a
separate bundle.

Signed-off-by: Scott Rushworth <openhab@5iver.com>
  • Loading branch information
Scott Rushworth committed Mar 25, 2020
1 parent 12b2190 commit 9468c87
Show file tree
Hide file tree
Showing 35 changed files with 4,021 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
* @openhab/2-x-add-ons-maintainers

# Add-on maintainers:
<<<<<<< Upstream, based on 12b2190d1e31b67e8f23c03e8b9cecd0f571f326
=======
/bundles/org.openhab.automation.helperlibraries.jython/ @openhab-5iver
>>>>>>> ed246af Add Jython Helper libraries
/bundles/org.openhab.binding.airquality/ @kubawolanin
/bundles/org.openhab.binding.airvisualnode/ @3cky
/bundles/org.openhab.binding.allplay/ @dominicdesu
Expand Down
5 changes: 5 additions & 0 deletions bom/openhab-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
<name>openHAB Add-ons :: BOM :: openHAB Add-ons</name>

<dependencies>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.automation.helperlibraries.jython</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.airquality</artifactId>
Expand Down
32 changes: 32 additions & 0 deletions bundles/org.openhab.automation.helperlibraries.jython/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
23 changes: 23 additions & 0 deletions bundles/org.openhab.automation.helperlibraries.jython/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.automation.helperlibraries.jython</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
13 changes: 13 additions & 0 deletions bundles/org.openhab.automation.helperlibraries.jython/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
This content is produced and maintained by the openHAB project.

* Project home: https://www.openhab.org

== Declared Project Licenses

This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.

== Source Code

https://github.com/openhab/openhab2-addons
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Jython Helper Libraries

This addon provides helper libraries for use with Jython and scripted automation.
3 changes: 3 additions & 0 deletions bundles/org.openhab.automation.helperlibraries.jython/bnd.bnd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Bundle-SymbolicName: ${project.artifactId}
DynamicImport-Package: *
-includeresource.resources: -src/main/resources
24 changes: 24 additions & 0 deletions bundles/org.openhab.automation.helperlibraries.jython/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>2.5.4-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.automation.helperlibraries.jython</artifactId>

<name>openHAB Add-ons :: Automation :: Jython Helper Libraries</name>

<dependencies>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.automation.module.script</artifactId>
<version>2.5.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.automation.helperlibraries.jython-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/2.5.0/xml/features</repository>

<feature name="openhab-helperlibraries-jython" description="Jython Helper Libraries" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-core-automation</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.automation.helperlibraries.jython/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.automation.helperlibraries.jython.internal;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.TreeSet;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* These helper libraries aid in the use of Jython within scripted automation.
*
* @author Scott Rushworth - Initial contribution
*/
@Component(service = JythonHelperLibraries.class)
@NonNullByDefault
public class JythonHelperLibraries {

protected final Logger logger = LoggerFactory.getLogger(getClass());
private static final String HELPER_LIBRARY_PYTHON_PATH = new StringBuilder(JythonHelperLibraries.class
.getProtectionDomain().getCodeSource().getLocation().toString().replace("file:", "")).toString();

@Activate
public JythonHelperLibraries() {
logger.debug("Loading Jython helper libraries");
String existingPythonPath = System.getProperty("python.path");
// logger.warn("existingPythonPath: '{}'", existingPythonPath);
if (existingPythonPath == null || existingPythonPath.isEmpty()) {
System.setProperty("python.path", HELPER_LIBRARY_PYTHON_PATH);
} else if (!existingPythonPath.contains(HELPER_LIBRARY_PYTHON_PATH)) {
TreeSet<String> newPythonPathList = new TreeSet<>(
new ArrayList<String>(Arrays.asList(existingPythonPath.split(File.pathSeparator))));
// logger.warn("Before addition: '{}'", newPythonPathList);
newPythonPathList.add(HELPER_LIBRARY_PYTHON_PATH);
// logger.warn("After addition: '{}'", newPythonPathList);
String newPythonPath = String.join(File.pathSeparator, newPythonPathList);
// logger.warn("String: '{}'", newPythonPath);
System.setProperty("python.path", newPythonPath);
}

logger.trace("python.home [{}], python.path [{}]", System.getProperty("python.home"),
System.getProperty("python.path"));
}

// This does not work properly, since Deactivate() is called immediately after Activate() due to there being no
// dependencies on the service.
// @Deactivate
// public void deactivate() {
// logger.debug("Unloading Jython helper libraries");
// String existingPythonPath = System.getProperty("python.path");
// //logger.warn("existingPythonPath: '{}'", existingPythonPath);
// if (existingPythonPath.contains(HELPER_LIBRARY_PYTHON_PATH)) {
// TreeSet<String> newPythonPathList = new TreeSet<>(
// new ArrayList<String>(Arrays.asList(existingPythonPath.split(File.pathSeparator))));
// //logger.warn("Before removal: '{}'", newPythonPathList);
// newPythonPathList.remove(HELPER_LIBRARY_PYTHON_PATH);
// //logger.warn("After removal: '{}'", newPythonPathList);
// String newPythonPath = String.join(File.pathSeparator, newPythonPathList);
// //logger.warn("String: '{}'", newPythonPath);
// System.setProperty("python.path", newPythonPath);
// }
// logger.trace("python.home [{}], python.path [{}], python.cachdir [{}]", System.getProperty("python.home"),
// System.getProperty("python.path"), System.getProperty("python.cachedir"));
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
The ``area_triggers_and_actions`` package provides a mechanism for using group
logic to trigger rules and then perform a particular action.
This package provides the following modules:
* ``area_actions``
"""
__all__ = ['start_action', 'stop_timer']

from threading import Timer

from core.jsr223.scope import ON, OFF, OPEN, CLOSED
from core.metadata import get_key_value
from core.log import logging, LOG_PREFIX, log_traceback

from community.area_triggers_and_actions.area_actions import *

try:
import sys
import personal.area_triggers_and_actions.area_actions
reload(sys.modules['personal.area_triggers_and_actions.area_actions'])
from personal.area_triggers_and_actions.area_actions import *
except:
pass

#from org.joda.time import DateTime

log = logging.getLogger("{}.community.area_triggers_and_actions".format(LOG_PREFIX))

timer_dict = {}

@log_traceback
def _timer_function(item, active, function_name, timer_type, timer_delay, recurring, function):
"""This is the function called by the timers."""
#log.warn("_timer_function: item.name [{}], active [{}], function_name [{}], timer_type [{}], timer_delay [{}], recurring [{}], function [{}]".format(item.name, active, function_name, timer_type, timer_delay, recurring, function))
function(item, active)
log.debug("{}: [{}] second {} {} timer has completed".format(item.name, timer_delay, function_name, timer_type))
if recurring and item.state in [ON, OPEN] if active else item.state in [OFF, CLOSED]:
timer_dict.update({item.name: {function_name: {timer_type: Timer(timer_delay, _timer_function, [item, active, function_name, timer_type, timer_delay, recurring, function])}}})
timer_dict[item.name][function_name][timer_type].start()
log.debug("{}: [{}] second recurring {} {} timer has started".format(item.name, timer_delay, function_name, timer_type))

def start_action(item, active, function_name):
"""
This is the function called by the rule to begin the selected action,
which may be first passed through a timer.
Args:
item Item: The Item to perform the action on
active boolean: Area activity (True for active and False for inactive)
function_name string: Name of the action function
"""
#start_time = DateTime.now().getMillis()
timer_type = "ON" if active else "OFF"
function = globals()[function_name]
function_metadata = get_key_value(item.name, "area_triggers_and_actions", "actions", function_name)
limited = function_metadata.get("limited")
timer_metadata = function_metadata.get(timer_type, {})
if not limited or timer_metadata:
timer_delay = timer_metadata.get("delay")
recurring = timer_metadata.get("recurring")
#log.warn("start_action: item.name [{}], active [{}], function_name [{}], timer_type [{}], timer_delay [{}], recurring [{}], function [{}]".format(item.name, active, function_name, timer_type, timer_delay, recurring, function))
if not timer_delay:
function(item, active)
elif timer_dict.get(item.name, {}).get(function_name, {}).get(timer_type) is None or not timer_dict[item.name][function_name][timer_type].isAlive():# if timer does not exist, create it
timer_dict.update({item.name: {function_name: {timer_type: Timer(timer_delay, _timer_function, [item, active, function_name, timer_type, timer_delay, recurring, function])}}})
timer_dict[item.name][function_name][timer_type].start()
log.debug("{}: [{}] second {}{} {} timer has started".format(item.name, timer_delay, "recurring " if recurring else "", function_name, timer_type))
stop_timer(item.name, function_name, "OFF" if active else "ON")
#log.warn("Test: start_action: {}: [{}]: time=[{}]".format(item.name, timer_type, DateTime.now().getMillis() - start_time))

def stop_timer(item_name, function_name, timer_type):
"""This function stops the timer."""
#log.warn("stop_timer: function_name [{}], timer_type [{}], item_name [{}]".format(function_name, timer_type, item_name))
if timer_dict.get(item_name, {}).get(function_name, {}).get(timer_type) is not None and timer_dict[item_name][function_name][timer_type].isAlive():# if timer exists, stop it
timer_dict[item_name][function_name][timer_type].cancel()
log.debug("{}: {} {} timer has been cancelled".format(item_name, function_name, timer_type))
Loading

0 comments on commit 9468c87

Please # to comment.