Skip to content

Commit 4146795

Browse files
committed
added shared jsr223 helper libraries
1 parent 858d2e8 commit 4146795

File tree

10 files changed

+204
-98
lines changed

10 files changed

+204
-98
lines changed

python/shared/actions.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import sys
2-
from core import osgi
2+
from shared.services import find_service
33

4-
actions = osgi.find_services("org.openhab.core.model.script.engine.action.ActionService", None)
4+
5+
actions = find_service("org.openhab.core.model.script.engine.action.ActionService", None)
56

67
_MODULE = sys.modules[__name__]
78

python/shared/helper.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import threading
77
import sys
88

9-
#from java.util import UUID
10-
#import datetime
119
from java.lang import NoSuchFieldException
1210
from org.openhab.core.automation import Rule as SmarthomeRule
1311

@@ -17,18 +15,16 @@
1715

1816
from java.time import ZonedDateTime, Instant, ZoneId
1917
from java.time.format import DateTimeFormatter
20-
21-
#from core.jsr223 import scope
22-
from core.triggers import ItemStateUpdateTrigger, ItemStateChangeTrigger
18+
19+
from shared.jsr223 import scope
20+
from shared.triggers import ItemStateUpdateTrigger, ItemStateChangeTrigger
2321

2422
from org.slf4j import LoggerFactory
2523

2624
from configuration import LOG_PREFIX, allTelegramBots, allTelegramAdminBots
2725

2826
log = LoggerFactory.getLogger(LOG_PREFIX)
2927

30-
scope = sys._getframe(1).f_globals
31-
3228
actions = scope.get("actions")
3329

3430
itemRegistry = scope.get("itemRegistry")

python/shared/jsr223.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import sys
2+
from org.osgi.framework import FrameworkUtil
3+
4+
def get_scope():
5+
depth = 1
6+
while True:
7+
try:
8+
frame = sys._getframe(depth)
9+
name = str(type(frame.f_globals))
10+
if name == "<type 'scope'>":
11+
return frame.f_globals
12+
depth += 1
13+
except ValueError:
14+
raise EnvironmentError("No JSR223 scope is available")
15+
16+
scope = get_scope()

python/shared/readme.txt

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Inspiration and some codes comes from
2+
3+
https://github.com/CrazyIvan359/openhab-helper-libraries
4+
5+
and
6+
7+
https://github.com/openhab-scripters/openhab-helper-libraries
8+
9+

python/shared/semantic/__init__.py

-27
Original file line numberDiff line numberDiff line change
@@ -1,27 +0,0 @@
1-
"""
2-
This module (really a Python package) patches the default scope ``items``
3-
object, so that Items can be accessed as if they were attributes (rather than a
4-
dictionary). It can also be used as a module for registering global variables
5-
that will outlive script reloads.
6-
7-
.. code-block::
8-
9-
import core
10-
11-
print items.TestString1
12-
13-
.. note::
14-
This patch will be applied when any module in the `core` package is loaded.
15-
"""
16-
17-
from core.jsr223.scope import items
18-
19-
#
20-
# Add an attribute-resolver to the items map
21-
#
22-
23-
def _item_getattr(self, name):
24-
return self[name]
25-
26-
if items:# this check prevents errors if no Items have been created yet
27-
type(items).__getattr__ = _item_getattr.__get__(items, type(items))
-27
Original file line numberDiff line numberDiff line change
@@ -1,27 +0,0 @@
1-
"""
2-
This module (really a Python package) patches the default scope ``items``
3-
object, so that Items can be accessed as if they were attributes (rather than a
4-
dictionary). It can also be used as a module for registering global variables
5-
that will outlive script reloads.
6-
7-
.. code-block::
8-
9-
import core
10-
11-
print items.TestString1
12-
13-
.. note::
14-
This patch will be applied when any module in the `core` package is loaded.
15-
"""
16-
17-
from core.jsr223.scope import items
18-
19-
#
20-
# Add an attribute-resolver to the items map
21-
#
22-
23-
def _item_getattr(self, name):
24-
return self[name]
25-
26-
if items:# this check prevents errors if no Items have been created yet
27-
type(items).__getattr__ = _item_getattr.__get__(items, type(items))
-27
Original file line numberDiff line numberDiff line change
@@ -1,27 +0,0 @@
1-
"""
2-
This module (really a Python package) patches the default scope ``items``
3-
object, so that Items can be accessed as if they were attributes (rather than a
4-
dictionary). It can also be used as a module for registering global variables
5-
that will outlive script reloads.
6-
7-
.. code-block::
8-
9-
import core
10-
11-
print items.TestString1
12-
13-
.. note::
14-
This patch will be applied when any module in the `core` package is loaded.
15-
"""
16-
17-
from core.jsr223.scope import items
18-
19-
#
20-
# Add an attribute-resolver to the items map
21-
#
22-
23-
def _item_getattr(self, name):
24-
return self[name]
25-
26-
if items:# this check prevents errors if no Items have been created yet
27-
type(items).__getattr__ = _item_getattr.__get__(items, type(items))

