pachube-stream 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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