Skip to content

Instantly share code, notes, and snippets.

@openpaul
Created June 8, 2015 11:46
Show Gist options
  • Save openpaul/2104acb62916663848cd to your computer and use it in GitHub Desktop.
Save openpaul/2104acb62916663848cd to your computer and use it in GitHub Desktop.
call RNV api via python
#/bin/python
# RNV.py
# this script can call the server of RNV like the official
# desktop widget does.
# It then returns and saves the departures of a certain station
# and certain lines and directions.
# Tested on ubuntu 15.04
#
# call via command line:
# rnv.py -i <hafasID> -n <Bus Number 1, Bus Number 2> -d <all|direction1, direction2>
# English:
# 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 3 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, see <http://www.gnu.org/licenses/>.
# Deutsch:
# Dieses Programm ist Freie Software: Sie können es unter den Bedingungen
# der GNU General Public License, wie von der Free Software Foundation,
# Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
# veröffentlichten Version, weiterverbreiten und/oder modifizieren.
#
# Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber
# OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
# Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
# Siehe die GNU General Public License für weitere Details.
#
# Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
# Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
import urllib
import urllib2
import json # for handleing the data
import pprint
import sys, getopt
import datetime
import os
import pickle # to save content
class rnv:
''' class to fetch and handle departures of lines in the
rnv area.'''
def __init__(self,argv):
# parse options:
self.options = self.parseOptions(argv)
self.content = {}
self.configPath = "%s/.config/rnv/storage.rnv" %(os.path.expanduser('~'))
# load old displays
self.content = self.loadDisplay()
if self.content == False:
self.fetchDepartures(self.options['id'])
else:
self.checkForUpdate()
self.ouput()
def parseOptions(self, argv):
# default options:
options = {
"id" : 1228, # number according to the url2
"direction" : "all", # may be: all,
"number" : "all" # all or number of line
}
# fetch all options:
try:
opts, args = getopt.getopt(argv,"hi:n:d:",["help", "id=","number=","direction="])
except getopt.GetoptError:
self.usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
# print usage tipps:
self.usage()
elif opt in ("-i", "--id"):
options['id'] = arg
elif opt in ("-n", "--number"):
options['number'] = arg.split(",")
elif opt in ("-d", "--direction"):
options['direction'] = arg.split(",")
print options['direction']
return options
def usage(self):
print 'rnv.py -i <hafasID> -n <Bus Number 1, Bus Number 2> -d <all|direction1, direction2>'
def checkForUpdate(self):
needUpdate = False
n = self.content["n"]
display = self.content["display"]
calltime = self.content["calltime"]
ctime = datetime.datetime.now()
displayNew = [dep for dep in display if dep[2] > ctime] # new list with only the departures in the future
# update if we loste more then 30% of our departures compared to the last call
if n > 0 and float(len(displayNew)/n) < 0.7:
needUpdate = True
if n == 0 or n < 1:
needUpdate = True
# only update every 5 minutes, not more frequent!
difftime = ctime - calltime
elapsedMin = divmod(difftime.total_seconds(), 60)[0]
if elapsedMin < 5:
needUpdate = False
# update every 15 minutes anyway
if elapsedMin > 15:
needUpdate = True
# now update if you want
if needUpdate:
self.fetchDepartures(self.options['id'])
else:
# save the new display list
self.content = { "calltime": calltime, # time of the last call
"n":n, # number of results in the last call
"display":displayNew} # results of the last call
# save this to the cache
self.saveDisplay(self.content)
'''
def fetchStations(self):
# this function works, but is not used in this script
# it is usefulll to discover the ID of the station you want to display
# url for the RNV stations widgets
url = "http://rnv.the-agent-factory.de:8080/easygo2/rest/regions/rnv/modules/stations/packages/1"
# return the stations to a global variable
stations = self.fetchUrl(url)
return stations
'''
def fetchDepartures(self,hafasID):
print "fetch departures",hafasID
url = 'http://rnv.the-agent-factory.de:8080/easygo2/rest/regions/rnv/modules/stationmonitor/element?hafasID=%s&time=null' % (hafasID)
departureJSON = self.fetchUrl(url)
ctime = datetime.datetime.now() # current time
display = []
# loop trough the results
for dep in departureJSON['listOfDepartures']:
# now we decide weather to show or to hide this ride
show = False
if "all" in self.options['number']:
show = True
elif dep['lineLabel'] in self.options['number']:
show = True
if show == True and "all" not in self.options["direction"] :
if dep['direction'] not in self.options["direction"]:
show = False
# now we know if we want to show this departure:
if show == True :
# this text could be displayed directly
text = "Line %s (%s) in %s Minuten" %(dep['lineLabel'],dep['direction'],dep['differenceTime'])
# transform minutes into absolute time for the cache
departureTime = ctime + datetime.timedelta(0,60*int(dep['differenceTime']))
display.append([dep['lineLabel'],dep['direction'],departureTime])
n = len(display)
# content object to store data
self.content = { "calltime": ctime, # time of the last call
"n":n, # number of results in the last call
"display":display} # results of the last call
# save this to the cache
self.saveDisplay(self.content)
def saveDisplay(self, content):
if(os.path.isfile(self.configPath) == False):
# create empty file
basedir = os.path.dirname(self.configPath)
if not os.path.exists(basedir):
os.makedirs(basedir)
open(self.configPath, 'a').close()
pickle.dump(content, open(self.configPath,"wb"))
return False
def loadDisplay(self):
# read previous saved display lines
if(os.path.isfile(self.configPath)):
self.content = pickle.load( open( self.configPath, "rb" ) )
return self.content
else:
return False
def fetchUrl(self, url):
# fetch the content of the url givven
# passing the correct user agent
user_agent = 'RNV DesktopWidget v1.0.0'
headers = { 'User-Agent' : user_agent }
req = urllib2.Request(url, None, headers)
response = urllib2.urlopen(req)
content = json.loads(response.read())
return content
def ouput(self):
# return everything to the console simple and plain:
n = self.content["n"]
display = self.content["display"]
calltime = self.content["calltime"]
ctime = datetime.datetime.now()
sysinfo = "Last call %s %s" % (calltime.date(), calltime.time())
print(sysinfo)
for dep in display:
minutes = dep[2] - ctime
diffMin = int(divmod(minutes.total_seconds(), 60)[0])+1
if diffMin == 1:
minuten = "Minute"
else:
minuten = "Minuten"
text = "%s %s Line %s (%s) um %s Uhr" %(diffMin, minuten,dep[0],dep[1],dep[2].strftime("%H:%M"))
print (text)
if __name__ == "__main__":
rnv(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment