kopia lustrzana https://github.com/craigerl/digipi
272 wiersze
9.7 KiB
Python
Executable File
272 wiersze
9.7 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# u p d a t e c h a n n e l . p y
|
|
# $Revision: 175 $
|
|
# $Author: eckertb $
|
|
# $Id: updatechannel.py 175 2014-10-19 19:01:52Z eckertb $
|
|
#
|
|
# Description:
|
|
# RMS Gateway - update the channel info currently stored in
|
|
# the winlink system
|
|
#
|
|
# RMS Gateway
|
|
#
|
|
# Copyright (c) 2004-2014 Hans-J. Barthen - DL5DI
|
|
# Copyright (c) 2008-2014 Brian R. Eckert - W3SG
|
|
#
|
|
# Questions or problems regarding this program can be emailed
|
|
# to linux-rmsgw@w3sg.org
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
#
|
|
|
|
import sys
|
|
import re
|
|
import requests
|
|
import json
|
|
import platform
|
|
from xml.etree import ElementTree
|
|
from optparse import OptionParser
|
|
from distutils.version import LooseVersion
|
|
import syslog
|
|
|
|
#################################
|
|
# BEGIN CONFIGURATION SECTION
|
|
#################################
|
|
|
|
service_config_xml = '/etc/rmsgw/winlinkservice.xml'
|
|
gateway_config = '/etc/rmsgw/gateway.conf'
|
|
channel_config_xml = '/etc/rmsgw/channels.xml'
|
|
py_version_require='2.7.9'
|
|
|
|
#################################
|
|
# END CONFIGURATION SECTION
|
|
#################################
|
|
cmdlineparser = OptionParser()
|
|
cmdlineparser.add_option("-d", "--debug",
|
|
action="store_true", dest="DEBUG", default=False,
|
|
help="turn on debug output")
|
|
(options, args) = cmdlineparser.parse_args()
|
|
|
|
errors = 0
|
|
|
|
#
|
|
# dictionaries for config info
|
|
#
|
|
ws_config = {}
|
|
svc_calls = {}
|
|
gw_config = {}
|
|
param_roots = {}
|
|
|
|
#
|
|
# load gateway config
|
|
#
|
|
with open(gateway_config) as gwfile:
|
|
for line in gwfile:
|
|
if not line.strip().startswith('#'):
|
|
name, val = line.partition("=")[::2]
|
|
gw_config[name.strip()] = val.strip()
|
|
gwfile.close()
|
|
|
|
#
|
|
# setup syslog
|
|
#
|
|
fac = eval('syslog.LOG_' + gw_config['LOGFACILITY'].upper())
|
|
mask = eval('syslog.LOG_' + gw_config['LOGMASK'].upper())
|
|
syslog.openlog(logoption=syslog.LOG_PID, facility=fac)
|
|
syslog.setlogmask(syslog.LOG_UPTO(mask))
|
|
|
|
#
|
|
# check python version
|
|
#
|
|
python_version=platform.python_version()
|
|
|
|
if LooseVersion(python_version) >= LooseVersion(py_version_require):
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'Python Version Check: ' + str(python_version) + ' OK')
|
|
else:
|
|
syslog.syslog(syslog.LOG_ERR, 'Need more current Python version, require version: ' + str(py_version_require) + ' or newer')
|
|
print('Exiting ...')
|
|
syslog.closelog()
|
|
sys.exit(1)
|
|
|
|
#
|
|
# load service config from XML
|
|
#
|
|
winlink_service = ElementTree.parse(service_config_xml)
|
|
winlink_config = winlink_service.getroot()
|
|
|
|
for svc_config in winlink_config.iter('config'):
|
|
ws_config['WebServiceAccessCode'] = svc_config.find('WebServiceAccessCode').text
|
|
ws_config['svchost'] = svc_config.find('svchost').text
|
|
ws_config['svcport'] = svc_config.find('svcport').text
|
|
ws_config['namespace'] = svc_config.find('namespace').text
|
|
|
|
for svc_ops in svc_config.findall('svcops'):
|
|
for svc_call in svc_ops:
|
|
svc_calls[svc_call.tag] = svc_call.text
|
|
param_roots[svc_call.tag] = svc_call.attrib['paramRoot']
|
|
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'ws_config = {}'.format(ws_config))
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'svc_calls = {}'.format(svc_calls))
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'param_roots = {}'.format(param_roots))
|
|
|
|
#
|
|
# get gateway callsign from config
|
|
# the basecall
|
|
#
|
|
if 'GWCALL' in gw_config:
|
|
options.callsign = gw_config['GWCALL'].upper()
|
|
|
|
basecall=options.callsign.split("-", 1)[0]
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'basecallsign = {}'.format(basecall))
|
|
|
|
#
|
|
# prepare and make webservice call
|
|
#
|
|
headers = {'Content-Type' : 'application/xml'}
|
|
#headers = {
|
|
# 'Accept': 'application/xml',
|
|
# 'Content-Type': 'application/xml'
|
|
#}
|
|
|
|
# svc_url = 'http://' + ws_config['svchost'] + ':' + ws_config['svcport'] + svc_calls['channeladd']
|
|
# Needs to look like this:
|
|
svc_url = 'https://' + ws_config['svchost'] + svc_calls['channeladd'] + '?' + 'Callsign=' + format(options.callsign) + '&Key=' + format(ws_config['WebServiceAccessCode'] + '&format=json')
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'svc_url = {}'.format(svc_url))
|
|
|
|
#
|
|
# load channel info from XML
|
|
#
|
|
document = ElementTree.parse(channel_config_xml)
|
|
rmschannels = document.getroot()
|
|
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, "rmschannels xml = {}".format(ElementTree.tostring(rmschannels)))
|
|
|
|
#
|
|
# Prepare xml parameters for call
|
|
#
|
|
channel_add = ElementTree.Element(param_roots['channeladd'])
|
|
channel_add.set('xmlns:i', 'http://www.w3.org/2001/XMLSchema-instance')
|
|
channel_add.set('xmlns', ws_config['namespace'])
|
|
|
|
ElementTree.SubElement(channel_add, "BaseCallsign")
|
|
ElementTree.SubElement(channel_add, "Baud")
|
|
ElementTree.SubElement(channel_add, "Callsign")
|
|
ElementTree.SubElement(channel_add, "Frequency")
|
|
ElementTree.SubElement(channel_add, "GridSquare")
|
|
ElementTree.SubElement(channel_add, "Mode")
|
|
ElementTree.SubElement(channel_add, "Power")
|
|
ElementTree.SubElement(channel_add, "Height")
|
|
ElementTree.SubElement(channel_add, "Gain")
|
|
ElementTree.SubElement(channel_add, "Direction")
|
|
ElementTree.SubElement(channel_add, "Hours")
|
|
ElementTree.SubElement(channel_add, "ServiceCode")
|
|
ElementTree.SubElement(channel_add, "Key")
|
|
#ElementTree.SubElement(channel_add, "Comments")
|
|
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'bare channel_add XML = {}'.format(ElementTree.tostring(channel_add)))
|
|
|
|
#
|
|
# with each configured channel,
|
|
# populate call xml tree with values from
|
|
# gateway channel config and make service call
|
|
#
|
|
ns = ws_config['namespace']
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'ns from ws_config = {}'.format(ns))
|
|
ns = '{http://www.namespace.org}'
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'ns = {}'.format(ns))
|
|
|
|
#if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'ns = {}'.format(ns))
|
|
|
|
for channel in rmschannels.findall("%schannel" % (ns)):
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'channel xml = {}'.format(ElementTree.tostring(channel)))
|
|
callsign = channel.find("%scallsign" % (ns)).text
|
|
|
|
syslog.syslog(syslog.LOG_INFO, 'Posting channel record updates for {}...'.format(callsign))
|
|
|
|
#
|
|
# prepare xml parameters for call
|
|
#
|
|
channel_add.find('BaseCallsign').text = channel.find('%sbasecall' % (ns)).text
|
|
channel_add.find('Baud').text = channel.find('%sbaud' % (ns)).text
|
|
channel_add.find('Callsign').text = channel.find('%scallsign' % (ns)).text
|
|
channel_add.find('Direction').text = channel.find('%sdirection' % (ns)).text
|
|
channel_add.find('Frequency').text = channel.find('%sfrequency' % (ns)).text
|
|
channel_add.find('Gain').text = channel.find('%sgain' % (ns)).text
|
|
channel_add.find('GridSquare').text = channel.find('%sgridsquare' % (ns)).text
|
|
channel_add.find('Height').text = channel.find('%sheight' % (ns)).text
|
|
channel_add.find('Mode').text = channel.find('%smode' % (ns)).text
|
|
channel_add.find('Power').text = channel.find('%spower' % (ns)).text
|
|
channel_add.find('Hours').text = channel.find('%shours' % (ns)).text
|
|
channel_add.find('ServiceCode').text = channel.find('%sservicecode' % (ns)).text
|
|
channel_add.find('Key').text = ws_config['WebServiceAccessCode']
|
|
# channel_add.find('Comments').text = channel.find('%scomments' % (ns)).text
|
|
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'channel_add XML = {}'.format(ElementTree.tostring(channel_add)))
|
|
|
|
# Post the request
|
|
try:
|
|
response = requests.post(svc_url, data=ElementTree.tostring(channel_add), headers=headers)
|
|
except requests.ConnectionError as e:
|
|
syslog.syslog(syslog.LOG_DEBUG,"Error: Internet connection failure:")
|
|
syslog.syslog(syslog.LOG_DEBUG, 'svc_url = {}'.format(svc_url))
|
|
syslog.syslog(syslog.LOG_DEBUG, str(e))
|
|
syslog.closelog()
|
|
sys.exit(1)
|
|
|
|
if options.DEBUG: syslog.syslog(syslog.LOG_DEBUG, 'Response = {}'.format(response.content))
|
|
|
|
json_data = response.json()
|
|
if options.DEBUG: print((json.dumps(json_data, indent=2)))
|
|
json_dict = json.loads(response.text)
|
|
|
|
|
|
# print the return code of this request, should be 200 which is "OK"
|
|
if options.DEBUG: print(("Request status code: " + str(response.status_code)))
|
|
if options.DEBUG: print(('Debug: Response =', response.content))
|
|
if options.DEBUG: print(("Debug: Content type: " + response.headers['content-type']))
|
|
# print('ResponseStatus : ', response.json().get('ResponseStatus'))
|
|
|
|
#
|
|
# Verify request status code
|
|
#
|
|
if response.ok:
|
|
if options.DEBUG: print("Debug: Good Request status code")
|
|
else:
|
|
print(("Debug: Bad Response status code: " + str(response.status_code)))
|
|
print(('*** Get for', options.callsign, 'failed, ErrorCode =', str(response.status_code)))
|
|
print(('*** Error code: ' + json_dict['ResponseStatus']['ErrorCode']))
|
|
print(('*** Error message: ' + json_dict['ResponseStatus']['Message']))
|
|
syslog.closelog()
|
|
sys.exit(1)
|
|
|
|
#
|
|
# check for errors coming back first
|
|
#
|
|
if json_dict['ResponseStatus']:
|
|
print(('ResponseStatus not NULL: ', json_dict['ResponseStatus']))
|
|
syslog.closelog()
|
|
sys.exit(1)
|
|
else:
|
|
if options.DEBUG: print(('ResponseStatus is NULL: ', json_dict['ResponseStatus']))
|
|
|
|
|
|
syslog.closelog()
|
|
|
|
if errors > 0:
|
|
sys.exit(1)
|
|
#else
|
|
sys.exit(0)
|