pachube-stream 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "pachube-stream", :path => File.expand_path("..", __FILE__)
4
+ gem "yard"
5
+
6
+ # These are development dependencies
7
+ group :test do
8
+ gem "rake"
9
+ gem "rspec", "2.5.0"
10
+ gem "autotest"
11
+ end
12
+
13
+ gemspec
14
+
15
+
data/README.rdoc ADDED
@@ -0,0 +1,109 @@
1
+ == PachubeStream
2
+
3
+ PachubeStream gives you an API for the Pachube TCP Stream using EventMachine
4
+
5
+ http://api.pachube.com/v2/beta/#tcp-socket-and-websocket-connections
6
+
7
+ == Quickstart
8
+
9
+ require "pachube-stream"
10
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
11
+
12
+ Look at the examples directory for exactly that!
13
+
14
+ == Connection Methods
15
+
16
+ The methods on the connection are what Pachube look for when making a request; this in-turn will
17
+ generate the correct method value in the 'http json'
18
+
19
+ === Example
20
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
21
+ request = connection.subscribe("/feeds/504")
22
+
23
+ Results In the following JSON request
24
+
25
+ {
26
+ "method" : "subscribe",
27
+ "resource" : "/feeds/504",
28
+ "headers" :
29
+ {
30
+ "X-PachubeApiKey" : "API_KEY"
31
+ },
32
+ "token" : "subscribe"
33
+ }
34
+
35
+
36
+ === Subscribe
37
+
38
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
39
+ request = connection.subscribe("/feeds/504")
40
+ request.on_datastream do |response|
41
+ puts response
42
+ end
43
+
44
+ === Unsubscribe
45
+
46
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
47
+ request = connection.unsubscribe("/feeds/504")
48
+ request.on_compelete do |response|
49
+ puts response
50
+ end
51
+
52
+ === Get
53
+
54
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
55
+ request = connection.get("/feeds/504")
56
+ request.on_get do |response|
57
+ puts response
58
+ end
59
+
60
+ === Put
61
+
62
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
63
+ request = connection.put("/feeds/504")
64
+ request.on_complete do |response|
65
+ puts response
66
+ end
67
+
68
+ === Delete
69
+
70
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
71
+ request = connection.delete("/feeds/504")
72
+ request.on_complete do |response|
73
+ puts response
74
+ end
75
+
76
+ === Post
77
+
78
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
79
+ request = connection.post("/feeds/504")
80
+ request.on_complete do |response|
81
+ puts response
82
+ end
83
+
84
+
85
+ The way we make a request is to send json in the format of a HTTP request; you only have
86
+ to give extra options when you want to provide your own headers, params and body etc;
87
+
88
+ Therefore when using the connection Methods
89
+
90
+ When can create this 'http json request' with PachubeStream::HttpRequest passing in a hash
91
+
92
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
93
+ request = connection.put("/feeds/504", PachubeStream::HttpRequest.new(:body => {}, :params => {}, :headers => {}))
94
+
95
+ request.on_complete do |response|
96
+ puts response
97
+ end
98
+
99
+ == Defaults:
100
+
101
+ When creating a connection you can specify the host and port these have defaults
102
+
103
+ host # => beta.pachube.com
104
+ port # => 8081
105
+
106
+
107
+ == Respect
108
+
109
+ Respect goes out to the twitter-stream Gem as one took some concepts form that; nice!
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { ["rspec2"] }
@@ -0,0 +1,32 @@
1
+ $: << 'lib' << '../lib'
2
+ require 'rubygems'
3
+ require 'eventmachine'
4
+ require '../lib/pachube-stream'
5
+
6
+ EM.run do
7
+ connection = PachubeStream::Connection.connect(:api_key => ENV["PACHUBE_API_KEY"])
8
+
9
+ connection.on_reconnect do |timeout, reconnect_retries|
10
+ puts timeout
11
+ puts reconnect_retries
12
+ end
13
+
14
+ connection.on_max_reconnects do |timeout, reconnect_retries|
15
+ puts timeout
16
+ puts reconnect_retries
17
+ end
18
+
19
+ feed = connection.subscribe("/feeds/6643") # random Feed
20
+
21
+ feed.on_datastream do |response|
22
+ puts response
23
+ end
24
+
25
+ feed.on_complete do |response|
26
+ puts response
27
+ end
28
+
29
+ feed.on_error do |response|
30
+ puts response
31
+ end
32
+ end
@@ -0,0 +1,80 @@
1
+ module PachubeStream
2
+ class Client
3
+
4
+ # @param [EventMachine::Connection] conn
5
+ # @param [String] api_key
6
+ # @param [Hash] options defaults {}
7
+ def initialize(conn, api_key, options = {})
8
+ @conn = conn
9
+ @api_key = api_key
10
+ @options = options
11
+ @requests = {}
12
+ end
13
+
14
+ # @param [String] response
15
+ #
16
+ # @return [Hash]
17
+ # @todo refactor ugly as Sin
18
+ def process_data(response)
19
+ parsed_response = parse_response(response)
20
+ status_ok = parsed_response["status"] && parsed_response["status"] != 200
21
+ if request = @requests[parsed_response["token"]]
22
+ if status_ok
23
+ call_block_for_request(request, parsed_response)
24
+ else
25
+ call_error_for_request_block(request, parsed_response)
26
+ end
27
+ else
28
+ if status_ok
29
+ @conn.on_response_block.call(parsed_response) if @conn.on_response_block
30
+ else
31
+ receive_error(parsed_response)
32
+ end
33
+ end
34
+ end
35
+
36
+ # @param [String] response
37
+ #
38
+ # @return [Hash]
39
+ def parse_response(response)
40
+ begin
41
+ Yajl::Parser.parse(response)
42
+ rescue Exception => e
43
+ receive_error("#{e.class}: " + [e.message, e.backtrace].flatten.join("\n\t"))
44
+ @conn.close_connection
45
+ return
46
+ end
47
+ end
48
+
49
+ def receive_error(error)
50
+ @conn.on_error_block.call(error) if @conn.on_error_block
51
+ end
52
+
53
+ # we send the request and also keep the request with the token
54
+ # as its key so we can attach callback to requests
55
+ def send_request(method, resource, html_request = {}, token = nil, &block)
56
+ @request = Request.new(@api_key, method, resource, html_request, token)
57
+ @requests[@request.token] = @request
58
+ @conn.send_data(@request.to_json)
59
+ @request
60
+ end
61
+
62
+ # finds the correct callback based on the token which
63
+ # has the method call in its sig
64
+ def call_block_for_request(request, parsed_response)
65
+ case request.token.gsub(/:.*/, "")
66
+ when "subscribe" && !parsed_response["body"].nil?
67
+ request.on_datastream_block.call(parsed_response) if request.on_datastream_block
68
+ when "get" && !parsed_response["body"].nil?
69
+ request.on_get_block.call(parsed_response) if request.on_get_block
70
+ else
71
+ request.on_complete_block.call(parsed_response) if request.on_complete_block
72
+ end
73
+ end
74
+
75
+ def call_error_for_request_block(request, parsed_response)
76
+ request.on_error_block.call(parsed_response) if request.on_error_block
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,117 @@
1
+ module PachubeStream
2
+ class Connection < EventMachine::Connection
3
+ include RequestMethods
4
+
5
+ NF_RECONNECT_START = 0.25
6
+ NF_RECONNECT_ADD = 0.25
7
+ NF_RECONNECT_MAX = 16
8
+ RECONNECT_MAX = 320
9
+ RETRIES_MAX = 10
10
+
11
+ attr_accessor :options, :on_init_callback, :api_key, :on_response_block, :on_error_block
12
+ attr_accessor :reconnect_callback, :max_reconnects_callback, :nf_last_reconnect, :reconnect_retries
13
+
14
+ # @todo tidy as crap
15
+ def self.connect(options = {})
16
+ api_key = options[:api_key]
17
+ raise ArgumentError.new("You need to supply an API Key") unless api_key
18
+ host = options[:host] || "beta.pachube.com"
19
+ port = options[:port] || 8081
20
+ EventMachine.connect host, port, self, options
21
+ rescue EventMachine::ConnectionError => e
22
+ conn = EventMachine::FailedConnection.new(req)
23
+ conn.error = e.message
24
+ conn.fail
25
+ conn
26
+ end
27
+
28
+ def initialize(options)
29
+ @options = options
30
+ @api_key = options[:api_key]
31
+ @timeout = options[:timeout] || 0
32
+ @reconnect_retries = 0
33
+ @immediate_reconnect = false
34
+ end
35
+
36
+ def client
37
+ @client ||= PachubeStream::Client.new(self, @api_key, @options)
38
+ end
39
+
40
+ def post_init
41
+ set_comm_inactivity_timeout @timeout if @timeout > 0
42
+ @on_inited_callback.call if @on_inited_callback
43
+ end
44
+
45
+ def on_reconnect(&block)
46
+ @reconnect_callback = block
47
+ end
48
+
49
+ def on_max_reconnects(&block)
50
+ @max_reconnects_callback = block
51
+ end
52
+
53
+ def on_response_block(&block)
54
+ @on_response_block = block
55
+ end
56
+
57
+ def on_error_block(&block)
58
+ @on_error_block = block
59
+ end
60
+
61
+ def stop
62
+ @gracefully_closed = true
63
+ close_connection
64
+ end
65
+
66
+ def immediate_reconnect
67
+ @immediate_reconnect = true
68
+ @gracefully_closed = false
69
+ close_connection
70
+ end
71
+
72
+ def unbind
73
+ schedule_reconnect unless @gracefully_closed
74
+ end
75
+
76
+ def receive_data(response)
77
+ client.process_data(response)
78
+ end
79
+
80
+ protected
81
+ def schedule_reconnect
82
+ timeout = reconnect_timeout
83
+ @reconnect_retries += 1
84
+ if (timeout <= RECONNECT_MAX) && (@reconnect_retries <= RETRIES_MAX)
85
+ reconnect_after(timeout)
86
+ else
87
+ @max_reconnects_callback.call(timeout, @reconnect_retries) if @max_reconnects_callback
88
+ end
89
+ end
90
+
91
+ def reconnect_after(timeout)
92
+ @reconnect_callback.call(timeout, @reconnect_retries) if @reconnect_callback
93
+
94
+ if timeout == 0
95
+ reconnect @options[:host], @options[:port]
96
+ else
97
+ EventMachine.add_timer(timeout) do
98
+ reconnect @options[:host], @options[:port]
99
+ end
100
+ end
101
+ end
102
+
103
+ def reconnect_timeout
104
+ if @immediate_reconnect
105
+ @immediate_reconnect = false
106
+ return 0
107
+ end
108
+ if @nf_last_reconnect
109
+ @nf_last_reconnect += NF_RECONNECT_ADD
110
+ else
111
+ @nf_last_reconnect = NF_RECONNECT_START
112
+ end
113
+ [@nf_last_reconnect, NF_RECONNECT_MAX].min
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,15 @@
1
+ module PachubeStream
2
+ class HtmlRequest < Hashie::Dash
3
+
4
+ property :resource
5
+ property :method
6
+ property :headers, :default => {}
7
+ property :token
8
+ property :body
9
+ property :params
10
+
11
+ def api_key=(api_key)
12
+ headers["X-PachubeApiKey"] = api_key
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ module PachubeStream
2
+ module RequestMethods
3
+
4
+ def get(resource, html_request = {}, token = nil, &block)
5
+ client.send_request(:get, resource, html_request = {}, token, &block)
6
+ end
7
+
8
+ def post(resource, html_request = {}, token = nil, &block)
9
+ client.send_request(:post, resource, html_request = {}, token, &block)
10
+ end
11
+
12
+ def put(resource, html_request = {}, token = nil, &block)
13
+ client.send_request(:put, resource, html_request = {}, token, &block)
14
+ end
15
+
16
+ def delete(resource,html_request = {}, token= nil, &block)
17
+ client.send_request(:delete, resource, html_request = {}, token, &block)
18
+ end
19
+
20
+ def subscribe(resource, html_request = {}, token = nil, &block)
21
+ client.send_request(:subscribe, resource, html_request = {}, token, &block)
22
+ end
23
+
24
+ def unsubsribe(resource, html_request = {}, token = nil, &block)
25
+ client.send_request(:unsubsribe, resource, html_request = {}, token, &block)
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,51 @@
1
+ module PachubeStream
2
+ class Request
3
+
4
+ attr_accessor :on_complete_block, :on_datastream_block, :request, :token, :method, :on_error_block, :on_get_block
5
+
6
+ # @param[String] method
7
+ # @param[String] html this means headers and body and resource and params
8
+ # @param[String] token if you wanted to send a specific token
9
+ def initialize(api_key, method, resource, html_request, token = nil)
10
+ @api_key = api_key
11
+ @method = method
12
+ @resource = resource
13
+ @html_request = html_request
14
+ @token = token || generate_token(method)
15
+ generate_html_request(api_key, method, resource, html_request, @token)
16
+ end
17
+
18
+ def on_complete(&block)
19
+ @on_complete_block = block
20
+ end
21
+
22
+ def on_datastream(&block)
23
+ @on_datastream_block = block
24
+ end
25
+
26
+ def on_error(&block)
27
+ @on_error_block = block
28
+ end
29
+
30
+ def on_get(&block)
31
+ @on_get_block = block
32
+ end
33
+
34
+ def to_json
35
+ @request.to_json
36
+ end
37
+
38
+ protected
39
+ def generate_token(method)
40
+ "#{method}:#{UUID.generate}"
41
+ end
42
+
43
+ def generate_html_request(api_key, method, resource, html_request, token)
44
+ @request = HtmlRequest.new(html_request)
45
+ @request.api_key = api_key
46
+ @request[:method] = method
47
+ @request[:resource] = resource
48
+ @request[:token] = token
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module PachubeStream
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,15 @@
1
+ module PachubeStream
2
+ end
3
+
4
+ require 'eventmachine'
5
+ require 'addressable/uri'
6
+ require "hashie"
7
+ require 'yajl'
8
+ require 'json'
9
+ require 'uuid'
10
+ require 'pachube-stream/methods'
11
+ require 'pachube-stream/connection'
12
+ require 'pachube-stream/client'
13
+ require 'pachube-stream/request'
14
+ require 'pachube-stream/html_request'
15
+
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "pachube-stream/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "pachube-stream"
7
+ s.version = PachubeStream::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Hookercookerman"]
10
+ s.email = ["hookercookerman@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Pachube TCP streaming API}
13
+ s.description = %q{Simple Ruby client library for pachube TCP streaming API. Uses EventMachine for connection handling.JSON format only.}
14
+
15
+ s.rubyforge_project = "pachube-stream"
16
+
17
+ s.add_dependency "eventmachine", ">= 1.0.0.beta.3"
18
+ s.add_dependency "addressable", ">= 2.2.3"
19
+ s.add_dependency "hashie", ">= 0.5.1"
20
+ s.add_dependency 'yajl-ruby', '~> 0.8.2'
21
+ s.add_dependency 'uuid', '~> 2.3.2'
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ s.require_paths = ["lib"]
27
+ end
@@ -0,0 +1,6 @@
1
+ {
2
+ "body":"Forbidden: You are not authorized",
3
+ "resource":"/feeds/664334434",
4
+ "token":"subscribe:df279110-4d78-012e-e33e-002332cf7bbe",
5
+ "status":403
6
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "resource":"/feeds/6643",
3
+ "token":"subscribe:a06d6f30-4d78-012e-e33d-002332cf7bbe",
4
+ "status":200
5
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "body":
3
+ {
4
+ "location":
5
+ {
6
+ "lon":-0.0215005874633789,
7
+ "domain":"physical",
8
+ "disposition":"fixed",
9
+ "exposure":"indoor",
10
+ "lat":51.4722148395794
11
+ },
12
+ "title":"CurrentCost meter",
13
+ "datastreams":
14
+ [
15
+ {
16
+ "current_value":"32.2",
17
+ "max_value":"32.3",
18
+ "min_value":"9.3",
19
+ "id":"0",
20
+ "tags":
21
+ [
22
+ "celsius",
23
+ "degrees",
24
+ "temperature"
25
+ ],
26
+ "unit":
27
+ {
28
+ "label":"Celsius",
29
+ "symbol":"C",
30
+ "type":"basicSI"
31
+ },
32
+ "at":"2011-04-20T12:35:42.653484Z"
33
+ },
34
+ {
35
+ "current_value":"309.0",
36
+ "max_value":"12675.0",
37
+ "min_value":"24.0",
38
+ "id":"1",
39
+ "tags":
40
+ [
41
+ "electricity",
42
+ "power",
43
+ "watts"
44
+ ],
45
+ "unit":
46
+ {
47
+ "label":"Watts",
48
+ "symbol":"W",
49
+ "type":"derivedSI"
50
+ },
51
+ "at":"2011-04-20T12:35:42.653484Z"
52
+ }
53
+ ],
54
+ "creator":"http://www.pachube.com/users/sc84647",
55
+ "private":"false",
56
+ "id":6643,
57
+ "version":"1.0.0",
58
+ "updated":"2011-04-20T12:35:42.653484Z",
59
+ "status":"live",
60
+ "feed":"http://api.pachube.com/v2/feeds/6643.json"
61
+ },
62
+ "resource":"/feeds/6643",
63
+ "token":"subscribe:a06d6f30-4d78-012e-e33d-002332cf7bbe"
64
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "headers":
3
+ {
4
+ "X-PachubeApiKey":"testing"
5
+ },
6
+ "method":"subscribe",
7
+ "resource":"/feeds/100",
8
+ "token":"token"
9
+ }
@@ -0,0 +1,106 @@
1
+ # encoding: utf-8
2
+ require File.expand_path("../spec_helper", __FILE__)
3
+
4
+ describe "Pachube" do
5
+ context "on connection" do
6
+ it "should return stream" do
7
+ EM.should_receive(:connect).and_return('TESTING CONNECT')
8
+ stream = PachubeStream::Connection.connect(:api_key => "Testing")
9
+ stream.should == 'TESTING CONNECT'
10
+ end
11
+
12
+ it "should define default properties" do
13
+ EM.should_receive(:connect).with do |host, port, handler, opts|
14
+ host.should == 'beta.pachube.com'
15
+ port.should == 8081
16
+ end
17
+ stream = PachubeStream::Connection.connect(:api_key => "Testing")
18
+ end
19
+ end
20
+
21
+ context "Connection #subscribe" do
22
+ attr_reader :stream
23
+ before(:each) do
24
+ $data_to_send = read_fixture('pachube/subscribe.json')
25
+ $recieved_data = ''
26
+ $close_connection = false
27
+ end
28
+
29
+ it "should send the 'http_request json request' with the method subscribe'" do
30
+ connect_stream do |connection|
31
+ connection.subscribe("/feeds/100", {}, "token")
32
+ end
33
+ Yajl::Parser.parse($recieved_data).should == Yajl::Parser.parse(read_fixture('pachube/subscribe_request.json'))
34
+ end
35
+
36
+ it "should capture response to the on_compelete as that is not a datastream response" do
37
+ connect_stream do |connection|
38
+ subscription = connection.subscribe("/feeds/100", {}, "subscribe:a06d6f30-4d78-012e-e33d-002332cf7bbe")
39
+ subscription.on_complete do |response|
40
+ $data_to_send = read_fixture('pachube/subscribe_data_stream.json')
41
+ response.should eq(Yajl::Parser.parse(read_fixture('pachube/subscribe.json')))
42
+ end
43
+ end
44
+ end
45
+
46
+ it "should send capture response on_datastream for datastream" do
47
+ $data_to_send = read_fixture('pachube/subscribe_data_stream.json')
48
+ connect_stream do |connection|
49
+ subscription = connection.subscribe("/feeds/100", {}, "subscribe:a06d6f30-4d78-012e-e33d-002332cf7bbe")
50
+ subscription.on_datastream do |response|
51
+ response.should eq(Yajl::Parser.parse(read_fixture('pachube/subscribe_data_stream.json')))
52
+ end
53
+ end
54
+ end
55
+
56
+ it "should capture to the on_error for the request when status code other then 200" do
57
+ $data_to_send = read_fixture('pachube/not_authorized.json')
58
+ connect_stream do |connection|
59
+ subscription = connection.subscribe("/feeds/100", {}, "subscribe:a06d6f30-4d78-012e-e33d-002332cf7bbe")
60
+ subscription.on_error do |response|
61
+ response.should eq(Yajl::Parser.parse(read_fixture('pachube/not_authorized.json')))
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ context "network failure" do
68
+ before(:each) do
69
+ $close_connection = true
70
+ $data_to_send = ''
71
+ end
72
+
73
+ it "should reconnect with 0.25 at base" do
74
+ connect_stream do |connection|
75
+ connection.should_receive(:reconnect_after).with(0.25)
76
+ end
77
+ end
78
+
79
+ it "should reconnect with linear timeout" do
80
+ connect_stream do |connection|
81
+ connection.nf_last_reconnect = 1
82
+ connection.should_receive(:reconnect_after).with(1.25)
83
+ end
84
+ end
85
+
86
+ it "should stop reconnecting after 100 times" do
87
+ connect_stream do |connection|
88
+ connection.reconnect_retries = 100
89
+ connection.should_not_receive(:reconnect_after)
90
+ end
91
+ end
92
+
93
+ it "should notify after reconnect limit is reached" do
94
+ timeout, retries = nil, nil
95
+ connect_stream do |connection|
96
+ connection.on_max_reconnects do |t, r|
97
+ timeout, retries = t, r
98
+ end
99
+ connection.reconnect_retries = 100
100
+ end
101
+ timeout.should == 0.25
102
+ retries.should == 101
103
+ end
104
+ end
105
+
106
+ end
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require "bundler"
3
+ Bundler.setup
4
+
5
+ require "pachube-stream"
6
+ Bundler.require(:test)
7
+
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+
11
+ def fixture_path(path)
12
+ File.join(File.dirname(__FILE__), 'fixtures', path)
13
+ end
14
+
15
+ def read_fixture(path)
16
+ File.read(fixture_path(path))
17
+ end
18
+
19
+ Host = "127.0.0.1"
20
+ Port = 9550
21
+
22
+ # == What would be awsome to capture the response tcpdump or something and the replay
23
+ class PachubeServer < EM::Connection
24
+ attr_accessor :data
25
+ def receive_data data
26
+ $recieved_data = data
27
+ send_data $data_to_send
28
+ EventMachine.next_tick {
29
+ close_connection if $close_connection
30
+ }
31
+ end
32
+ end
33
+
34
+ def connect_stream(opts={}, &blk)
35
+ EM.run {
36
+ opts.merge!(:host => Host, :port => Port)
37
+ stop_in = opts.delete(:stop_in) || 0.5
38
+ unless opts[:start_server] == false
39
+ EM.start_server Host, Port, PachubeServer
40
+ end
41
+ @stream = PachubeStream::Connection.connect(:api_key => "testing", :host => Host, :port => Port)
42
+ blk.call(@stream) if blk
43
+ EM.add_timer(stop_in){ EM.stop }
44
+ }
45
+ end
46
+
47
+ Rspec.configure do |config|
48
+ config.mock_with :rspec
49
+ config.filter_run :focus => true
50
+ config.run_all_when_everything_filtered = true
51
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pachube-stream
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 3
9
+ version: 0.0.3
10
+ platform: ruby
11
+ authors:
12
+ - Hookercookerman
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-04-20 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: eventmachine
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ - 0
32
+ - beta
33
+ - 3
34
+ version: 1.0.0.beta.3
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: addressable
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ segments:
46
+ - 2
47
+ - 2
48
+ - 3
49
+ version: 2.2.3
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: hashie
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ - 5
63
+ - 1
64
+ version: 0.5.1
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: yajl-ruby
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ - 8
78
+ - 2
79
+ version: 0.8.2
80
+ type: :runtime
81
+ version_requirements: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ name: uuid
84
+ prerelease: false
85
+ requirement: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ segments:
91
+ - 2
92
+ - 3
93
+ - 2
94
+ version: 2.3.2
95
+ type: :runtime
96
+ version_requirements: *id005
97
+ description: Simple Ruby client library for pachube TCP streaming API. Uses EventMachine for connection handling.JSON format only.
98
+ email:
99
+ - hookercookerman@gmail.com
100
+ executables: []
101
+
102
+ extensions: []
103
+
104
+ extra_rdoc_files: []
105
+
106
+ files:
107
+ - .gitignore
108
+ - Gemfile
109
+ - README.rdoc
110
+ - Rakefile
111
+ - autotest/discover.rb
112
+ - examples/subscribe.rb
113
+ - lib/pachube-stream.rb
114
+ - lib/pachube-stream/client.rb
115
+ - lib/pachube-stream/connection.rb
116
+ - lib/pachube-stream/html_request.rb
117
+ - lib/pachube-stream/methods.rb
118
+ - lib/pachube-stream/request.rb
119
+ - lib/pachube-stream/version.rb
120
+ - pachube-stream.gemspec
121
+ - spec/fixtures/pachube/not_authorized.json
122
+ - spec/fixtures/pachube/subscribe.json
123
+ - spec/fixtures/pachube/subscribe_data_stream.json
124
+ - spec/fixtures/pachube/subscribe_request.json
125
+ - spec/pachube_spec.rb
126
+ - spec/spec_helper.rb
127
+ has_rdoc: true
128
+ homepage: ""
129
+ licenses: []
130
+
131
+ post_install_message:
132
+ rdoc_options: []
133
+
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ segments:
150
+ - 0
151
+ version: "0"
152
+ requirements: []
153
+
154
+ rubyforge_project: pachube-stream
155
+ rubygems_version: 1.3.7
156
+ signing_key:
157
+ specification_version: 3
158
+ summary: Pachube TCP streaming API
159
+ test_files:
160
+ - spec/fixtures/pachube/not_authorized.json
161
+ - spec/fixtures/pachube/subscribe.json
162
+ - spec/fixtures/pachube/subscribe_data_stream.json
163
+ - spec/fixtures/pachube/subscribe_request.json
164
+ - spec/pachube_spec.rb
165
+ - spec/spec_helper.rb