This is a set of answer rather than a question. The questions answered are:
1) How do I access Modbus registers using python?
2) How do I enable the Hiawatha server on Venus OS or GX device to run python scripts?
3) Where can I add my own HTML or script pages to be served by my GX device?
Last year we used a GPS GSM vehicle tracker device to keep track of the boat location while cruising but had no real programatic access to the location data. Using Venus OS on a Raspberry pi I have developed a method to access our location via web pages.
Enable Python scripts in the Venus OS Web server (Hiawatha)
Nano /etc/hiawatha/hiawatha.conf and uncomment the python script line
#CGIhandler = /usr/bin/perl:pl
#CGIhandler = /usr/bin/php-cgi:php
# enable by LH to run py as cgi scripts
CGIhandler = /usr/bin/python:py
#CGIhandler = /usr/bin/ruby:rb
#CGIhandler = /usr/bin/ssi-cgi:shtml
It is possible to modify hiawatha.conf to set up a new virtual server with specific access conditions to improve security. I have not covered these changes in this post but can look into it if anyone in interested.
Add pages to be served by the Hiawatha Server
Pages to be served can be added in the directory /var/www/venus
A new page page.html is then accessible on the GX local network as
http://<IP address>/page.html
If you want to access your pages from the internet you will need to reconfigure your routers firewall to direct incoming traffic from the internet to arrive at the IP address of the GX device. This is not necessary if you are just going to access the GX on the local network. If doing this for permanent use then it would be best to edit hiawatha.conf to set up a new virtual server as mentioned above, with out that your router may open access to your GX remote console without the security of going via the VRM.
Use python to access Modbus registers
Here is the python script I am using to read the latitude and longitude data from the GX Modbus.
#!/usr/bin/env python
#import pymodmus stuff
from pymodbus.constants import Defaults
from pymodbus.constants import Endian
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from pymodbus.payload import BinaryPayloadDecoder
Defaults.Timeout = 25
Defaults.Retries = 5
client = ModbusClient('localhost', port='502')
# need 4x16 bit registers so read argument is 4 - modbus is just like that
result = client.read_input_registers(2800, 4)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Big)
#This is written longahnd so that you can see what is happening
reg1=decoder.decode_32bit_int()
reg2=decoder.decode_32bit_int()
latitude=float(reg1)/10000000
longitude=float(reg2)/10000000
(Strange 5.s are appearing in some code snippets they should not be there, please ignore)
This is the first half of a file location.py stored in /var/www/venus
The second half returns the information in an html page like this
#got the location so send HTTP redirect to display in google maps
print "Content-Type: text/html"
print """\
<html>
<head>
<title>Lady's Smock Location</title>
</head>
<body>
<h1>Where is Lady's Smock</h1>
"""
print("<a href='https://www.google.com/maps/?f=q&q=%f,%f&z=17'>Boat Location</a>" % (latitude, longitude))
print("<br>Latitude %f Longitude %f" % (latitude, longitude))
print """\
</body>
</html>
"""
Note that you do not need to set execute access on the file, the server CGI handler will take care of running the file. However it is useful to set execute access (chmod 775 location.py) to test run the file for errors. Remember to remove the execute access (chmod -x location.py) when you have finished testing.
Accessing http://<GX IP address>/location.py displays the following.
And clicking on the link displays the location in google maps.
Alternative html responses
As an alternative you can issue an HTTP or HTML redirect to go to google maps like this.
#got the location so send HTTP redirect to display in google maps
print "status: 303 refer other"
print "Content-Type: text/html"
print("location: https://www.google.com/maps/?f=q&q=%f,%f&z=17" % (latitude, longitude))
#Keep Hiawatha server happy with blank content
print """\
<html>
<body>
</body>
</html>
"""
or like this
#got the location so send redirect to display in google
print """\
Content-Type: text/html
<html>
"""
print("<meta http-equiv='refresh' content='0;url=https://www.google.com/maps?f=q&q=%f,%f' />" % (latitude, longitude))
print """\
</head>
<body>
you should have been redirected
</body>
</html>
"""
Accessing either of these pages should redirect immediately to a google map showing the location.
Embedding location information in other web pages
If you want to use the location information embedded in other web pages then you need to us a google maps embed API as described in: https://developers.google.com/maps/documentation/embed/get-api-key
This adds only a little more complication like this.
apikey = "your secret key from google"
#got the location so send redirect to display in google
print """\
Content-Type: text/html
<html>
<body>"""
print("<iframe src='https://www.google.com/maps/embed/v1/place?key=%s&q=%f,%f' width='100%%' height='96%%'/>" % (apikey, latitude, longitude))
print """\
</iframe>
</body>
</html>
"""
(Strange 5.s are appearing in some code snippets they should not be there, please ignore)
This creates a response which embeds the google map in an iframe you can then embed that iframe in your own web pages like this:
<iframe src="http://<domain address of your GX device>/map-iframe.py" width="640" height="480"></iframe>
On our boats webpage this will look like this:
Finally
Remember that all changes to /var/www and /etc will be lost after an upgrade (I hope to do a post soon about storing all changes on a removable USB memory stick so that you can re apply changes easily after any upgrade)
"On the Back's of Giants" None of what I have done here would have been possible without the assistance of many others who have posted their code snippets to the internet in "Stackexchange" the Victron Community and other locations I freely acknowledge their contributions and make this post in the same spirit - Enjoy.