senec 0.6.2 → 0.7.1

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: 877e39b91e6ff1f4709131aaf96394db590396faad43d8648c88ab90cce1ca3a
4
- data.tar.gz: bffeb00945d5a22ab11936299ec8d716283aa5c8283250c2ec337534f10af690
3
+ metadata.gz: 3fd3ccc37bfaa1b9583583d9d845200844da9f51e4231c3c527729ac7494c790
4
+ data.tar.gz: 2cd5722e55aca66579c755d6fc9490b1f546616048f3a208b4e4fce15d68723c
5
5
  SHA512:
6
- metadata.gz: 966c843b9dfe626d753cf7ceafa1c030479a59c8bd076009e8406252147d09f11f239225b86c628a537eb87b538d5893503c6206579cf0c769d235e442035100
7
- data.tar.gz: ca2fc0dfe72ce5934bc0ebeae1b2ac453f188031dbd0a2c515f135c892bc1d971fec9d81f9b7ccde604affdd0a6d312ee9dabfa349f00bd9df2ec97039e22734
6
+ metadata.gz: e14c8db17de64087e464f587764c29ea3f3d89b92edd95b1bd1a8090d81610dac5bcd5e177620260ef29784a24dc2572fc993dfda33205b7534b7d154c863dd2
7
+ data.tar.gz: c650cbe64f69875e943330752510b525d2215399b6087fcaa46625e6aa3a07f89cf3ca6699d260ac132329b5913a267526afcbc1cbf29f12331c8490f49d8350
@@ -6,6 +6,11 @@ jobs:
6
6
  test:
7
7
  runs-on: ubuntu-latest
8
8
 
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby: ['3.0', '3.1', '3.2']
13
+
9
14
  steps:
10
15
  - name: Checkout the code
11
16
  uses: actions/checkout@v3
@@ -14,7 +19,7 @@ jobs:
14
19
  uses: ruby/setup-ruby@v1
15
20
  with:
16
21
  bundler-cache: true
17
- ruby-version: '3.1'
22
+ ruby-version: ${{ matrix.ruby }}
18
23
 
19
24
  - name: Lint with RuboCop
20
25
  run: bundle exec rubocop
data/.rubocop.yml CHANGED
@@ -4,7 +4,7 @@ require:
4
4
  - rubocop-rake
5
5
 
6
6
  AllCops:
7
- TargetRubyVersion: 2.7
7
+ TargetRubyVersion: 3.0
8
8
  NewCops: enable
9
9
 
