stekker_zaptec 1.1.1 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b93472771162eced218695ad47612b8d001d0b562669077af092de5ac5733d81
4
- data.tar.gz: 78d184fb7979d966be2944c575a70444372555ea78101163f78c8565b5a90cec
3
+ metadata.gz: 91b9631174d32dc32bd0844c8fa0d96bf6b484a39c9318cf25b31fc8f76956a8
4
+ data.tar.gz: ab0ac00f5cc38aca2e70a8a4ad2f954e31e4796a30dac919c8a849862d471bda
5
5
  SHA512:
6
- metadata.gz: d9930219d2b59aea5968498626b3289e40762a83afdfbd177605e4909ec9424cf588ca62f29b6162bce63803f4a4dd4a1ee06631451251cc547fb8678712bfc4
7
- data.tar.gz: 5674b39478d6d644036f4ea5e85794e5331ef0440775d83ee21c46e36fd98e0f77e5b09d5e112f9c0238a7269fbf784a52449f08a55a05c9e8738bf870af2b07
6
+ metadata.gz: 16c452cd49022e999f5e3250804a75359296088a573de565fcc7b8d2e27358c5308fba53eed8d3859efcee0dd0d5202c0224a52f0ea01f2c272d14a439425b9a
7
+ data.tar.gz: 5ef016998af407c8edf1fb1364af5e7a88e0cf2ceea241f4f8e9228308ec63e874a547991ebd3feb4caa8fff46144f72058accde785abba8a3d84902d129d308
@@ -15,7 +15,7 @@ jobs:
15
15
  uses: actions/checkout@v3
16
16
 
17
17
  - name: Install Ruby and gems
18
- uses: ruby/setup-ruby@ee2113536afb7f793eed4ce60e8d3b26db912da4
18
+ uses: ruby/setup-ruby@v1
19
19
  with:
20
20
  bundler-cache: true
21
21
 
data/.rubocop.yml CHANGED
@@ -1,383 +1,346 @@
1
1
  require:
2
- - rubocop-rails
3
2
  - rubocop-rspec
4
3
 
5
4
  AllCops:
6
5
  NewCops: enable
7
- Exclude:
8
- - "vendor/**/*"
9
- - "bin/**/*"
10
- - "node_modules/**/*"
11
- - "db/schema.rb"
12
- - "db/sequent_schema.rb"
13
- - "db/seeds.rb"
14
- - "db/seed/**/*"
15
- - "db/migrate/**/*"
16
-
17
- Rails/EnvironmentVariableAccess:
18
- AllowReads: true
19
-
20
- Rails/HasAndBelongsToMany:
21
- Enabled: false
22
6
 
23
- RSpec/VerifiedDoubles:
7
+ Layout/BeginEndAlignment:
24
8
  Enabled: true
25
- Exclude:
26
- - "spec/components/previews/**/*"
27
9
 
28
- Style/MultilineBlockChain:
29
- Enabled: false
10
+ Layout/BlockAlignment:
11
+ Enabled: true
12
+ EnforcedStyleAlignWith: start_of_block
30
13
 
31
- RSpec/NoExpectationExample:
32
- Exclude:
33
- - "spec/domain/**/*"
14
+ Layout/EmptyLineBetweenDefs:
15
+ Enabled: false
34
16
 
35
- Style/SymbolArray:
36
- EnforcedStyle: brackets
17
+ Layout/EmptyLinesAroundAttributeAccessor:
18
+ Enabled: true
37
19
 
38
- Metrics/ParameterLists:
20
+ Layout/FirstArgumentIndentation:
39
21
  Enabled: true
40
- CountKeywordArgs: false
22
+ EnforcedStyle: consistent
41
23
 
42
- Style/NumericLiterals:
43
- Enabled: false
24
+ Layout/FirstArrayElementIndentation:
25
+ Enabled: true
26
+ EnforcedStyle: consistent
44
27
 
45
- Style/FrozenStringLiteralComment:
46
- EnforcedStyle: never
28
+ Layout/FirstArrayElementLineBreak:
29
+ Enabled: true
47
30
 
48
- Style/GuardClause:
49
- Enabled: false
31
+ Layout/FirstHashElementIndentation:
32
+ Enabled: true
33
+ EnforcedStyle: consistent
50
34
 
51
- Style/ClassAndModuleChildren:
52
- Enabled: false
35
+ Layout/FirstHashElementLineBreak:
36
+ Enabled: true
53
37
 
54
- Lint/DuplicateBranch:
55
- Enabled: false
38
+ Layout/FirstMethodArgumentLineBreak:
39
+ Enabled: true
56
40
 
57
- Lint/RaiseException:
41
+ Layout/FirstParameterIndentation:
58
42
  Enabled: true
43
+ EnforcedStyle: consistent
59
44
 
60
- Rails/SkipsModelValidations:
61
- Enabled: false
45
+ Layout/LineLength:
46
+ Enabled: true
47
+ Max: 115
62
48
 
63
- Lint/StructNewOverride:
49
+ Layout/MultilineArrayBraceLayout:
64
50
  Enabled: true
51
+ EnforcedStyle: new_line
65
52
 
66
- Rails:
53
+ Layout/MultilineArrayLineBreaks:
67
54
  Enabled: true
68
55
 
69
- Style/AccessorGrouping:
56
+ Layout/MultilineHashBraceLayout:
70
57
  Enabled: true
58
+ EnforcedStyle: new_line
71
59
 
72
- Style/IfInsideElse:
73
- Enabled: false
60
+ Layout/MultilineHashKeyLineBreaks:
61
+ Enabled: true
74
62
 
75
- Rails/LexicallyScopedActionFilter:
76
- Enabled: false
63
+ Layout/MultilineMethodArgumentLineBreaks:
64
+ Enabled: true
77
65
 
