Няма описание http://j1x-huginn.herokuapp.com

public_transport_agent.rb 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. require 'date'
  2. require 'cgi'
  3. module Agents
  4. class PublicTransportAgent < Agent
  5. cannot_receive_events!
  6. description <<-MD
  7. Specify the following user settings:
  8. * stops (array)
  9. * agency (string)
  10. * alert_window_in_minutes (integer)
  11. This Agent generates Events based on NextBus GPS transit predictions. First, select an agency by visiting [http://www.nextbus.com/predictor/agencySelector.jsp](http://www.nextbus.com/predictor/agencySelector.jsp) and finding your transit system. Once you find it, copy the part of the URL after `?a=`. For example, for the San Francisco MUNI system, you would end up on [http://www.nextbus.com/predictor/stopSelector.jsp?a=**sf-muni**](http://www.nextbus.com/predictor/stopSelector.jsp?a=sf-muni) and copy "sf-muni". Put that into this Agent's agency setting.
  12. Next, find the stop tags that you care about. To find the tags for the sf-muni system, for the N route, visit this URL:
  13. [http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni&r=**N**](http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni&r=N)
  14. The tags are listed as tag="1234". Copy that number and add the route before it, separated by a pipe '&#124;' symbol. Once you have one or more tags from that page, add them to this Agent's stop list. E.g,
  15. agency: "sf-muni"
  16. stops: ["N|5221", "N|5215"]
  17. This Agent will generate predictions by requesting a URL similar to the following:
  18. [http://webservices.nextbus.com/service/publicXMLFeed?command=predictionsForMultiStops&a=sf-muni&stops=N&#124;5221&stops=N&#124;5215](http://webservices.nextbus.com/service/publicXMLFeed?command=predictionsForMultiStops&a=sf-muni&stops=N&#124;5221&stops=N&#124;5215)
  19. Finally, set the arrival window that you're interested in. E.g., 5 minutes. Events will be created by the agent anytime a new train or bus comes into that time window.
  20. alert_window_in_minutes: 5
  21. This memory should get cleaned up when timestamp is older than an hour (or something) so that it doesn't fill up all of the Agent's memory.
  22. MD
  23. default_schedule "every_2m"
  24. event_description <<-MD
  25. Events look like this:
  26. { "routeTitle":"N-Judah",
  27. "stopTag":"5215",
  28. "prediction":
  29. {"epochTime":"1389622846689",
  30. "seconds":"3454","minutes":"57","isDeparture":"false",
  31. "affectedByLayover":"true","dirTag":"N__OB4KJU","vehicle":"1489",
  32. "block":"9709","tripTag":"5840086"
  33. }
  34. }
  35. MD
  36. def session
  37. @session ||= Patron::Session.new
  38. @session.connect_timeout = 10
  39. @session.timeout = 60
  40. @session.headers['Accept-Language'] = 'en-us,en;q=0.5'
  41. @session.headers['User-Agent'] = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.12 (KHTML, like Gecko) Chrome/9.0.584.0 Safari/534.12"
  42. @session
  43. end
  44. def check_url
  45. stop_query = URI.encode(options["stops"].collect{|a| "&stops=#{a}"}.join)
  46. "http://webservices.nextbus.com/service/publicXMLFeed?command=predictionsForMultiStops&a=#{options["agency"]}#{stop_query}"
  47. end
  48. def stops
  49. options["stops"].collect{|a| a.split("|").last}
  50. end
  51. def check
  52. page = session.get(check_url)
  53. page = Nokogiri::XML page.body
  54. predictions = page.css("//prediction")
  55. predictions.each do |pr|
  56. parent = pr.parent.parent
  57. vals = {routeTitle: parent["routeTitle"], stopTag: parent["stopTag"]}
  58. if pr["minutes"] && pr["minutes"].to_i < options["alert_window_in_minutes"].to_i
  59. vals = vals.merge Hash.from_xml(pr.to_xml)
  60. if not_already_in_memory?(vals)
  61. create_event(:payload => vals)
  62. add_to_memory(vals)
  63. else
  64. end
  65. end
  66. end
  67. end
  68. def add_to_memory(vals)
  69. self.memory["existing_routes"] ||= []
  70. self.memory["existing_routes"] << {stopTag: vals["stopTag"], tripTag: vals["prediction"]["tripTag"], epochTime: vals["prediction"]["epochTime"], currentTime: Time.now}
  71. end
  72. def not_already_in_memory?(vals)
  73. m = self.memory["existing_routes"]
  74. m.select{|h| h[:stopTag] == vals["stopTag"] &&
  75. h[:tripTag] == vals["prediction"]["tripTag"] &&
  76. h[:epochTime] == vals["prediction"]["epochTime"]
  77. }.count == 0
  78. end
  79. def default_options
  80. {
  81. agency: "sf-muni",
  82. stops: ["N|5221", "N|5215"],
  83. alert_window_in_minutes: 5
  84. }
  85. end
  86. def validate_options
  87. errors.add(:base, 'agency is required') unless options['agency'].present?
  88. errors.add(:base, 'alert_window_in_minutes is required') unless options['alert_window_in_minutes'].present?
  89. errors.add(:base, 'stops are required') unless options['stops'].present?
  90. end
  91. def working?
  92. event_created_within?(2) && !recent_error_logs?
  93. end
  94. end
  95. end