Hi,
in the last 2 weeks I started to learn Python. After a few hours I was able to write some small programs and so fascinated thus I started to migrate my existing bash scripts to python, to have a more stable and reliable interface solution.
I know that the created code is for sure not perfect and could be optimized, but I also know that there are several Python beginners in the pimatic community looking for an interface to pimatic or some code snippets to write own solutions.
For read/write from/to pimatic (variables) I’ve created a module ‘pimatic.py’ .
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import os.path
import requests
import json
config = {
'host' : os.uname()[1],
'port' : '',
'user' : '',
'pass' : '',
'home' : '/home/pi',
'config' : '/pimatic-app/config.json',
'vdir' : '/api/variables/',
'headers' : {'Content-Type':'application/json'}
}
#-------------------------------------------------------------------------------------------------
# get host and login data to access pimatic server
#
# for local pimatic access, config.json is read to get account data
# for remote access, create a file 'server.host' in PIMATIC_HOME and json format,
# where host is the 'hostname' of the pimatic server and include the
# host access parameter to login to pimatic server --> explore 'server.example'
#
def get_credentials_for_pimatic_access(pimatic_server):
global config
error = None
#
# check if a server file for remote access exist, otherwise use local hostname and config.json
#
file = config['home'] + '/server.' + pimatic_server # for remote access
if os.path.isfile(file) and os.access(file, os.R_OK):
config['host'] = pimatic_server
else :
error = 'There is no readable server file \'' + file + '\' for remote access!'
file = config['home'] + config['config'] # local config file
if not os.path.isfile(file) or not os.access(file, os.R_OK):
error = error + 'nor a readable standard json file!'
return error
else:
error = None
#
# open file (json format) and get port, username and password
#
with open(file, 'r') as conf:
try:
pjson = json.load(conf)
except ValueError:
error = 'Decoding of JSON file \'' + file + '\' has failed!'
return error
port = (pjson['settings']['httpServer']['port'])
if port == None:
port = (pjson['settings']['httpsServer']['port'])
if port != None:
config['port'] = str(port)
else :
error = 'could not read port from file: '+ file +'!'
for user in pjson['users']:
#{u'username': u'admin', u'password': u'nnnnnn', u'role': u'admin'}
if user['role'] == 'admin':
config['user'] = user['username']
config['pass'] = user['password']
#print config
return error
#----------------------------------------------------------------------------------------
# write variable (name, value) trough pimatic server
#
def write(pimatic_server, pimatic_variable, pimatic_value):
error = None
if get_credentials_for_pimatic_access(pimatic_server) :
return [error]
url = 'http://'+ config['host'] + ':' + config['port'] + config['vdir'] + pimatic_variable
params = {'type': 'value', 'valueOrExpression': pimatic_value}
try:
rdata = requests.patch(url, data=None, headers=config['headers'], auth=(config['user'], config['pass']), params=params)
except requests.exceptions.ConnectionError as error:
return [error]
except requests.exceptions.HTTPError as error:
return [error]
if not rdata.ok :
error = rdata.status_code
elif not rdata.json()['success'] :
error = 'something went wrong!'
return [error]
#----------------------------------------------------------------------------------------
# read variable (name, value) from conf server
#
def read(pimatic_server, pimatic_variable):
error = None
pvalue = ""
if get_credentials_for_pimatic_access(pimatic_server) :
return [error]
url = 'http://'+ config['host'] + ':' + config['port'] + config['vdir'] + pimatic_variable
try:
rdata = requests.get(url, auth=(config['user'], config['pass']))
except requests.exceptions.ConnectionError as error:
return pvalue
except requests.exceptions.HTTPError as error:
return [error, pvalue]
if rdata.ok :
if rdata.json()['success'] and rdata.json()['variable'] is None:
error = 'sorry, did not receive a value for variable \'' + pimatic_variable + '\'!'
elif rdata.json()['success'] and rdata.json()['variable']:
pvalue = rdata.json()['variable']['value']
else:
error = 'something went wrong, did not receive a value for variable \'' + pvalue + '\'!'
else :
error = rdata.status_code
return [error, pvalue]
The module can be imported into pimatic scripts and provide than functions to read and to write variables to a local or remote pimatic server. For easy understanding of usage and for testing the following python script can be used to read/write values from shell level to a pimatic server.
rpimatic.py [-h] [-s SERVER] -c COMMAND -n PIMATIC_VAR_NAME
[-v PIMATIC_VAR_VALUE]
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import argparse
import pimatic
def main ():
parser = argparse.ArgumentParser(description='Read/Write variables to/from a pimatic server')
parser.add_argument("-s","--server", help="host name for target pimatic server", default=os.uname()[1], required=False)
parser.add_argument("-c","--command", help="command to execute: read|write", required=True)
parser.add_argument("-n","--pimatic_var_name", help="name of variable", default=None, required=True)
parser.add_argument("-v","--pimatic_var_value", help="value of variable", default=None, required=False)
flags = parser.parse_args()
command = flags.command
pserver = flags.server
pvariable = flags.pimatic_var_name
pvalue = flags.pimatic_var_value
if command == 'write' :
rvalue = pimatic.write(pserver, pvariable, pvalue)
print ('Error: %s - send value for \'%s\' : \'%s\'' % ( rvalue[0], pvariable, pvalue))
elif command == 'read' :
rvalue = pimatic.read(pserver, pvariable)
print ('Error: %s - received value for \'%s\' : \'%s\'' % ( rvalue[0], pvariable, rvalue[1]))
else :
print 'wrong command !'
if __name__ == '__main__':
main()
For access to a local pimatic server the ‘config.json’ file is read to get the port and account data of the user with ‘role : admin’. For remote access a file named ‘server.targethost’ in JSON format needs to be created in directory ‘/home/pi’. Here is a simple example file.
server.myPimaticHost - myPimaticHost must be a valid, resolvable hostname or IP address
{
"settings": {
"locale": "de",
"httpServer": {
"enabled": true,
"port": 80
},
"httpsServer": {}
},
"users": [
{
"username": "admin",
"password": "XXXXXXX",
"role": "admin"
}
]
}
Not yet support are SSL-Connections, due that I’m not using https for access to my pimatic host. But it should be just a little effort to add this enhancement to the code.
I just started with python, so I would be pleased for every feedback to improve the modul. In the meantime I migrated also my bash script for google calendar access and substituted ‘gcalcli’ by own written python scripts.
Pimatic is really great !! Have fun …