78
- Style/BisectedAttrAccessor:
66
+ Layout/MultilineMethodCallBraceLayout:
79
67
  Enabled: true
80
- Style/RedundantAssignment:
68
+ EnforcedStyle: new_line
69
+
70
+ Layout/MultilineMethodCallIndentation:
81
71
  Enabled: true
82
- Rails/ActiveRecordCallbacksOrder:
72
+ EnforcedStyle: indented
73
+
74
+ Layout/SpaceAroundMethodCallOperator:
83
75
  Enabled: true
84
- Rails/FindById:
76
+
77
+ Layout/TrailingWhitespace:
78
+ AllowInHeredoc: true
85
79
  Enabled: true
86
- Rails/Inquiry:
87
- Enabled: false
88
- Rails/MailerName:
80
+
81
+ Lint/AmbiguousBlockAssociation:
82
+ Exclude:
83
+ - spec/**/*
84
+
85
+ Lint/BinaryOperatorWithIdenticalOperands:
89
86
  Enabled: true
90
- Rails/MatchRoute:
87
+
88
+ Lint/ConstantDefinitionInBlock:
91
89
  Enabled: true
92
- Rails/NegateInclude:
90
+
91
+ Lint/DeprecatedOpenSSLConstant:
93
92
  Enabled: true
94
- Rails/Pluck:
93
+
94
+ Lint/DuplicateBranch:
95
+ Enabled: false
96
+
97
+ Lint/DuplicateElsifCondition:
95
98
  Enabled: true
96
- Rails/PluckInWhere:
99
+
100
+ Lint/DuplicateRequire:
97
101
  Enabled: true
98
- Rails/RenderInline:
102
+
103
+ Lint/DuplicateRescueException:
99
104
  Enabled: true
100
- Rails/RenderPlainText:
105
+
106
+ Lint/EmptyConditionalBody:
101
107
  Enabled: true
102
- Rails/ShortI18n:
108
+
109
+ Lint/EmptyFile:
103
110
  Enabled: true
104
- Rails/WhereExists:
111
+
112
+ Lint/FloatComparison:
105
113
  Enabled: true
106
- Lint/DuplicateElsifCondition:
114
+
115
+ Lint/IdentityComparison:
107
116
  Enabled: true
108
- Style/ArrayCoercion:
117
+
118
+ Lint/MissingSuper:
109
119
  Enabled: true
110
- Style/CaseLikeIf:
120
+
121
+ Lint/MixedRegexpCaptureTypes:
111
122
  Enabled: true
112
- Style/HashAsLastArrayItem:
123
+
124
+ Lint/OutOfRangeRegexpRef:
113
125
  Enabled: true
114
- Style/HashLikeCase:
126
+
127
+ Lint/RaiseException:
115
128
  Enabled: true
116
- Style/RedundantFileExtensionInRequire:
129
+
130
+ Lint/SelfAssignment:
117
131
  Enabled: true
118
132
 
119
- # Allow emoji in comments
120
- Style/AsciiComments:
121
- Enabled: false
133
+ Lint/StructNewOverride:
134
+ Enabled: true
122
135
 
123
- Naming/PredicateName:
136
+ Lint/TopLevelReturnWithArgument:
124
137
  Enabled: true
125
- ForbiddenPrefixes:
126
- is_
127
138
 
128
- Naming/VariableNumber:
139
+ Lint/TrailingCommaInAttributeDeclaration:
129
140
  Enabled: true
130
- Exclude:
131
- - "spec/**/*"
132
- - "gems/we_connect/spec//**/*"
133
141
 
134
- Style/EmptyMethod:
135
- EnforcedStyle: expanded
142
+ Lint/UnreachableLoop:
143
+ Enabled: true
136
144
 
137
- Style/StringLiterals:
138
- EnforcedStyle: double_quotes
145
+ Lint/UselessAssignment:
146
+ Enabled: true
139
147
 
140
- Style/StringLiteralsInInterpolation:
141
- EnforcedStyle: double_quotes
142
- Exclude:
143
- - "spec/**/*"
148
+ Lint/UselessMethodDefinition:
149
+ Enabled: true
144
150
 
145
- Layout/TrailingWhitespace:
151
+ Lint/UselessTimes:
146
152
  Enabled: true
147
- AllowInHeredoc: true
148
153
 
149
- Metrics/ClassLength:
154
+ Metrics/AbcSize:
150
155
  Enabled: false
151
156
 
152
- Layout/LineLength:
157
+ Metrics/BlockLength:
153
158
  Enabled: true
154
- Max: 115 # Readable github.com diffs
155
159
 
156
- Style/Documentation:
160
+ Metrics/ClassLength:
157
161
  Enabled: false
158
162
 
159
- Layout/EmptyLineBetweenDefs:
160
- Enabled: false
163
+ Metrics/CyclomaticComplexity:
164
+ Max: 42
161
165
 
162
166
  Metrics/MethodLength:
163
167
  Max: 42
164
168
  Exclude:
165
- - "**/spec/**/*"
169
+ - "spec/**/*_spec.rb"
166
170
 
167
- Metrics/BlockLength:
168
- Exclude:
169
- - "**/spec/**/*"
170
- - "config/routes.rb"
171
- - "**/*.gemspec"
172
-
173
- Lint/UselessAssignment:
174
- Exclude:
175
- - "spec/**/*"
171
+ Metrics/ModuleLength:
172
+ Enabled: false
176
173
 
177
- Style/HashEachMethods:
174
+ Metrics/ParameterLists:
175
+ CountKeywordArgs: false
178
176
  Enabled: true
179
177
 
180
- Style/HashTransformKeys:
181
- Enabled: true
178
+ Metrics/PerceivedComplexity:
179
+ Max: 42
182
180
 
183
- Style/HashTransformValues:
181
+ Naming/PredicateName:
184
182
  Enabled: true
183
+ ForbiddenPrefixes: is_
185
184
 
186
- Layout/SpaceAroundMethodCallOperator:
185
+ Naming/VariableNumber:
187
186
  Enabled: true
188
187
 
189
- Style/ExponentialNotation:
190
- Enabled: true
188
+ RSpec/AnyInstance:
189
+ Enabled: false
191
190
 
192
- Layout/EmptyLinesAroundAttributeAccessor:
193
- Enabled: true
191
+ RSpec/DescribeClass:
192
+ Enabled: false
194
193
 
195
- Lint/DeprecatedOpenSSLConstant:
196
- Enabled: true
194
+ RSpec/DescribedClass:
195
+ Enabled: false
197
196
 
198
- Style/SlicingWithRange:
199
- Enabled: true
197
+ RSpec/ExampleLength:
198
+ Enabled: false
200
199
 
201
- Style/IfUnlessModifier:
200
+ RSpec/MultipleExpectations:
202
201
  Enabled: false
203
202
 
204
- Lint/MixedRegexpCaptureTypes:
205
- Enabled: true
203
+ RSpec/NestedGroups:
204
+ Max: 4
206
205
 
207
- Style/RedundantFetchBlock:
208
- Enabled: true
206
+ RSpec/NoExpectationExample:
207
+ Exclude:
208
+ - spec/domain/**/*
209
209
 
210
- Style/RedundantRegexpCharacterClass:
210
+ RSpec/VerifiedDoubles:
211
211
  Enabled: true
212
212
 
213
- Style/RedundantRegexpEscape:
213
+ Style/AccessorGrouping:
214
214
  Enabled: true
215
215
 
216
- Metrics/CyclomaticComplexity:
217
- Max: 42
218
-
219
- Metrics/PerceivedComplexity:
220
- Max: 42
216
+ Style/ArrayCoercion:
217
+ Enabled: true
221
218
 
222
- Style/RescueModifier:
219
+ Style/AsciiComments:
223
220
  Enabled: false
224
221
 
225
- Style/Lambda:
226
- EnforcedStyle: literal
222
+ Style/BisectedAttrAccessor:
223
+ Enabled: true
227
224
 
228
225
  Style/BlockDelimiters:
229
226
  Enabled: true
230
227
 
231
- Style/SingleArgumentDig: # (new in 0.89)
228
+ Style/CaseLikeIf:
232
229
  Enabled: true
233
230
 
234
- Lint/BinaryOperatorWithIdenticalOperands: # (new in 0.89)
235
- Enabled: true
236
- Lint/DuplicateRequire: # (new in 0.90)
237
- Enabled: true
238
- Lint/DuplicateRescueException: # (new in 0.89)
239
- Enabled: true
240
- Lint/EmptyConditionalBody: # (new in 0.89)
241
- Enabled: true
242
- Lint/EmptyFile: # (new in 0.90)
243
- Enabled: true
244
- Lint/FloatComparison: # (new in 0.89)
245
- Enabled: true
246
- Lint/MissingSuper: # (new in 0.89)
247
- Enabled: true
248
- Lint/OutOfRangeRegexpRef: # (new in 0.89)
249
- Enabled: true
250
- Lint/SelfAssignment: # (new in 0.89)
251
- Enabled: true
252
- Lint/TopLevelReturnWithArgument: # (new in 0.89)
253
- Enabled: true
254
- Lint/TrailingCommaInAttributeDeclaration: # (new in 0.90)
255
- Enabled: true
256
- Lint/UnreachableLoop: # (new in 0.89)
257
- Enabled: true
258
- Lint/UselessMethodDefinition: # (new in 0.90)
259
- Enabled: true
260
- Style/CombinableLoops: # (new in 0.90)
261
- Enabled: true
262
- Style/ExplicitBlockArgument: # (new in 0.89)
263
- Enabled: true
264
- Style/GlobalStdStream: # (new in 0.89)
265
- Enabled: true
266
- Style/KeywordParametersOrder: # (new in 0.90)
267
- Enabled: true
268
- Style/OptionalBooleanParameter: # (new in 0.89)
269
- Enabled: true
270
- Style/RedundantSelfAssignment: # (new in 0.90)
271
- Enabled: true
272
- Style/SoleNestedConditional: # (new in 0.89)
273
- Enabled: true
274
- Style/StringConcatenation: # (new in 0.89)
231
+ Style/ClassAndModuleChildren:
232
+ Enabled: false
233
+
234
+ Style/CombinableLoops:
275
235
  Enabled: true
276
236
 
277
- Metrics/ModuleLength:
237
+ Style/Documentation:
278
238
  Enabled: false
279
239
 
280
- Layout/BeginEndAlignment: # (new in 0.91)
240
+ Style/EmptyMethod:
241
+ EnforcedStyle: expanded
242
+
243
+ Style/ExplicitBlockArgument:
281
244
  Enabled: true
282
- Lint/ConstantDefinitionInBlock: # (new in 0.91)
245
+
246
+ Style/ExponentialNotation:
283
247
  Enabled: true
284
- Lint/IdentityComparison: # (new in 0.91)
248
+
249
+ Style/FrozenStringLiteralComment:
250
+ EnforcedStyle: never
251
+
252
+ Style/GlobalStdStream:
285
253
  Enabled: true
286
- Lint/UselessTimes: # (new in 0.91)
254
+
255
+ Style/GuardClause:
256
+ Enabled: false
257
+
258
+ Style/HashAsLastArrayItem:
287
259
  Enabled: true
288
- Rails/AfterCommitOverride: # (new in 2.8)
260
+
261
+ Style/HashEachMethods:
289
262
  Enabled: true
290
- Rails/SquishedSQLHeredocs: # (new in 2.8)
263
+
264
+ Style/HashLikeCase:
291
265
  Enabled: true
292
- Rails/WhereNot: # (new in 2.8)
266
+
267
+ Style/HashTransformKeys:
293
268
  Enabled: true
294
- Metrics/AbcSize:
295
- Enabled: false
296
269
 
297
- Rails/UnknownEnv:
298
- Environments:
299
- - production
300
- - development
301
- - test
302
- - staging
270
+ Style/HashTransformValues:
271
+ Enabled: true
303
272
 
304
- RSpec/DescribeClass:
305
- Enabled: false
306
- RSpec/DescribedClass:
307
- Enabled: false
308
- RSpec/NestedGroups:
309
- Max: 4
310
- RSpec/MultipleExpectations:
273
+ Style/IfInsideElse:
311
274
  Enabled: false
312
- RSpec/ExampleLength:
275
+
276
+ Style/IfUnlessModifier:
313
277
  Enabled: false
314
- RSpec/AnyInstance:
278
+
279
+ Style/KeywordParametersOrder:
280
+ Enabled: true
281
+
282
+ Style/Lambda:
283
+ EnforcedStyle: literal
284
+
285
+ Style/MultilineBlockChain:
315
286
  Enabled: false
316
287
 
317
- # No translations needed in Admin, for now:
318
- Rails/I18nLocaleTexts:
319
- Exclude:
320
- - "app/controllers/admin/**/*"
288
+ Style/NumericLiterals:
289
+ Enabled: false
321
290
 
322
- ##
323
- # Multi-line formatting (hashes)
324
- ##
325
- Layout/FirstHashElementLineBreak:
291
+ Style/OptionalBooleanParameter:
326
292
  Enabled: true
327
293
 
328
- Layout/FirstHashElementIndentation:
294
+ Style/RedundantAssignment:
329
295
  Enabled: true
330
- EnforcedStyle: consistent
331
296
 
332
- Layout/MultilineHashBraceLayout:
297
+ Style/RedundantFetchBlock:
333
298
  Enabled: true
334
- EnforcedStyle: new_line
335
299
 
336
- Layout/MultilineHashKeyLineBreaks:
300
+ Style/RedundantFileExtensionInRequire:
337
301
  Enabled: true
338
302
 
339
- ##
340
- # Multi-line formatting (array)
341
- ##
342
- Layout/FirstArrayElementLineBreak:
303
+ Style/RedundantRegexpCharacterClass:
343
304
  Enabled: true
344
305
 
345
- Layout/FirstArrayElementIndentation:
306
+ Style/RedundantRegexpEscape:
346
307
  Enabled: true
347
- EnforcedStyle: consistent
348
308
 
349
- Layout/MultilineArrayBraceLayout:
309
+ Style/RedundantSelfAssignment:
350
310
  Enabled: true
351
- EnforcedStyle: new_line
352
311
 
353
- Layout/MultilineArrayLineBreaks:
354
- Enabled: true
312
+ Style/RescueModifier:
313
+ Enabled: false
355
314
 
356
- ##
357
- # Multi-line formatting (methods/arguments/blocks)
358
- ##
359
- Layout/FirstMethodArgumentLineBreak:
315
+ Style/SingleArgumentDig:
360
316
  Enabled: true
361
317
 
362
- Layout/FirstArgumentIndentation:
318
+ Style/SlicingWithRange:
363
319
  Enabled: true
364
- EnforcedStyle: consistent
365
320
 
366
- Layout/FirstParameterIndentation:
321
+ Style/SoleNestedConditional:
367
322
  Enabled: true
368
- EnforcedStyle: consistent
369
323
 
370
- Layout/MultilineMethodCallBraceLayout:
324
+ Style/StringConcatenation:
371
325
  Enabled: true
372
- EnforcedStyle: new_line
373
326
 
374
- Layout/MultilineMethodArgumentLineBreaks:
327
+ Style/StringLiterals:
328
+ EnforcedStyle: double_quotes
329
+
330
+ Style/StringLiteralsInInterpolation:
331
+ EnforcedStyle: double_quotes
332
+
333
+ Style/SymbolArray:
334
+ EnforcedStyle: brackets
335
+
336
+ Style/TrailingCommaInArguments:
375
337
  Enabled: true
338
+ EnforcedStyleForMultiline: comma
376
339
 
377
- Layout/MultilineMethodCallIndentation:
340
+ Style/TrailingCommaInArrayLiteral:
378
341
  Enabled: true
379
- EnforcedStyle: indented
342
+ EnforcedStyleForMultiline: comma
380
343
 
381
- Layout/BlockAlignment:
344
+ Style/TrailingCommaInHashLiteral:
382
345
  Enabled: true
383
- EnforcedStyleAlignWith: start_of_block
346
+ EnforcedStyleForMultiline: comma
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.0.2
1
+ 3.2.1
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in zaptec.gemspec
4
4
  gemspec
5
5
 
6
+ gem "gem-release", "~> 2.2"
6
7
  gem "jwt", "~> 2.6"
7
8
  gem "rake", "~> 13.0"
8
9
  gem "rspec", "~> 3.0"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stekker_zaptec (1.1.1)
4
+ stekker_zaptec (1.2.1)
5
5
  activemodel
6
6
  activesupport
7
7
  faraday
@@ -10,17 +10,18 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activemodel (7.0.4.2)
14
- activesupport (= 7.0.4.2)
15
- activesupport (7.0.4.2)
13
+ activemodel (7.0.8)
14
+ activesupport (= 7.0.8)
15
+ activesupport (7.0.8)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
17
  i18n (>= 1.6, < 2)
18
18
  minitest (>= 5.1)
19
19
  tzinfo (~> 2.0)
20
- addressable (2.8.1)
20
+ addressable (2.8.5)
21
21
  public_suffix (>= 2.0.2, < 6.0)
22
22
  ast (2.4.2)
23
- concurrent-ruby (1.2.0)
23
+ base64 (0.1.1)
24
+ concurrent-ruby (1.2.2)
24
25
  crack (0.4.5)
25
26
  rexml
26
27
  diff-lcs (1.5.0)
@@ -49,63 +50,72 @@ GEM
49
50
  faraday-retry (1.0.3)
50
51
  faraday_middleware (1.2.0)
51
52
  faraday (~> 1.0)
53
+ gem-release (2.2.2)
52
54
  hashdiff (1.0.1)
53
- i18n (1.12.0)
55
+ i18n (1.14.1)
54
56
  concurrent-ruby (~> 1.0)
55
57
  json (2.6.3)
56
- jwt (2.6.0)
57
- minitest (5.17.0)
58
+ jwt (2.7.1)
59
+ language_server-protocol (3.17.0.3)
60
+ minitest (5.20.0)
58
61
  multipart-post (2.3.0)
59
- parallel (1.22.1)
60
- parser (3.2.0.0)
62
+ parallel (1.23.0)
63
+ parser (3.2.2.3)
61
64
  ast (~> 2.4.1)
62
- public_suffix (5.0.1)
63
- rack (3.0.4.1)
65
+ racc
66
+ public_suffix (5.0.3)
67
+ racc (1.7.1)
68
+ rack (3.0.8)
64
69
  rainbow (3.1.1)
65
70
  rake (13.0.6)
66
- regexp_parser (2.6.2)
67
- rexml (3.2.5)
71
+ regexp_parser (2.8.1)
72
+ rexml (3.2.6)
68
73
  rspec (3.12.0)
69
74
  rspec-core (~> 3.12.0)
70
75
  rspec-expectations (~> 3.12.0)
71
76
  rspec-mocks (~> 3.12.0)
72
- rspec-core (3.12.0)
77
+ rspec-core (3.12.2)
73
78
  rspec-support (~> 3.12.0)
74
- rspec-expectations (3.12.2)
79
+ rspec-expectations (3.12.3)
75
80
  diff-lcs (>= 1.2.0, < 2.0)
76
81
  rspec-support (~> 3.12.0)
77
- rspec-mocks (3.12.3)
82
+ rspec-mocks (3.12.6)
78
83
  diff-lcs (>= 1.2.0, < 2.0)
79
84
  rspec-support (~> 3.12.0)
80
- rspec-support (3.12.0)
81
- rubocop (1.44.1)
85
+ rspec-support (3.12.1)
86
+ rubocop (1.56.3)
87
+ base64 (~> 0.1.1)
82
88
  json (~> 2.3)
89
+ language_server-protocol (>= 3.17.0)
83
90
  parallel (~> 1.10)
84
- parser (>= 3.2.0.0)
91
+ parser (>= 3.2.2.3)
85
92
  rainbow (>= 2.2.2, < 4.0)
86
93
  regexp_parser (>= 1.8, < 3.0)
87
94
  rexml (>= 3.2.5, < 4.0)
88
- rubocop-ast (>= 1.24.1, < 2.0)
95
+ rubocop-ast (>= 1.28.1, < 2.0)
89
96
  ruby-progressbar (~> 1.7)
90
97
  unicode-display_width (>= 2.4.0, < 3.0)
91
- rubocop-ast (1.24.1)
92
- parser (>= 3.1.1.0)
93
- rubocop-capybara (2.17.0)
98
+ rubocop-ast (1.29.0)
99
+ parser (>= 3.2.1.0)
100
+ rubocop-capybara (2.18.0)
94
101
  rubocop (~> 1.41)
95
- rubocop-rails (2.17.4)
102
+ rubocop-factory_bot (2.23.1)
103
+ rubocop (~> 1.33)
104
+ rubocop-rails (2.21.0)
96
105
  activesupport (>= 4.2.0)
97
106
  rack (>= 1.1)
98
107
  rubocop (>= 1.33.0, < 2.0)
99
- rubocop-rspec (2.18.1)
108
+ rubocop-rspec (2.24.0)
100
109
  rubocop (~> 1.33)
101
110
  rubocop-capybara (~> 2.17)
102
- ruby-progressbar (1.11.0)
111
+ rubocop-factory_bot (~> 2.22)
112
+ ruby-progressbar (1.13.0)
103
113
  ruby2_keywords (0.0.5)
104
- timecop (0.9.6)
114
+ timecop (0.9.8)
105
115
  tzinfo (2.0.6)
106
116
  concurrent-ruby (~> 1.0)
107
117
  unicode-display_width (2.4.2)
108
- webmock (3.18.1)
118
+ webmock (3.19.1)
109
119
  addressable (>= 2.8.0)
110
120
  crack (>= 0.3.2)
111
121
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -118,6 +128,7 @@ PLATFORMS
118
128
  x86_64-linux
119
129
 
120
130
  DEPENDENCIES
131
+ gem-release (~> 2.2)
121
132
  jwt (~> 2.6)
122
133
  rake (~> 13.0)
123
134
  rspec (~> 3.0)
data/README.md CHANGED
@@ -63,3 +63,15 @@ client.state(id, device_type_apollo).online?
63
63
  ## Contributing
64
64
 
65
65
  Bug reports and pull requests are welcome on GitHub at https://github.com/stekker/zaptec.
66
+
67
+ ## Publishing
68
+
69
+ ```bash
70
+ # - bumps the gem version to the next major, minor or patch version.
71
+ # - creates commit for the version bump
72
+ # - tags the commit
73
+ # - pushes the commit and tag
74
+ # - publishes the gem to Rubygems
75
+ bin/release [major|minor|patch]
76
+ # See also https://github.com/svenfuchs/gem-release#gem-bump
77
+ ```
data/bin/release ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ # Read major/minor/patch argument
7
+ version="$1"
8
+
9
+ # Do a pretend version bump to determine what the new version should be
10
+ bumped_version=$(gem bump "$version" --pretend --no-commit | awk '{ print $4 }' | tr -d '[:space:]')
11
+
12
+ # Use ruby to get the root level directory name
13
+ gem_name=$(ruby -e "puts File.basename(Dir.pwd)")
14
+
15
+ # Update version file
16
+ gem bump --version "$bumped_version" --no-commit
17
+
18
+ # Run bundle install to ensure gem version in Gemfile is updated
19
+ bundle install
20
+
21
+ # Stage Gemfile.lock and the version file
22
+ git add Gemfile.lock "lib/$gem_name/version.rb"
23
+
24
+ # Finally create the bump commit
25
+ git commit -m "Bump $gem_name to $bumped_version"
26
+
27
+ # Create a tag, push the commit and tag, and release to Rubygems
28
+ gem bump --version "$bumped_version" --no-commit --tag --push --release
@@ -4,11 +4,15 @@ require "active_model"
4
4
  require "active_support/all"
5
5
 
6
6
  require "zaptec/charger"
7
+ require "zaptec/circuit"
7
8
  require "zaptec/client"
8
9
  require "zaptec/constants"
9
10
  require "zaptec/credentials"
10
11
  require "zaptec/errors"
12
+ require "zaptec/installation"
13
+ require "zaptec/installation_hierarchy"
11
14
  require "zaptec/meter_reading"
15
+ require "zaptec/null_encryptor"
12
16
  require "zaptec/state"
13
17
  require "zaptec/version"
14
18
 
@@ -1,38 +1,14 @@
1
1
  module Zaptec
2
2
  class Charger
3
- attr_reader :id,
4
- :name,
5
- :device_id,
6
- :device_type,
7
- :installation_name,
8
- :installation_id
9
-
10
- def initialize(
11
- id:,
12
- name:,
13
- device_id:,
14
- device_type:,
15
- installation_name:,
16
- installation_id:
17
- )
18
-
19
- @id = id
20
- @name = name
21
- @device_id = device_id
22
- @device_type = device_type
23
- @installation_name = installation_name
24
- @installation_id = installation_id
3
+ def initialize(data)
4
+ @data = data.symbolize_keys
25
5
  end
26
6
 
27
- def self.parse(data)
28
- new(
29
- id: data.fetch("Id"),
30
- name: data.fetch("Name"),
31
- device_id: data.fetch("DeviceId"),
32
- device_type: data.fetch("DeviceType"),
33
- installation_name: data.fetch("InstallationName"),
34
- installation_id: data.fetch("InstallationId")
35
- )
36
- end
7
+ def id = @data.fetch(:Id)
8
+ def name = @data.fetch(:Name)
9
+ def device_id = @data.fetch(:DeviceId)
10
+ def device_type = @data.fetch(:DeviceType)
11
+ def installation_name = @data.fetch(:InstallationName)
12
+ def installation_id = @data.fetch(:InstallationId)
37
13
  end
38
14
  end
@@ -0,0 +1,14 @@
1
+ module Zaptec
2
+ class Circuit
3
+ def initialize(data)
4
+ @data = data.symbolize_keys
5
+ end
6
+
7
+ def id = @data.fetch(:Id)
8
+ def max_current = @data.fetch(:MaxCurrent)
9
+
10
+ def chargers
11
+ @chargers ||= @data.fetch(:Chargers).map { |data| Charger.new(data) }
12
+ end
13
+ end
14
+ end
data/lib/zaptec/client.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  module Zaptec
2
2
  class Client
3
- BASE_URI = "https://api.zaptec.com".freeze
3
+ BASE_URL = "https://api.zaptec.com".freeze
4
4
  USER_ROLE = 1
5
5
  OWNER_ROLE = 2
6
+ TOKENS_CACHE_KEY = "zaptec.auth.tokens".freeze
6
7
 
7
- attr_reader :http_client, :credentials
8
+ attr_reader :credentials
8
9
 
9
10
  delegate :expired?,
10
11
  :access_token,
@@ -12,37 +13,45 @@ module Zaptec
12
13
  to: :credentials,
13
14
  prefix: true
14
15
 
15
- def initialize(credentials: nil)
16
- @credentials = credentials
16
+ def initialize(
17
+ username:,
18
+ password:,
19
+ token_cache: ActiveSupport::Cache::MemoryStore.new,
20
+ encryptor: NullEncryptor.new
21
+ )
22
+ @username = username
23
+ @password = password
24
+ @token_cache = token_cache
25
+ @encryptor = encryptor
26
+ end
17
27
 
18
- @http_client = Faraday.new(url: BASE_URI) do |conn|
19
- conn.request :json
20
- conn.response :json
21
- conn.response :raise_error
22
- end
28
+ # https://zendesk.zaptec.com/hc/en-001/articles/6062673456657-Access-to-Installations-Authentication-for-Third-Parties#lookup-key-0-0
29
+ def grant_access_url(lookup_key:, partner_name:, redirect_url: nil, language: "en")
30
+ query = URI.encode_www_form(partnerName: partner_name, returnUrl: redirect_url, lang: language)
31
+ "https://portal.zaptec.com/#!/access/request/#{lookup_key}?#{query}"
23
32
  end
24
33
 
25
34
  # https://zaptec.com/downloads/ZapChargerPro_Integration.pdf
26
35
  def authorize(username:, password:)
27
36
  raise Errors::ParameterMissing if username.blank? || password.blank?
28
37
 
29
- start = Time.zone.now
38
+ start = Time.current
30
39
 
31
- response = http_client.post(
32
- "#{BASE_URI}/oauth/token",
40
+ response = connection.post(
41
+ "#{BASE_URL}/oauth/token",
33
42
  {
34
- username: username,
35
- password: password,
36
- grant_type: "password"
43
+ username:,
44
+ password:,
45
+ grant_type: "password",
37
46
  }.to_query,
38
47
  {
39
- "Content-Type": "application/x-www-form-urlencoded"
40
- }
48
+ "Content-Type": "application/x-www-form-urlencoded",
49
+ },
41
50
  )
42
51
 
43
52
  @credentials = Zaptec::Credentials.new(
44
53
  response.body["access_token"],
45
- start + response.body["expires_in"].to_f
54
+ start + response.body["expires_in"].to_f,
46
55
  )
47
56
  rescue Faraday::BadRequestError
48
57
  raise Errors::AuthorizationFailed
@@ -53,7 +62,19 @@ module Zaptec
53
62
  get("/api/chargers", { Roles: USER_ROLE | OWNER_ROLE })
54
63
  .body
55
64
  .fetch("Data")
56
- .map { |data| Charger.parse(data) }
65
+ .map { |data| Charger.new(data) }
66
+ end
67
+
68
+ # https://api.zaptec.com/help/index.html#/Installation/get_api_installation__id_
69
+ def get_installation(installation_id)
70
+ get("/api/installation/#{installation_id}")
71
+ .then { |response| Installation.new(response.body) }
72
+ end
73
+
74
+ # https://api.zaptec.com/help/index.html#/Installation/get_api_installation__id__hierarchy
75
+ def get_installation_hierarchy(installation_id)
76
+ get("/api/installation/#{installation_id}/hierarchy")
77
+ .then { |response| InstallationHierarchy.new(response.body) }
57
78
  end
58
79
 
59
80
  # https://api.zaptec.com/help/index.html#/Charger/get_api_chargers__id__state
@@ -62,8 +83,8 @@ module Zaptec
62
83
  .body
63
84
  .to_h do |state|
64
85
  [
65
- Constants.observation_state_id_to_name(state_id: state.fetch("StateId"), device_type: device_type),
66
- state.fetch("ValueAsString", nil)
86
+ Constants.observation_state_id_to_name(state_id: state.fetch("StateId"), device_type:),
87
+ state.fetch("ValueAsString", nil),
67
88
  ]
68
89
  end
69
90
  .then { |data| State.new(data) }
@@ -75,6 +96,22 @@ module Zaptec
75
96
 
76
97
  private
77
98
 
99
+ attr_reader :username, :password
100
+
101
+ def connection
102
+ Faraday.new(url: BASE_URL) do |conn|
103
+ conn.request :json
104
+ conn.response :json
105
+ conn.response :raise_error
106
+ end
107
+ end
108
+
109
+ def authenticated_connection
110
+ connection.tap do |conn|
111
+ conn.request :authorization, "Bearer", access_token
112
+ end
113
+ end
114
+
78
115
  # https://api.zaptec.com/help/index.html#/Charger/post_api_chargers__id__sendCommand__commandId_
79
116
  def send_command(charger_id, command)
80
117
  command_id = Constants.command_to_command_id(command)
@@ -83,29 +120,69 @@ module Zaptec
83
120
  end
84
121
 
85
122
  def get(endpoint, query = {})
86
- require_valid_credentials!
123
+ with_error_handling do
124
+ authenticated_connection.get("#{BASE_URL}#{endpoint}", query)
125
+ end
126
+ end
87
127
 
88
- http_client.get(
89
- "#{BASE_URI}#{endpoint}",
90
- query,
91
- { Authorization: "Bearer #{credentials.access_token}" }
92
- )
128
+ def post(endpoint, body: nil, query: nil)
129
+ with_error_handling do
130
+ authenticated_connection.post("#{BASE_URL}#{endpoint}", body) do |req|
131
+ req.params = query unless query.nil?
132
+ end
133
+ end
93
134
  end
94
135
 
95
- def post(endpoint, body = nil)
96
- require_valid_credentials!
136
+ def with_error_handling
137
+ token_refreshed ||= false
97
138
 
98
- http_client.post(
99
- "#{BASE_URI}#{endpoint}",
100
- body,
101
- { Authorization: "Bearer #{credentials.access_token}" }
102
- )
139
+ yield
140
+ rescue Faraday::UnauthorizedError => e
141
+ if token_refreshed
142
+ raise Errors::RequestFailed.new("Request returned status #{e.response_status}", e.response)
143
+ else
144
+ refresh_access_token!
145
+ token_refreshed = true
146
+
147
+ retry
148
+ end
103
149
  rescue Faraday::Error => e
104
- raise Errors::RequestFailed, "Request returned status #{e.response_status}"
150
+ raise Errors::RequestFailed.new("Request returned status #{e.response_status}", e.response)
151
+ end
152
+
153
+ def access_token
154
+ current_access_token
155
+ .then do |current|
156
+ if current.expired?
157
+ refresh_access_token!
158
+ current_access_token
159
+ else
160
+ current
161
+ end
162
+ end
163
+ .then(&:access_token)
105
164
  end
106
165
 
107
- def require_valid_credentials!
108
- raise Errors::Unauthorized if credentials.blank? || credentials.expired?
166
+ def current_access_token
167
+ encrypted_tokens = @token_cache.fetch(TOKENS_CACHE_KEY) do
168
+ @encryptor.encrypt(request_access_token.to_json, cipher_options: { deterministic: true })
169
+ end
170
+
171
+ plain_text_tokens = @encryptor.decrypt(encrypted_tokens)
172
+ Credentials.parse(JSON.parse(plain_text_tokens))
109
173
  end
174
+
175
+ def refresh_access_token!
176
+ @token_cache.write(
177
+ TOKENS_CACHE_KEY,
178
+ @encryptor.encrypt(request_access_token.to_json, cipher_options: { deterministic: true }),
179
+ expires_in: 1.day,
180
+ )
181
+ rescue Faraday::Error => e
182
+ raise Errors::RequestFailed.new("Request returned status #{e.response_status}", e.response)
183
+ end
184
+
185
+ # https://developer.easee.cloud/reference/post_api-accounts-login
186
+ def request_access_token = authorize(username:, password:)
110
187
  end
