-
-
Notifications
You must be signed in to change notification settings - Fork 79
Appendix C Interfacing Generator Monitor to External Applications
GenMon supports multiple ways to export information to external applications. Applications can interface via TCP/IP. The ClientInterface.py python module is a wrapper for TCP/IP communications to GenMon. In addition the web server application genserv.py is an additional layer that uses ClientInterface module internally to expose a web based interface. Both the ClientInterface and the web interface support exporting data in ASCII and JSON format. The ClientInterface supports many commands to export data which are documented in the Genmon documentation. In addition JSON specific commands have been added. These JSON commands mimic existing GenMon commands in the type of data that is exported, however the format of the data is JSON instead of ASCII. The JSON commands are:
- status_json - export generator status
- status_num_json - export generator status in numeric format
- outage_json - export outage information
- maint_json - export maintenance information
- monitor_json - export information about genmon
- logs_json - export generator logs
- registers_json - export primary registers of the generator controller
- allregs_json - export primary registers and raw log registers
The following repository items are examples of how to interface to Genmon:
- Web UI - genserv.py, /static/genmon.js. These modules show how to interface to genmon via the web interface.
- Web UI = /static/internal.js. This modules uses JSON formatted data to display registers.
- ClientInterface.py - This command line application uses the myclient.py python module to make socket calls. See the genmon documentation for use.
- ClientInterface.java - This java module is the java equivalent of myclient.py. It has had minimal testing but is provided as an example of interfacing to genmon via java If there are any questions regarding how to interface to genmon, feel free to open a thread in the issues section of this project.
The Generator Monitor can display end user data on the Monitor page in the Web Interface. Data is imported into the Generator Monitor by storing JSON formatted data in a file named "userdefined.json" in the genmon directory. The directory can be changed via the advanced settings (double click the gear icon in the upper right). For example you could create a python program that will read the pi's GPIO pins every 5 seconds. If the GPIO changed the program could re-write the userdefined.json file to show the GPIO status.
There are a few folks who have integrated Genmon with some home automation software like NodeLink and Home Assistant. For more info search the issues in this project for the "automation" label. To better integrate with home automation software, the program genmqtt.py was created to import genmon data into a MQTT broker. MQTT is a transport protocol that is used in "Internet of Things" (IoT) and Home Automation applications.
If you have setup secure http with a username and password you can login like this:
import requests
url = 'https://192.168.1.10' # change to your pi IP address
values = {'username': 'myusername', # change myusername to your username
'password': 'mypassword'} # change mypassword to your password
try:
session = requests.Session()
# disable SSL checking for self signed keys
# remove if using user generated keys
session.verify = False
r = session.post(url, data=values)
#print r.text
# get the status data via the same session we used to login
r = session.get(url + "/cmd/status_json")
print r.text
except Exception as e1:
print ("Error: " + str(e1))
You can make calls to the web server. For example if you pi is at IP address 192.168.1.10 you can make use this url:
http://192.168.1.10:8000/cmd/status_json
The different commands are listed in the code at this location
Another command of interest would be the "getbase" command:
http://192.168.1.10:8000/cmd/getbase
This is command is used to change the colors of the menu on the web interface. It returns one of the following states:
ALARM, SERVICEDUE,EXERCISING, RUNNING,RUNNING-MANUAL,OFF, or READY
You can get all the info that is displayed in the web app with these commands:
status_json, maint_json, outage_json, logs_json, monitor_json
If you enter the url with your ip address in your browser you will see the output in JSON format. This can easily be used in most programming languages hat support sockets and JSON. From the Linux command line you can use the curl utility like this:
curl http://192.168.1.10:8000/cmd/status_json
You can also extend the server urls provided by the internal web server (Flask server).
genserv.py will look for a file in the genmon folder named genservext.py, if it is present it will import that file.
The file genservext.py should look something like this:
from __future__ import print_function
from __main__ import app
from genserv import ServePage
#-------------------------------------------------------------------------------
@app.route('/testit', methods=['GET'])
def testit():
return ServePage("myhtml.html")
This will load the file myhtml.html from the ./genmon/static folder if you use the http://192.168.1.10:8000/testit URL.
From here you can create a new html (myhtml.html) in the ./genmon/static folder that loads a javascript (also in the static folder) file and add additional python commands (GPIO, etc) to genservext.py.
Similar to the above method, this approach allows you to extend genmon by monitoring and acting on commands sent to genmon by the socket interface. genmon.py will look for a file in the genmon folder named genmonext.py, if it is present it will import that file and load a python class named GenmonExt. For external command received on the socket interface, genmon will call the GenmonExt member function named PreProcessCommand. Here is an example genmonext.py:
from genmonlib.mysupport import MySupport
#------------ GenmonExt class --------------------------------------------------
class GenmonExt(MySupport):
def __init__(self,
log = None):
self.log = log
self.LogError("GENMONEXT Loaded")
# init class
#-------------------------------------------------------------------------------
# called before any command is processed
def PreProcessCommand(self, command_string):
try:
# parse command
if not isinstance(command_string, str):
# invalid command
return
if not (command_string.lower().startswith == "generator:"):
return
if not "setremote=" in command_string.lower():
return
if "=starttransfer" in command_string.lower():
return
if "=start" in command_string.lower():
# start command
self.LogError("Set remote start")
return
if "=stop" in command_string.lower():
# stop command
self.LogError("Set remote stop")
return
except Exception as e1:
self.LogErrorLine("Error in PreProcessCommand: " + str(e1))
return
NOTE: This interface does not allow commands to be changed, only monitored.