tibber 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 64eba9e3ecaabcac3c6fa77b2d93bdd0a4808b9399a2094987aebfef332586c2
4
+ data.tar.gz: eca76b85e9d6d79961c27048046ebe4c6d3d42a5d2432367188b50a9ec1bc10c
5
+ SHA512:
6
+ metadata.gz: fe85a0c01428961c7eb6f8ef27192ac4b49877b67d6031f37c9d850886fa5e6919bc9313d994dd9aa37fe733f77200a5be42070f015ec12245d2e4c9847e4839
7
+ data.tar.gz: 9a35eb84167e0f37606ccdce5f8340ed8e4332d856c190643c5a2c5018b6c0ef0a338b272efd1881e8c8923ffd9587ce13aac8990bd6c058e911e853dbed25d6
data/.env.template ADDED
@@ -0,0 +1,2 @@
1
+ # demo token used
2
+ TIBBER_ACCESS_TOKEN=5K4MVS-OjfWhK_4yrjOlFe1F6kJXPVf7eQYggo8ebAE
data/.gitignore ADDED
@@ -0,0 +1,45 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+ /data/
13
+ *.log
14
+ *.txt
15
+ *.json
16
+ *.yml
17
+ .DS_Store
18
+
19
+ # Used by dotenv library to load environment variables.
20
+ .env
21
+
22
+
23
+ ## Documentation cache and generated files:
24
+ /.yardoc/
25
+ /_yardoc/
26
+ /doc/
27
+ /rdoc/
28
+
29
+ ## Environment normalization:
30
+ /.bundle/
31
+ /vendor/bundle
32
+ /lib/bundler/man/
33
+
34
+ # for a library or gem, you might want to ignore these files since the code is
35
+ # intended to run in multiple environments; otherwise, check them in:
36
+ # Gemfile.lock
37
+ # .ruby-version
38
+ # .ruby-gemset
39
+
40
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
41
+ .rvmrc
42
+
43
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
44
+ # .rubocop-https?--*
45
+ Gemfile.lock
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-02-25
4
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in hudu.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # Tibber API
2
+ [![Version](https://img.shields.io/gem/v/tibber.svg)](https://rubygems.org/gems/tibber)
3
+
4
+ This is a wrapper for the Tibber rest API.
5
+
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'tibber'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install tibber
22
+
23
+ ## Usage
24
+
25
+ Before you start making the requests to API provide the endpoint and api key using the configuration wrapping.
26
+
27
+ ```ruby
28
+ require 'tibber'
29
+ require 'logger'
30
+
31
+ # use do block
32
+ Tibber.configure do |config|
33
+ config.access_token = ENV['TIBBER_ACCESS_TOKEN']
34
+ config.logger = Logger.new(TEST_LOGGER)
35
+ end
36
+
37
+ # or configure with options hash
38
+ client = Tibber.client
39
+ client.login
40
+
41
+ ```
42
+
43
+ ## Resources
44
+ ### Authentication
45
+ ```ruby
46
+ # setup
47
+ #
48
+ begin
49
+ client = Tibber.client
50
+ client.login
51
+ rescue Tibber::AuthenticationError => e
52
+ puts "Error logging in tibber api"
53
+ puts e
54
+ end
55
+ ```
56
+
57
+
58
+
59
+ ### Graph QL Data resources
60
+ Endpoint for data related requests
61
+
62
+ ```ruby
63
+ # show todays prices
64
+ prices = client.price_info
65
+
66
+ prices.homes.each do |home|
67
+ puts "Today's prices:"
68
+ home.currentSubscription.priceInfo.today.each do |hour|
69
+ puts "#{hour.startsAt} #{hour.total} #{hour.currency} (#{hour.energy} + #{hour.tax})"
70
+ end
71
+ end
72
+
73
+ ```
74
+
75
+ |Resource|API endpoint|
76
+ |:--|:--|
77
+ |.information | returns `name userId login accountType websocketSubscriptionUrl homes including homes meteringPointData, subscriptions` and `features` |
78
+ |.price_info|price information for all `homes[id,currentSubscription{priceInfo{current,today[],tomorrow[]}}]` |
79
+ |.consumption(home_id, resolution, count)|Array of `home.consumption.nodes[]`: `from to cost unitPrice unitPriceVAT consumption consumptionUnit`|
80
+ |.send_push_notification(title, message, screen_to_open)| send notificartion ot devices and returns `successful` & `pushedToNumberOfDevices`|
81
+
82
+ ## Publishing
83
+
84
+ 1. Update version in [version.rb](lib/tibber/version.rb).
85
+ 2. Add release to [CHANGELOG.md](CHANGELOG.md)
86
+ 3. Commit.
87
+ 4. Test build.
88
+ ```
89
+ > rake build
90
+
91
+ ```
92
+ 5. Release
93
+ ```
94
+ > rake release
95
+
96
+ ## Contributing
97
+
98
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jancotanis/tibber.
99
+
100
+ ## License
101
+
102
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'dotenv'
5
+ require 'rake/testtask'
6
+
7
+ Dotenv.load
8
+
9
+ #system './bin/cc-test-reporter before-build'
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << 'test'
12
+ t.libs << 'lib'
13
+ t.test_files = FileList['test/**/*_test.rb']
14
+ end
15
+
16
+ require 'rubocop/rake_task'
17
+ RuboCop::RakeTask.new
18
+ task default: %i[test rubocop]
19
+ #system './bin/cc-test-reporter after-build'
data/lib/tibber/api.rb ADDED
@@ -0,0 +1,35 @@
1
+ require "wrapi"
2
+ require File.expand_path('request', __dir__)
3
+ require File.expand_path('authorization', __dir__)
4
+
5
+ module Tibber
6
+ # @private
7
+ class API
8
+
9
+ # @private
10
+ attr_accessor *WrAPI::Configuration::VALID_OPTIONS_KEYS
11
+
12
+ # Creates a new API and copies settings from singleton
13
+ def initialize(options = {})
14
+ options = Tibber.options.merge(options)
15
+ WrAPI::Configuration::VALID_OPTIONS_KEYS.each do |key|
16
+ send("#{key}=", options[key])
17
+ end
18
+ end
19
+
20
+ def config
21
+ conf = {}
22
+ WrAPI::Configuration::VALID_OPTIONS_KEYS.each do |key|
23
+ conf[key] = send key
24
+ end
25
+ conf
26
+ end
27
+
28
+ include WrAPI::Connection
29
+ include WrAPI::Request
30
+ include Request::GraphQL
31
+ include WrAPI::Authentication
32
+ include Authentication
33
+
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path('error', __dir__)
2
+
3
+ module Tibber
4
+ # Deals with authentication flow and stores it within global configuration
5
+ module Authentication
6
+
7
+ # Authorize to the Tibber portal using the access_token
8
+ # @see https://developer.tibber.com/docs/guides/calling-api
9
+ def login(options = {})
10
+ raise ConfigurationError, "Accesstoken/api-key not set" unless access_token
11
+ # only bearer token needed
12
+ # will do sanity check if token if valid
13
+ graphql_call('{viewer{name}}')
14
+ rescue GraphQLError => e
15
+ raise AuthenticationError.new e
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,177 @@
1
+ require File.expand_path('api', __dir__)
2
+ require File.expand_path('const', __dir__)
3
+ require File.expand_path('error', __dir__)
4
+
5
+ module Tibber
6
+ # Wrapper for the Tibber REST API
7
+ #
8
+ # @see https://developer.tibber.com/docs/overview
9
+ class Client < API
10
+ attr_accessor :information
11
+
12
+ def initialize(options = {})
13
+ super(options)
14
+ login
15
+ @information = self.info
16
+ rescue GraphQLError => e
17
+ raise AuthenticationError.new e
18
+ end
19
+
20
+ private
21
+ def self.api_endpoint(method, query)
22
+
23
+ # all records
24
+ self.send(:define_method, method) do |params = {}|
25
+ r = graphql_call(query, params)
26
+ end
27
+ end
28
+
29
+ public
30
+ # return device information
31
+ # product_type
32
+ # product_name
33
+ # serial
34
+ # firmware_version
35
+ # api_version
36
+ # devices: HWE-P1, HWE-SKT, HWE-WTR, HWE-KWH1 and SDM230-wifi, HWE-KWH3 and SDM630-wifi
37
+ api_endpoint :info, '
38
+ {
39
+ viewer {
40
+ name
41
+ userId
42
+ login
43
+ accountType
44
+ websocketSubscriptionUrl
45
+ homes {
46
+ id
47
+ timeZone
48
+ appNickname
49
+ appAvatar
50
+ size
51
+ type
52
+ numberOfResidents
53
+ primaryHeatingSource
54
+ hasVentilationSystem
55
+ mainFuseSize
56
+ address {
57
+ address1
58
+ address2
59
+ address3
60
+ city
61
+ postalCode
62
+ country
63
+ latitude
64
+ longitude
65
+ }
66
+ meteringPointData {
67
+ consumptionEan
68
+ gridCompany
69
+ gridAreaCode
70
+ priceAreaCode
71
+ productionEan
72
+ energyTaxType
73
+ vatType
74
+ estimatedAnnualConsumption
75
+ }
76
+ features {
77
+ realTimeConsumptionEnabled
78
+ }
79
+ subscriptions {
80
+ id
81
+ validFrom
82
+ validTo
83
+ status
84
+ priceRating {
85
+ thresholdPercentages {
86
+ high low
87
+ }
88
+ hourly {
89
+ minEnergy maxEnergy
90
+ minTotal maxTotal
91
+ currency
92
+ }
93
+ daily {
94
+ minEnergy maxEnergy
95
+ minTotal maxTotal
96
+ currency
97
+ }
98
+ monthly {
99
+ minEnergy maxEnergy
100
+ minTotal maxTotal
101
+ currency
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }'
108
+ api_endpoint :price_info, '
109
+ {
110
+ viewer {
111
+ homes {
112
+ id
113
+ currentSubscription{
114
+ priceInfo{
115
+ current{
116
+ startsAt
117
+ total
118
+ energy
119
+ tax
120
+ currency
121
+ }
122
+ today {
123
+ startsAt
124
+ total
125
+ energy
126
+ tax
127
+ currency
128
+ }
129
+ tomorrow {
130
+ startsAt
131
+ total
132
+ energy
133
+ tax
134
+ currency
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }'
141
+ api_endpoint:_send_push_notification, '
142
+ mutation {
143
+ sendPushNotification(input: {
144
+ title: "%{title}",
145
+ message: "%{message}",
146
+ screenToOpen: %{screen_to_open}
147
+ }){
148
+ successful
149
+ pushedToNumberOfDevices
150
+ }
151
+ }'
152
+ def send_push_notification(title, message, screen_to_open)
153
+ _send_push_notification({ title: title, message: message, screen_to_open: screen_to_open }).sendPushNotification
154
+ end
155
+ api_endpoint :_consumption, '
156
+ {
157
+ viewer {
158
+ home(id:"%{id}") {
159
+ consumption(resolution: %{resolution}, last: %{count}) {
160
+ nodes {
161
+ from
162
+ to
163
+ cost
164
+ unitPrice
165
+ unitPriceVAT
166
+ consumption
167
+ consumptionUnit
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }'
173
+ def consumption(home_id, resolution, count)
174
+ _consumption({ id: home_id, resolution: resolution, count: count })
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,22 @@
1
+
2
+ module Tibber
3
+ class Enum
4
+ def self.enum(array)
5
+ array.each do |c|
6
+ const_set c,c
7
+ end
8
+ end
9
+ end
10
+ class Screens < Enum
11
+ enum %w[HOME REPORTS CONSUMPTION COMPARISON DISAGGREGATION HOME_PROFILE CUSTOMER_PROFILE METER_READING NOTIFICATIONS INVOICES]
12
+ end
13
+ class Resolution < Enum
14
+ enum %w[HOURLY DAILY WEEKLY MONTHLY ANNUAL]
15
+ end
16
+ class HomeType < Enum
17
+ enum %w[APARTMENT ROWHOUSE HOUSE COTTAGE]
18
+ end
19
+ class Avatar < Enum
20
+ enum %w[APARTMENT ROWHOUSE FLOORHOUSE1 FLOORHOUSE2 FLOORHOUSE3 COTTAGE CASTLE]
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module Tibber
2
+
3
+ # Generic error to be able to rescue all Hudu errors
4
+ class TibberError < StandardError; end
5
+
6
+ # GraphQL returns error
7
+ class GraphQLError < TibberError; end
8
+
9
+ # GraphQL returns error
10
+ class ConfigurationError < TibberError; end
11
+
12
+ # Issue authenticting
13
+ class AuthenticationError < TibberError; end
14
+
15
+ end
@@ -0,0 +1,37 @@
1
+ require 'faraday'
2
+
3
+ module Tibber
4
+ # Deals with requests
5
+ module Request
6
+
7
+ # JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol. Primarily this
8
+ # specification defines several data structures and the rules around their processing. It is
9
+ # transport agnostic in that the concepts can be used within the same process, over sockets, over
10
+ # http, or in many various message passing environments. It uses JSON (RFC 4627) as data format.
11
+ #
12
+ # https://www.jsonrpc.org/specification
13
+ module GraphQL
14
+
15
+ def graphql_call(query, params = nil)
16
+ query = (query % params) if params && params.size > 0
17
+ options = {
18
+ "query": query
19
+ }
20
+ result = post( '', options )
21
+ raise GraphQLError.new(result.body['errors']) if result.body['errors']
22
+ data = result.body['data']
23
+ WrAPI::Request::Entity.create(data['viewer'] ? data['viewer'] : data)
24
+
25
+ rescue Faraday::BadRequestError => e
26
+ body = e.response[:body]
27
+ if body && body['errors']
28
+ error = body['errors']
29
+ else
30
+ error = e.to_s
31
+ end
32
+ raise GraphQLError.new(error)
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tibber
4
+ VERSION = '0.1.0'
5
+ end
data/lib/tibber.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "wrapi"
2
+ require File.expand_path('tibber/client', __dir__)
3
+ require File.expand_path('tibber/version', __dir__)
4
+
5
+ module Tibber
6
+ extend WrAPI::Configuration
7
+ extend WrAPI::RespondTo
8
+
9
+ DEFAULT_UA = "Ruby Tibber API client #{Tibber::VERSION}".freeze
10
+ DEFAULT_ENDPOINT = 'https://api.tibber.com/v1-beta/gql'.freeze
11
+ #
12
+ # @return [Hudu::Client]
13
+ def self.client(options = {})
14
+ Tibber::Client.new({ user_agent: DEFAULT_UA, endpoint: DEFAULT_ENDPOINT }.merge(options))
15
+ end
16
+
17
+ def self.reset
18
+ super
19
+ self.endpoint = nil
20
+ self.user_agent = DEFAULT_UA
21
+ self.endpoint = DEFAULT_ENDPOINT
22
+ end
23
+ end
data/tibber.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/tibber/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'tibber'
7
+ s.version = Tibber::VERSION
8
+ s.authors = ['Janco Tanis']
9
+ s.email = 'gems@jancology.com'
10
+ s.license = 'MIT'
11
+
12
+ s.summary = 'A Ruby wrapper for the Tibber APIs (readonly)'
13
+ s.homepage = 'https://rubygems.org/gems/tibber'
14
+
15
+ s.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
16
+
17
+ s.metadata['homepage_uri'] = s.homepage
18
+ s.metadata['source_code_uri'] = 'https://github.com/jancotanis/tibber'
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ s.files = Dir.chdir(File.expand_path(__dir__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
24
+ end
25
+ s.bindir = 'exe'
26
+ s.executables = s.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
+ s.require_paths = ['lib']
28
+
29
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
+ s.platform = Gem::Platform::RUBY
31
+ s.add_runtime_dependency 'faraday'
32
+ s.add_runtime_dependency 'wrapi', ">= 0.3.0"
33
+ s.add_development_dependency 'dotenv'
34
+ s.add_development_dependency 'minitest'
35
+ s.add_development_dependency 'simplecov'
36
+ s.add_development_dependency 'rubocop'
37
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tibber
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Janco Tanis
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-02-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: wrapi
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: dotenv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email: gems@jancology.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - ".env.template"
104
+ - ".gitignore"
105
+ - CHANGELOG.md
106
+ - Gemfile
107
+ - README.md
108
+ - Rakefile
109
+ - lib/tibber.rb
110
+ - lib/tibber/api.rb
111
+ - lib/tibber/authorization.rb
112
+ - lib/tibber/client.rb
113
+ - lib/tibber/const.rb
114
+ - lib/tibber/error.rb
115
+ - lib/tibber/request.rb
116
+ - lib/tibber/version.rb
117
+ - tibber.gemspec
118
+ homepage: https://rubygems.org/gems/tibber
119
+ licenses:
120
+ - MIT
121
+ metadata:
122
+ homepage_uri: https://rubygems.org/gems/tibber
123
+ source_code_uri: https://github.com/jancotanis/tibber
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 2.4.0
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubygems_version: 3.2.12
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: A Ruby wrapper for the Tibber APIs (readonly)
143
+ test_files: []