111
188
  end
@@ -21,6 +21,22 @@ module Zaptec
21
21
  .fetch(command.to_s) { raise "Unknown command '#{command}'" }
22
22
  end
23
23
 
24
+ def country_id_to_country_code(country_id)
25
+ return if country_id.nil?
26
+
27
+ constants
28
+ .fetch("Countries")
29
+ .fetch(country_id)
30
+ .fetch("Code")
31
+ end
32
+
33
+ def network_type_to_name(network_type)
34
+ constants
35
+ .fetch("NetworkTypes")
36
+ .detect { |_name, type| type == network_type }
37
+ .then { |name, _type| name }
38
+ end
39
+
24
40
  private
25
41
 
26
42
  def device_type_observation_ids(device_type)
@@ -10,5 +10,16 @@ module Zaptec
10
10
  def expired?(at = Time.zone.now)
11
11
  expires_at.nil? || at >= expires_at
12
12
  end
13
+
14
+ def self.parse(data)
15
+ new(
16
+ data.fetch("access_token"),
17
+ Time.zone.at(data.fetch("expires_at")),
18
+ )
19
+ end
20
+
21
+ def as_json(*)
22
+ super.merge("expires_at" => expires_at.to_i)
23
+ end
13
24
  end
14
25
  end
data/lib/zaptec/errors.rb CHANGED
@@ -3,7 +3,14 @@ module Zaptec
3
3
  class Base < StandardError; end
4
4
  class ParameterMissing < Base; end
5
5
  class Unauthorized < Base; end
6
- class RequestFailed < Base; end
6
+ class RequestFailed < Base
7
+ attr_reader :response
8
+
9
+ def initialize(message, response = nil)
10
+ @response = response
11
+ super(message)
12
+ end
13
+ end
7
14
  class AuthorizationFailed < Base; end
8
15
  end
9
16
  end
@@ -0,0 +1,15 @@
1
+ module Zaptec
2
+ class Installation
3
+ def initialize(data)
4
+ @data = data.deep_symbolize_keys
5
+ end
6
+
7
+ def id = @data.fetch(:Id)
8
+ def address = @data[:Address]
9
+ def zip_code = @data[:ZipCode]
10
+ def city = @data[:City]
11
+ def latitude = @data[:Latitude]
12
+ def country_code = Constants.country_id_to_country_code(@data[:CountryId])
13
+ def longitude = @data[:Longitude]
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Zaptec
2
+ class InstallationHierarchy
3
+ def initialize(data)
4
+ @data = data.deep_symbolize_keys
5
+ end
6
+
7
+ def id = @data.fetch(:Id)
8
+ def name = @data.fetch(:Name)
9
+ def network_type = Constants.network_type_to_name(@data.fetch(:NetworkType))
10
+
11
+ def circuits
12
+ @circuits ||= @data.fetch(:Circuits).map { |data| Circuit.new(data) }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Zaptec
2
+ # rubocop:disable Lint/UnusedMethodArgument
3
+ class NullEncryptor
4
+ def encrypt(clear_text, key_provider: nil, cipher_options: {})
5
+ clear_text
6
+ end
7
+
8
+ def decrypt(encrypted_text, key_provider: nil, cipher_options: {})
9
+ encrypted_text
10
+ end
11
+
12
+ def encrypted?(_text)
13
+ false
14
+ end
15
+ end
16
+ # rubocop:enable Lint/UnusedMethodArgument
17
+ end
data/lib/zaptec/state.rb CHANGED
@@ -20,7 +20,7 @@ module Zaptec
20
20
  def online? = @data.fetch(:IsOnline).to_i.positive?
21
21
 
22
22
  def meter_reading
23
- @meter_reading ||= MeterReading.new(reading_kwh: total_charge_power_session, timestamp: Time.zone.now)
23
+ @meter_reading ||= MeterReading.new(reading_kwh: total_charge_power, timestamp: Time.zone.now)
24
24
  end
25
25
 
26
26
  private
@@ -1,3 +1,3 @@
1
1
  module Zaptec
2
- VERSION = "1.1.1".freeze
2
+ VERSION = "1.2.1".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stekker_zaptec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Team Stekker
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-20 00:00:00.000000000 Z
11
+ date: 2023-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -83,15 +83,20 @@ files:
83
83
  - README.md
84
84
  - Rakefile
85
85
  - bin/console
86
+ - bin/release
86
87
  - bin/setup
87
88
  - data/constants.json
88
89
  - lib/stekker_zaptec.rb
89
90
  - lib/zaptec/charger.rb
91
+ - lib/zaptec/circuit.rb
90
92
  - lib/zaptec/client.rb
91
93
  - lib/zaptec/constants.rb
92
94
  - lib/zaptec/credentials.rb
93
95
  - lib/zaptec/errors.rb
96
+ - lib/zaptec/installation.rb
97
+ - lib/zaptec/installation_hierarchy.rb
94
98
  - lib/zaptec/meter_reading.rb
99
+ - lib/zaptec/null_encryptor.rb
95
100
  - lib/zaptec/state.rb
96
101
  - lib/zaptec/version.rb
97
102
  - zaptec.gemspec
@@ -110,14 +115,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
115
  requirements:
111
116
  - - ">="
112
117
  - !ruby/object:Gem::Version
113
- version: 3.0.2
118
+ version: 3.2.1
114
119
  required_rubygems_version: !ruby/object:Gem::Requirement
115
120
  requirements:
116
121
  - - ">="
117
122
  - !ruby/object:Gem::Version
118
123
  version: '0'
119
124
  requirements: []
120
- rubygems_version: 3.2.22
125
+ rubygems_version: 3.4.18
121
126
  signing_key:
122
127
  specification_version: 4
123
128
  summary: Connect to your Zaptec charger