Using a Python-REST-API for Monitoring Things States
In advance: I am no python crack but searched a solution for creating Things-items and updating the states, too. Just for having a quick accessable overview in the new OpenHab widgets.
The Beginning:
- create an OH-API-token. Save it or write it down somewhere.
- think about a semantic group name for your Things-items.
Next step will be, copying the code into a new file into a new file in /openhab/scripts/“filename”.py.
What will happen:
- The Things will be fetched an renamed, which is necessary for having the link for creating the Item
- The list of Things-Items is compared with the existing Item-list. So just new Thing-Items and new Thing-Item-states will be pushed through HTTP-request.
getthingsitem.py
import requests
from datetime import datetime
#Global Variables
openhabip = 'XXX.XXX.XXX.XXX'
syntax_replacement = {" " : "_", "-" : "_", "ä" : "ae", "ü" : "ue", "ö" : "oe", ".":"_","!":"",":" : "_","(":"_",")":"_"}
timestamp = datetime.now().strftime("%A %d/%m/%Y, %H:%M:%S")
thingitemgroup = 'gThingStates' #you can change the group name, as you like
access_token = 'YOUR OPHAB API TOKEN'
headers = {'accept':'*/*','content-type':'application/json','Authorization': 'Bearer {}'.format(access_token)}
headers_post = {'accept':'*/*','content-type':'text/plain','Authorization': 'Bearer {}'.format(access_token)}
things_req = requests.get('http://'+openhabip+':8080/rest/things', headers=headers)
items_req = requests.get('http://'+openhabip+':8080/rest/items', headers=headers)
def getthings(): #fetching things
things_arr = []
things_all = things_req.json()
for i in range(len(things_all)):
if things_all[i]["statusInfo"]["status"] :
things_exp = (things_all[i]["label"]).translate(str.maketrans(syntax_replacement))+"_Thing"
things_status = (things_all[i]["statusInfo"]["status"])
things_arr.append({'item' : things_exp , 'state' : things_status})
return things_arr
def getOHitems(): #fetching OH-Items
ohitems_arr = []
ohitems_all = items_req.json()
for i in range(len(ohitems_all)):
ohitems_exp = (ohitems_all[i]["name"])
ohitems_exp_state = (ohitems_all[i]["state"])
ohitems_arr.append({'item' : ohitems_exp , 'state' : ohitems_exp_state})
return ohitems_arr
def comparegets(): #comparing lists for adding or updating just new Thing-Items or states. Less API requests, especially while running the script in cron-intervals.
things_arr = getthings()
ohitems_arr = getOHitems()
thing_put = []
have_2 = {(d['item'], d['state']) for d in ohitems_arr}
extra = [d for d in things_arr if (d['item'], d['state']) not in have_2]
print(timestamp)
if extra == []:
print("No new Items to add or to update!")
else:
print("New items added or updated: ", extra)
for i in range(len(extra)): #creating new items from new thing and updating states, if changed
if extra[i]["item"]:
things_exp = (extra[i]["item"])
things_status = (extra[i]["state"])
thing_link = ('http://'+openhabip+':8080/rest/items/'+things_exp)
thing_put.append({'item' : things_exp , 'state' : things_status, 'link' : thing_link})
itemtoput_arr = [{'link': 'http://'+openhabip+':8080/rest/items/'+things_exp, 'state': 'null', 'editable': 'true', 'type': 'String', 'name': things_exp, 'label': things_exp, 'category': '', 'tags': [ 'Point' ], 'groupNames': [ thingitemgroup]}]
newitem_put = requests.put('http://'+openhabip+':8080/rest/items' , json=itemtoput_arr , headers=headers)
item_post = requests.put('http://'+openhabip+':8080/rest/items/'+things_exp +'/state' , data=things_status , headers=headers_post)
print(newitem_put)
print(item_post)
comparegets()
Add the Exec Binding to your instance like e.g.:
UID: exec:command:ExecGetThings
label: ExecGetThings
thingTypeUID: exec:command
configuration:
transform: REGEX((.*))
interval: 0
autorun: false
command: sudo -u openhab python3 /etc/openhab/scripts/getthingstates.py
timeout: 30
It is possible to create 5 channels (see OpenHab Exec Binding)
For running the rule th channel id “run” is needed, which sends “ON” to the created Exec Thing.
I am running the script through a rule:
triggers:
- id: "1"
configuration:
cronExpression: 0 0/15 * * * ? *
type: timer.GenericCronTrigger
conditions: []
actions:
- inputs: {}
id: "2"
configuration:
itemName: ExecGetThings_Ausfuhrung
command: ON
type: core.ItemCommandAction
- inputs: {}
id: "3"
configuration:
type: application/vnd.openhab.dsl.rule
script:
logInfo("GetThingsRule","Neue Things werden gesucht und die States werden aktualisiert!")
type: script.ScriptAction
Remember setting the py-script name as you choosed in the beginning and place it in the rule where I wrote “getthingstates”.
There is a need to whitelist the command in the Exec Binding in /misc/exec.whitelist .
Result:
In the first execution all Things will be added an the states will be set as String.
In a widget a result after filtering for states !=“ONLINE” could be:
Other Thing-States will be shown as in the Things-UI.
New Things will be added wile running the rule and states will be updated.
If you have suggestions or questions, please feel free. I try to answer.
Hav a nice OH-time!