trmnl-api 0.2.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 569d9d6bbfd5690691f558a31079e9837b9c39141c02e5f43e44bd58cfbf2663
4
- data.tar.gz: e77c972a0cebebc856605a9fb3c4b7fc99bb6c475f786900e7eba0e3b508875e
3
+ metadata.gz: db11ea72e435255e8f0aac6ab4a457c019a0a073abf35d4bae0e71c90b395b17
4
+ data.tar.gz: d571107317c9968116e3d3e6d66b73b9155641ebdffe723837cd40b223116e70
5
5
  SHA512:
6
- metadata.gz: 26a8717e1cdd331584bc6f390bfc07ef30b072b2f9a5a406c562fd5eee369576b17b149f762ca4f9e48b0c763891e92618e0823eae384d549392910e917b1e8d
7
- data.tar.gz: 5b9cfef970999778d870a606961a6dd54de4233eb2343a72b07ff11d26729d91652a324a99fda045998d6f706b91cf078e77ba077d047798ce77e058a162cdef
6
+ metadata.gz: 6287bd8712e51994d7e07915f6b3194f48498ca02b062844e19ed54d1c60e3d4b0c063c607cbd99a39efdceec912cb25f58d81b60d23e75bc31866b27adf8bf0
7
+ data.tar.gz: 04e59263fbdcaa32ea0e6eb41375f6007500bd4c34293fc3c4acbb0686457e95fe23f1dac234ecb7f004bba3cb690e0321f4cd271689d39cfa203c6ebe262304
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -174,6 +174,36 @@ client.log token: "secret",
174
174
 
175
175
  You'll either get a 204 No Content or 200 OK response depending on if the device exists or not.
176
176
 
177
+ ==== Models
178
+
179
+ Allows you to obtain the model information for all devices and screens. Example:
180
+
181
+ [source,ruby]
182
+ ----
183
+ client = TRMNL::API::Client.new
184
+ client.models
185
+
186
+ # Success(
187
+ # #<data TRMNL::API::Models::Model
188
+ # name="test",
189
+ # label="Test",
190
+ # description="A test.",
191
+ # colors=2,
192
+ # bit_depth=1,
193
+ # scale_factor=1,
194
+ # rotation=90,
195
+ # mime_type="image/png",
196
+ # width=800,
197
+ # height=480,
198
+ # offset_x=10,
199
+ # offset_y=15,
200
+ # published_at="2025-07-16T18:18:11+00:00"
201
+ # >
202
+ # )
203
+ ----
204
+
205
+ ℹ️ The `scale_factor` can be an integer or float.
206
+
177
207
  ==== Setup
178
208
 
179
209
  Allows you to obtain the setup response for when a new device is setup. You must supply your device's MAC Address as the `id`. Example:
@@ -13,6 +13,7 @@ module TRMNL
13
13
  endpoint_display: :display,
14
14
  endpoint_firmware: :firmware,
15
15
  endpoint_log: :log,
16
+ endpoint_models: :models,
16
17
  endpoint_setup: :setup
17
18
  ]
18
19
 
@@ -21,6 +22,7 @@ module TRMNL
21
22
  endpoint_display: :class,
22
23
  endpoint_firmware: :class,
23
24
  endpoint_log: :class,
25
+ endpoint_models: :class,
24
26
  endpoint_setup: :class
25
27
  ]
26
28
 
@@ -37,6 +39,8 @@ module TRMNL
37
39
 
38
40
  def log(**) = endpoint_log.call(**)
39
41
 
42
+ def models(**) = endpoint_models.call(**)
43
+
40
44
  def setup(**) = endpoint_setup.call(**)
41
45
  end
42
46
  end
@@ -23,6 +23,7 @@ module TRMNL
23
23
  register :current_screen, Contracts::CurrentScreen
24
24
  register :display, Contracts::Display
25
25
  register :firmware, Contracts::Firmware
26
+ register :model, Contracts::Model
26
27
  register :setup, Contracts::Setup
27
28
  end
28
29
 
@@ -30,6 +31,7 @@ module TRMNL
30
31
  register :current_screen, Models::CurrentScreen
31
32
  register :display, Models::Display
32
33
  register :firmware, Models::Firmware
34
+ register :model, Models::Model
33
35
  register :setup, Models::Setup
34
36
  end