python/shared/semantic/model/semantic_model.py

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
#https://github.com/openhab/openhab-core/blob/master/bundles/org.openhab.core.semantics/model/SemanticTags.csv
2-
from core.actions import HTTP
2+
from shared.actions import HTTP
3+
from shared.services import get_service
4+
35
import json
46
import re
57
import io
68

7-
from core import osgi,metadata
8-
try:
9-
from org.openhab.core.items import Metadata, MetadataKey
10-
except:
11-
from org.eclipse.smarthome.core.items import Metadata, MetadataKey
9+
from org.openhab.core.items import Metadata, MetadataKey
10+
1211

13-
METADATA_REGISTRY = osgi.get_service(
12+
METADATA_REGISTRY = get_service(
1413
"org.openhab.core.items.MetadataRegistry"
15-
) or osgi.get_service(
14+
) or get_service(
1615
"org.eclipse.smarthome.core.items.MetadataRegistry"
1716
)
1817

python/shared/services.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import sys
2+
from org.osgi.framework import FrameworkUtil
3+
4+
from shared.jsr223 import scope
5+
6+
scriptExtension = scope.get("scriptExtension")
7+
8+
_BUNDLE = FrameworkUtil.getBundle(type(scriptExtension))
9+
BUNDLE_CONTEXT = _BUNDLE.getBundleContext() if _BUNDLE else None
10+
REGISTERED_SERVICES = {}
11+
12+
def get_service(class_or_name):
13+
if BUNDLE_CONTEXT:
14+
classname = class_or_name.getName() if isinstance(class_or_name, type) else class_or_name
15+
ref = BUNDLE_CONTEXT.getServiceReference(classname)
16+
return BUNDLE_CONTEXT.getService(ref) if ref else None
17+
else:
18+
return None
19+
20+
def find_service(class_name, service_filter):
21+
if BUNDLE_CONTEXT:
22+
references = BUNDLE_CONTEXT.getServiceReferences(class_name, service_filter)
23+
if references:
24+
return [BUNDLE_CONTEXT.getService(reference) for reference in references]
25+
else:
26+
return []
27+
else:
28+
return None

python/shared/triggers.py

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
from shared.jsr223 import scope
2+
3+
import uuid
4+
import re
5+
6+
scriptExtension = scope.get("scriptExtension")
7+
scriptExtension.importPreset("RuleSupport")
8+
9+
TriggerBuilder = scope.get("TriggerBuilder")
10+
Configuration = scope.get("Configuration")
11+
Trigger = scope.get("Trigger")
12+
13+
from java.nio.file import StandardWatchEventKinds
14+
ENTRY_CREATE = StandardWatchEventKinds.ENTRY_CREATE # type: WatchEvent.Kind
15+
ENTRY_DELETE = StandardWatchEventKinds.ENTRY_DELETE # type: WatchEvent.Kind
16+
ENTRY_MODIFY = StandardWatchEventKinds.ENTRY_MODIFY # type: WatchEvent.Kind
17+
18+
def validate_uid(uid):
19+
if uid is None:
20+
uid = uuid.uuid1().hex
21+
else:
22+
uid = re.sub(r"[^A-Za-z0-9_-]", "_", uid)
23+
uid = "{}_{}".format(uid, uuid.uuid1().hex)
24+
if not re.match("^[A-Za-z0-9]", uid):# in case the first character is still invalid
25+
uid = "{}_{}".format("jython", uid)
26+
uid = re.sub(r"__+", "_", uid)
27+
return uid
28+
29+
class CronTrigger(Trigger):
30+
def __init__(self, cron_expression, trigger_name=None):
31+
trigger_name = validate_uid(trigger_name)
32+
configuration = {'cronExpression': cron_expression}
33+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("timer.GenericCronTrigger").withConfiguration(Configuration(configuration)).build()
34+
35+
36+
class ItemStateUpdateTrigger(Trigger):
37+
def __init__(self, item_name, state=None, trigger_name=None):
38+
trigger_name = validate_uid(trigger_name)
39+
configuration = {"itemName": item_name}
40+
if state is not None:
41+
configuration["state"] = state
42+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.ItemStateUpdateTrigger").withConfiguration(Configuration(configuration)).build()
43+
44+
45+
class ItemStateChangeTrigger(Trigger):
46+
def __init__(self, item_name, previous_state=None, state=None, trigger_name=None):
47+
trigger_name = validate_uid(trigger_name)
48+
configuration = {"itemName": item_name}
49+
if state is not None:
50+
configuration["state"] = state
51+
if previous_state is not None:
52+
configuration["previousState"] = previous_state
53+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.ItemStateChangeTrigger").withConfiguration(Configuration(configuration)).build()
54+
55+
56+
class ItemCommandTrigger(Trigger):
57+
def __init__(self, item_name, command=None, trigger_name=None):
58+
trigger_name = validate_uid(trigger_name)
59+
configuration = {"itemName": item_name}
60+
if command is not None:
61+
configuration["command"] = command
62+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.ItemCommandTrigger").withConfiguration(Configuration(configuration)).build()
63+
64+
65+
class ThingStatusUpdateTrigger(Trigger):
66+
def __init__(self, thing_uid, status=None, trigger_name=None):
67+
trigger_name = validate_uid(trigger_name)
68+
configuration = {"thingUID": thing_uid}
69+
if status is not None:
70+
configuration["status"] = status
71+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.ThingStatusUpdateTrigger").withConfiguration(Configuration(configuration)).build()
72+
73+
74+
class ThingStatusChangeTrigger(Trigger):
75+
def __init__(self, thing_uid, previous_status=None, status=None, trigger_name=None):
76+
trigger_name = validate_uid(trigger_name)
77+
configuration = {"thingUID": thing_uid}
78+
if previous_status is not None:
79+
configuration["previousStatus"] = previous_status
80+
if status is not None:
81+
configuration["status"] = status
82+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.ThingStatusChangeTrigger").withConfiguration(Configuration(configuration)).build()
83+
84+
85+
class ChannelEventTrigger(Trigger):
86+
def __init__(self, channel_uid, event=None, trigger_name=None):
87+
trigger_name = validate_uid(trigger_name)
88+
configuration = {"channelUID": channel_uid}
89+
if event is not None:
90+
configuration["event"] = event
91+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.ChannelEventTrigger").withConfiguration(Configuration(configuration)).build()
92+
93+
94+
class GenericEventTrigger(Trigger):
95+
def __init__(self, event_source, event_types, event_topic="*/*", trigger_name=None):
96+
trigger_name = validate_uid(trigger_name)
97+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.GenericEventTrigger").withConfiguration(Configuration({
98+
"eventTopic": event_topic,
99+
"eventSource": event_source,
100+
"eventTypes": event_types
101+
})).build()
102+
103+
104+
class ItemEventTrigger(Trigger):
105+
def __init__(self, event_types, item_name=None, trigger_name=None):
106+
trigger_name = validate_uid(trigger_name)
107+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.GenericEventTrigger").withConfiguration(Configuration({
108+
"eventTopic": "*/items/*",
109+
"eventSource": "/items/{}".format(item_name if item_name else ""),
110+
"eventTypes": event_types
111+
})).build()
112+
113+
114+
class ThingEventTrigger(Trigger):
115+
def __init__(self, event_types, thing_uid=None, trigger_name=None):
116+
trigger_name = validate_uid(trigger_name)
117+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("core.GenericEventTrigger").withConfiguration(Configuration({
118+
"eventTopic": "*/things/*",
119+
"eventSource": "/things/{}".format(thing_uid if thing_uid else ""),
120+
"eventTypes": event_types
121+
})).build()
122+
123+
124+
class StartupTrigger(Trigger):
125+
def __init__(self, trigger_name=None):
126+
trigger_name = validate_uid(trigger_name)
127+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("jsr223.StartupTrigger").withConfiguration(Configuration()).build()
128+
129+
130+
class DirectoryEventTrigger(Trigger):
131+
def __init__(self, path, event_kinds=[ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY], watch_subdirectories=False, trigger_name=None):
132+
trigger_name = validate_uid(trigger_name)
133+
configuration = {
134+
'path': path,
135+
'event_kinds': str(event_kinds),
136+
'watch_subdirectories': watch_subdirectories,
137+
}
138+
self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("jsr223.DirectoryEventTrigger").withConfiguration(Configuration(configuration)).build()

0 commit comments

Comments
 (0)