10
10
  Style/Documentation:
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020,2022 Georg Ledermann
3
+ Copyright (c) 2020,2023 Georg Ledermann
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ [![Continuous integration](https://github.com/solectrus/senec/actions/workflows/push.yml/badge.svg)](https://github.com/solectrus/senec/actions/workflows/push.yml)
2
+ [![wakatime](https://wakatime.com/badge/user/697af4f5-617a-446d-ba58-407e7f3e0243/project/84ac7dc2-9288-497c-bb20-9c6123d3de66.svg)](https://wakatime.com/badge/user/697af4f5-617a-446d-ba58-407e7f3e0243/project/84ac7dc2-9288-497c-bb20-9c6123d3de66)
3
+
1
4
  # Unofficial Ruby Client for SENEC Home
2
5
 
3
6
  Access your local SENEC Solar Battery Storage System
@@ -20,7 +23,8 @@ $ gem install senec
20
23
  ```ruby
21
24
  require 'senec'
22
25
 
23
- request = Senec::Request.new host: '10.0.1.99'
26
+ senec_ip = '10.0.1.99'
27
+ request = Senec::Request.new host: senec_ip
24
28
 
25
29
  puts "PV production: #{request.inverter_power} W"
26
30
  puts "House power consumption: #{request.house_power} W"
@@ -53,10 +57,22 @@ puts "Measure time: #{Time.at request.measure_time}"
53
57
  # Wallbox charge power: [ 8680, 0, 0, 0 ] W
54
58
  #
55
59
  # Grid power: 315 W
56
- # Current state of the system: CHARGE
60
+ # Current state of the system: 14
57
61
  # Measure time: 2021-10-06 17:50:22 +0200
58
62
  ```
59
63
 
64
+ To get the state name (in German) instead of just the number:
65
+
66
+ ```ruby
67
+ state_names = Senec::State.new(host: senec_ip).names
68
+ request = Senec::Request.new host: senec_ip, state_names: state_names
69
+
70
+ puts request.current_state_name
71
+ # => "LADEN"
72
+ ```
73
+
74
+ The state names are extracted on-the-fly from the JavaScript source code returned by the SENEC web interface.
75
+
60
76
  ## Development
61
77
 
62
78
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -71,6 +87,8 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/solect
71
87
 
72
88
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
73
89
 
90
+ Copyright (c) 2020,2023 Georg Ledermann
91
+
74
92
  ## Code of Conduct
75
93
 
76
94
  Everyone interacting in this project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/solectrus/senec/blob/master/CODE_OF_CONDUCT.md).
@@ -1,100 +1,4 @@
1
- module Senec # rubocop:disable Metrics/ModuleLength
2
- # Taken from https://github.com/mchwalisz/pysenec
3
- STATE_NAMES = {
4
- 0 => 'INITIAL STATE',
5
- 1 => 'ERROR INVERTER COMMUNICATION',
6
- 2 => 'ERROR ELECTRICY METER',
7
- 3 => 'RIPPLE CONTROL RECEIVER',
8
- 4 => 'INITIAL CHARGE',
9
- 5 => 'MAINTENANCE CHARGE',
10
- 6 => 'MAINTENANCE READY',
11
- 7 => 'MAINTENANCE REQUIRED',
12
- 8 => 'MAN. SAFETY CHARGE',
13
- 9 => 'SAFETY CHARGE READY',
14
- 10 => 'FULL CHARGE',
15
- 11 => 'EQUALIZATION: CHARGE',
16
- 12 => 'DESULFATATION: CHARGE',
17
- 13 => 'BATTERY FULL',
18
- 14 => 'CHARGE',
19
- 15 => 'BATTERY EMPTY',
20
- 16 => 'DISCHARGE',
21
- 17 => 'PV + DISCHARGE',
22
- 18 => 'GRID + DISCHARGE',
23
- 19 => 'PASSIVE',
24
- 20 => 'OFF',
25
- 21 => 'OWN CONSUMPTION',
26
- 22 => 'RESTART',
27
- 23 => 'MAN. EQUALIZATION: CHARGE',
28
- 24 => 'MAN. DESULFATATION: CHARGE',
29
- 25 => 'SAFETY CHARGE',
30
- 26 => 'BATTERY PROTECTION MODE',
31
- 27 => 'EG ERROR',
32
- 28 => 'EG CHARGE',
33
- 29 => 'EG DISCHARGE',
34
- 30 => 'EG PASSIVE',
35
- 31 => 'EG PROHIBIT CHARGE',
36
- 32 => 'EG PROHIBIT DISCHARGE',
37
- 33 => 'EMERGANCY CHARGE',
38
- 34 => 'SOFTWARE UPDATE',
39
- 35 => 'NSP ERROR',
40
- 36 => 'NSP ERROR: GRID',
41
- 37 => 'NSP ERROR: HARDWRE',
42
- 38 => 'NO SERVER CONNECTION',
43
- 39 => 'BMS ERROR',
44
- 40 => 'MAINTENANCE: FILTER',
45
- 41 => 'SLEEPING MODE',
46
- 42 => 'WAITING EXCESS',
47
- 43 => 'CAPACITY TEST: CHARGE',
48
- 44 => 'CAPACITY TEST: DISCHARGE',
49
- 45 => 'MAN. DESULFATATION: WAIT',
50
- 46 => 'MAN. DESULFATATION: READY',
51
- 47 => 'MAN. DESULFATATION: ERROR',
52
- 48 => 'EQUALIZATION: WAIT',
53
- 49 => 'EMERGANCY CHARGE: ERROR',
54
- 50 => 'MAN. EQUALIZATION: WAIT',
55
- 51 => 'MAN. EQUALIZATION: ERROR',
56
- 52 => 'MAN: EQUALIZATION: READY',
57
- 53 => 'AUTO. DESULFATATION: WAIT',
58
- 54 => 'ABSORPTION PHASE',
59
- 55 => 'DC-SWITCH OFF',
60
- 56 => 'PEAK-SHAVING: WAIT',
61
- 57 => 'ERROR BATTERY INVERTER',
62
- 58 => 'NPU-ERROR',
63
- 59 => 'BMS OFFLINE',
64
- 60 => 'MAINTENANCE CHARGE ERROR',
65
- 61 => 'MAN. SAFETY CHARGE ERROR',
66
- 62 => 'SAFETY CHARGE ERROR',
67
- 63 => 'NO CONNECTION TO MASTER',
68
- 64 => 'LITHIUM SAFE MODE ACTIVE',
69
- 65 => 'LITHIUM SAFE MODE DONE',
70
- 66 => 'BATTERY VOLTAGE ERROR',
71
- 67 => 'BMS DC SWITCHED OFF',
72
- 68 => 'GRID INITIALIZATION',
73
- 69 => 'GRID STABILIZATION',
74
- 70 => 'REMOTE SHUTDOWN',
75
- 71 => 'OFFPEAK-CHARGE',
76
- 72 => 'ERROR HALFBRIDGE',
77
- 73 => 'BMS: ERROR OPERATING TEMPERATURE',
78
- 74 => 'FACOTRY SETTINGS NOT FOUND',
79
- 75 => 'BACKUP POWER MODE - ACTIVE',
80
- 76 => 'BACKUP POWER MODE - BATTERY EMPTY',
81
- 77 => 'BACKUP POWER MODE ERROR',
82
- 78 => 'INITIALISING',
83
- 79 => 'INSTALLATION MODE',
84
- 80 => 'GRID OFFLINE',
85
- 81 => 'BMS UPDATE NEEDED',
86
- 82 => 'BMS CONFIGURATION NEEDED',
87
- 83 => 'INSULATION TEST',
88
- 84 => 'SELFTEST',
89
- 85 => 'EXTERNAL CONTROL',
90
- 86 => 'ERROR: TEMPERATURESENSOR',
91
- 87 => 'GRID OPERATOR: CHARGE PROHIBITED',
92
- 88 => 'GRID OPERATOR: DISCHARGE PROHIBITED',
93
- 89 => 'SPARE CAPACITY',
94
- 90 => 'SELFTEST ERROR',
95
- 91 => 'EARTH FAULT'
96
- }.freeze
97
-
1
+ module Senec
98
2
  # For a full list of available vars, see http://[IP-of-your-SENEC]/vars.html
99
3
  # Comments taken from https://gist.github.com/smashnet/82ad0b9d7f0ba2e5098e6649ba08f88a
100
4
  BASIC_REQUEST = {
@@ -112,6 +16,9 @@ module Senec # rubocop:disable Metrics/ModuleLength
112
16
  GUI_INVERTER_POWER: '', # PV production (W)
113
17
  STAT_HOURS_OF_OPERATION: '' # Appliance hours of operation
114
18
  },
19
+ PV1: {
20
+ MPP_POWER: '' # List: MPP power (W)
21
+ },
115
22
  TEMPMEASURE: {
116
23
  CASE_TEMP: ''
117
24
  },
data/lib/senec/request.rb CHANGED
@@ -1,12 +1,12 @@
1
- require 'http'
2
- require 'json'
1
+ require 'httparty'
3
2
  require 'senec/value'
4
3
  require 'senec/constants'
5
4
 
6
5
  module Senec
7
6
  class Request
8
- def initialize(host:)
7
+ def initialize(host:, state_names: nil)
9
8
  @host = host
9
+ @state_names = state_names
10
10
  end
11
11
 
12
12
  def house_power
@@ -17,6 +17,10 @@ module Senec
17
17
  get('ENERGY', 'GUI_INVERTER_POWER')
18
18
  end
19
19
 
20
+ def mpp_power
21
+ get('PV1', 'MPP_POWER')
22
+ end
23
+
20
24
  def bat_power
21
25
  get('ENERGY', 'GUI_BAT_DATA_POWER')
22
26
  end
@@ -46,9 +50,13 @@ module Senec
46
50
  end
47
51
 
48
52
  def current_state
49
- state = get('STATISTIC', 'CURRENT_STATE')
53
+ get('STATISTIC', 'CURRENT_STATE')
54
+ end
55
+
56
+ def current_state_name
57
+ throw RuntimeError, 'No state names provided!' unless @state_names
50
58
 
51
- STATE_NAMES[state]
59
+ @state_names[current_state]
52
60
  end
53
61
 
54
62
  def measure_time
@@ -71,15 +79,15 @@ module Senec
71
79
 
72
80
  def response
73
81
  @response ||= begin
74
- res = HTTP.post uri, json: Senec::BASIC_REQUEST
75
- raise Senec::Error, res.status.to_s unless res.status.success?
82
+ res = HTTParty.post(url, body: JSON.generate(Senec::BASIC_REQUEST))
83
+ raise Senec::Error, res.message.to_s unless res.success?
76
84
 
77
- JSON.parse(res.body)
85
+ res.parsed_response
78
86
  end
79
87
  end
80
88
 
81
- def uri
82
- URI.parse("http://#{@host}/lala.cgi")
89
+ def url
90
+ "http://#{@host}/lala.cgi"
83
91
  end
84
92
  end
85
93
  end
@@ -0,0 +1,46 @@
1
+ require 'httparty'
2
+
3
+ module Senec
4
+ class State
5
+ def initialize(host:)
6
+ @host = host
7
+ end
8
+
9
+ attr_reader :host
10
+
11
+ # Extract state names from JavaScript file, which is formatted like this:
12
+ #
13
+ # var system_state_name = {
14
+ # 0: "FIRST STATE",
15
+ # 1: "SECOND STATE",
16
+ # ...
17
+ # };
18
+ def names
19
+ response.match(FILE_REGEX)[0].split("\n").each_with_object({}) do |line, hash|
20
+ key, value = line.match(LINE_REGEX)&.captures
21
+ next unless key && value
22
+
23
+ hash[key.to_i] = value
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ FILE_REGEX = /var system_state_name = \{(.*?)\};/m
30
+ LINE_REGEX = /(\d+)\s*:\s*"(.*)"/
31
+
32
+ def response
33
+ @response ||= begin
34
+ res = HTTParty.get url
35
+ raise Senec::Error, res.message unless res.success?
36
+
37
+ res.body
38
+ end
39
+ end
40
+
41
+ # Use the JavaScript file with German names from the SENEC web interface
42
+ def url
43
+ "http://#{host}/js/DE-de.js"
44
+ end
45
+ end
46
+ end
data/lib/senec/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Senec
2
- VERSION = '0.6.2'.freeze
2
+ VERSION = '0.7.1'.freeze
3
3
  end
data/lib/senec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'senec/version'
2
+ require 'senec/state'
2
3
  require 'senec/request'
3
4
 
4
5
  module Senec
data/senec.gemspec CHANGED
@@ -10,8 +10,8 @@ Gem::Specification.new do |spec|
10
10
  spec.description = 'Access your local SENEC Solar Battery Storage System'
11
11
  spec.homepage = 'https://github.com/solectrus/senec'
12
12
  spec.license = 'MIT'
13
- spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
14
- spec.add_runtime_dependency 'http', '~> 5'
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
14
+ spec.add_runtime_dependency 'httparty'
15
15
 
16
16
  spec.metadata['homepage_uri'] = spec.homepage
17
17
  spec.metadata['source_code_uri'] = 'https://github.com/solectrus/senec'
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: senec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Georg Ledermann
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-13 00:00:00.000000000 Z
11
+ date: 2023-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: http
14
+ name: httparty
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5'
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '5'
26
+ version: '0'
27
27
  description: Access your local SENEC Solar Battery Storage System
28
28
  email:
29
29
  - georg@ledermann.dev
@@ -46,6 +46,7 @@ files:
46
46
  - lib/senec.rb
47
47
  - lib/senec/constants.rb
48
48
  - lib/senec/request.rb
49
+ - lib/senec/state.rb
49
50
  - lib/senec/value.rb
50
51
  - lib/senec/version.rb
51
52
  - senec.gemspec
@@ -65,14 +66,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
66
  requirements:
66
67
  - - ">="
67
68
  - !ruby/object:Gem::Version
68
- version: 2.7.0
69
+ version: 3.0.0
69
70
  required_rubygems_version: !ruby/object:Gem::Requirement
70
71
  requirements:
71
72
  - - ">="
72
73
  - !ruby/object:Gem::Version
73
74
  version: '0'
74
75
  requirements: []
75
- rubygems_version: 3.3.25
76
+ rubygems_version: 3.4.7
76
77
  signing_key:
77
78
  specification_version: 4
78
79
  summary: Unofficial Ruby Client for SENEC Home