35
37
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/schema"
4
+
5
+ module TRMNL
6
+ module API
7
+ module Contracts
8
+ # Validates API response.
9
+ Model = Dry::Schema.JSON do
10
+ required(:data).array(:hash) do
11
+ required(:name).filled :string
12
+ required(:label).filled :string
13
+ required(:description).filled :string
14
+ required(:colors).filled :integer
15
+ required(:bit_depth).filled :integer
16
+ required(:scale_factor) { filled? > int? | float? }
17
+ required(:rotation).filled :integer
18
+ required(:mime_type).filled :string
19
+ required(:width).filled :integer
20
+ required(:height).filled :integer
21
+ required(:offset_x).filled :integer
22
+ required(:offset_y).filled :integer
23
+ required(:published_at).filled :time
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -13,6 +13,7 @@ module TRMNL
13
13
  register(:display) { Display.new }
14
14
  register(:firmware) { Firmware.new }
15
15
  register(:log) { Log.new }
16
+ register(:models) { Model.new }
16
17
  register(:setup) { Setup.new }
17
18
  end
18
19
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "inspectable"
4
+ require "pipeable"
5
+
6
+ module TRMNL
7
+ module API
8
+ module Endpoints
9
+ # Handles API request/response.
10
+ class Model
11
+ include TRMNL::API::Dependencies[
12
+ :requester,
13
+ contract: "contracts.model",
14
+ model: "models.model"
15
+ ]
16
+
17
+ include Inspectable[contract: :class]
18
+ include Pipeable
19
+
20
+ def call
21
+ pipe(
22
+ requester.get("models"),
23
+ try(:parse, catch: JSON::ParserError),
24
+ validate(contract, as: :to_h),
25
+ as(:fetch, :data),
26
+ map { |data| model.for(**data) }
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRMNL
4
+ module API
5
+ module Models
6
+ # Models data for API display responses.
7
+ Model = Struct.new(
8
+ :name,
9
+ :label,
10
+ :description,
11
+ :colors,
12
+ :bit_depth,
13
+ :scale_factor,
14
+ :rotation,
15
+ :mime_type,
16
+ :width,
17
+ :height,
18
+ :offset_x,
19
+ :offset_y,
20
+ :published_at
21
+ ) do
22
+ def self.for(attributes) = new(**attributes)
23
+
24
+ def initialize(**)
25
+ super
26
+ apply_defaults
27
+ freeze
28
+ end
29
+
30
+ def to_json(*) = to_h.to_json(*)
31
+
32
+ private
33
+
34
+ def apply_defaults
35
+ %i[colors bit_depth scale_factor rotation width height offset_x offset_y].each do |name|
36
+ self[name] ||= 0
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -6,9 +6,8 @@ require "http"
6
6
  module TRMNL
7
7
  module API
8
8
  # Provides a low level configurable and monadic API client.
9
- # :reek:DataClump
10
9
  class Requester
11
- include Dependencies[:settings, :http]
10
+ include Dependencies[:settings, :http, :logger]
12
11
  include Dry::Monads[:result]
13
12
 
14
13
  HEADERS = {}.freeze
@@ -26,13 +25,32 @@ module TRMNL
26
25
 
27
26
  attr_reader :settings, :http
28
27
 
29
- # rubocop:todo Metrics/ParameterLists
30
28
  def call method, path, headers, **options
31
29
  http.headers(settings.headers.merge(headers))
32
- .public_send(method, "#{settings.uri}/#{path}", options)
30
+ .public_send(method, uri(path), options)
33
31
  .then { |response| response.status.success? ? Success(response) : Failure(response) }
32
+ rescue HTTP::ConnectionError => error then handle_bad_connection path, error
33
+ rescue HTTP::TimeoutError => error then handle_timeout path, error
34
+ rescue OpenSSL::SSL::SSLError => error then handle_bad_ssl path, error
35
+ end
36
+
37
+ def uri(path) = "#{settings.uri}/#{path}"
38
+
39
+ def handle_bad_connection path, error
40
+ logger.debug { error.message }
41
+ Failure "Unable to connect: #{uri(path).inspect}. Is the network intermittent or down?"
42
+ end
43
+
44
+ def handle_timeout path, error
45
+ logger.debug { error.message }
46
+ Failure "Connection timed out: #{uri(path).inspect}."
47
+ end
48
+
49
+ def handle_bad_ssl path, error
50
+ logger.debug { error.message }
51
+ Failure "Unable to secure connection: #{uri(path).inspect}. " \
52
+ "Is your certificate or SSL valid?"
34
53
  end
35
- # rubocop:enable Metrics/ParameterLists
36
54
  end
37
55
  end
38
56
  end
data/lib/trmnl/api.rb CHANGED
@@ -16,7 +16,7 @@ module TRMNL
16
16
  # Main namespace.
17
17
  module API
18
18
  def self.loader registry = Zeitwerk::Registry
19
- @loader ||= registry.loaders.find { |loader| loader.tag == "trmnl-api" }
19
+ @loader ||= registry.loaders.each.find { |loader| loader.tag == "trmnl-api" }
20
20
  end
21
21
 
22
22
  def self.new(&) = Client.new(&)
data/trmnl-api.gemspec CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "trmnl-api"
5
- spec.version = "0.2.0"
5
+ spec.version = "0.4.0"
6
6
  spec.authors = ["TRMNL"]
7
- spec.email = ["support@usetrmnl.com"]
7
+ spec.email = ["engineering@usetrmnl.com"]
8
8
  spec.homepage = "https://github.com/usetrmnl/trmnl-api"
9
9
  spec.summary = "A monadic TRMNL API client."
10
10
  spec.license = "MIT"
@@ -23,11 +23,11 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.required_ruby_version = "~> 3.4"
25
25
 
26
- spec.add_dependency "cogger", "~> 1.2"
26
+ spec.add_dependency "cogger", "~> 1.4"
27
27
  spec.add_dependency "containable", "~> 1.2"
28
28
  spec.add_dependency "dry-monads", "~> 1.8"
29
29
  spec.add_dependency "dry-schema", "~> 1.14"
30
- spec.add_dependency "http", "~> 5.2"
30
+ spec.add_dependency "http", "~> 5.3"
31
31
  spec.add_dependency "infusible", "~> 4.3"
32
32
  spec.add_dependency "inspectable", "~> 0.3"
33
33
  spec.add_dependency "pipeable", "~> 1.3"
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trmnl-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - TRMNL
@@ -41,14 +41,14 @@ dependencies:
41
41
  requirements:
42
42
  - - "~>"
43
43
  - !ruby/object:Gem::Version
44
- version: '1.2'
44
+ version: '1.4'
45
45
  type: :runtime
46
46
  prerelease: false
47
47
  version_requirements: !ruby/object:Gem::Requirement
48
48
  requirements:
49
49
  - - "~>"
50
50
  - !ruby/object:Gem::Version
51
- version: '1.2'
51
+ version: '1.4'
52
52
  - !ruby/object:Gem::Dependency
53
53
  name: containable
54
54
  requirement: !ruby/object:Gem::Requirement
@@ -97,14 +97,14 @@ dependencies:
97
97
  requirements:
98
98
  - - "~>"
99
99
  - !ruby/object:Gem::Version
100
- version: '5.2'
100
+ version: '5.3'
101
101
  type: :runtime
102
102
  prerelease: false
103
103
  version_requirements: !ruby/object:Gem::Requirement
104
104
  requirements:
105
105
  - - "~>"
106
106
  - !ruby/object:Gem::Version
107
- version: '5.2'
107
+ version: '5.3'
108
108
  - !ruby/object:Gem::Dependency
109
109
  name: infusible
110
110
  requirement: !ruby/object:Gem::Requirement
@@ -162,7 +162,7 @@ dependencies:
162
162
  - !ruby/object:Gem::Version
163
163
  version: '2.7'
164
164
  email:
165
- - support@usetrmnl.com
165
+ - engineering@usetrmnl.com
166
166
  executables: []
167
167
  extensions: []
168
168
  extra_rdoc_files:
@@ -179,6 +179,7 @@ files:
179
179
  - lib/trmnl/api/contracts/current_screen.rb
180
180
  - lib/trmnl/api/contracts/display.rb
181
181
  - lib/trmnl/api/contracts/firmware.rb
182
+ - lib/trmnl/api/contracts/model.rb
182
183
  - lib/trmnl/api/contracts/setup.rb
183
184
  - lib/trmnl/api/dependencies.rb
184
185
  - lib/trmnl/api/endpoints/container.rb
@@ -187,10 +188,12 @@ files:
187
188
  - lib/trmnl/api/endpoints/display.rb
188
189
  - lib/trmnl/api/endpoints/firmware.rb
189
190
  - lib/trmnl/api/endpoints/log.rb
191
+ - lib/trmnl/api/endpoints/model.rb
190
192
  - lib/trmnl/api/endpoints/setup.rb
191
193
  - lib/trmnl/api/models/current_screen.rb
192
194
  - lib/trmnl/api/models/display.rb
193
195
  - lib/trmnl/api/models/firmware.rb
196
+ - lib/trmnl/api/models/model.rb
194
197
  - lib/trmnl/api/models/setup.rb
195
198
  - lib/trmnl/api/requester.rb
196
199
  - trmnl-api.gemspec
@@ -218,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
221
  - !ruby/object:Gem::Version
219
222
  version: '0'
220
223
  requirements: []
221
- rubygems_version: 3.6.9
224
+ rubygems_version: 3.7.1
222
225
  specification_version: 4
223
226
  summary: A monadic TRMNL API client.
224
227
  test_files: []
metadata.gz.sig CHANGED
Binary file