Skip to content

Commit 8ffb55f

Browse files
Merge pull request #501 from virtualdj/feat-scale-division
Allow to divide a register value by a number
2 parents 26036d5 + 75f83d5 commit 8ffb55f

File tree

2 files changed

+133
-119
lines changed

2 files changed

+133
-119
lines changed

custom_components/solarman/parser.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ def try_parse_signed (self, rawData, definition, start, length):
7878
value = (value - maxint) * scale
7979
else:
8080
value = value * scale
81+
82+
if ('scale_division' in definition) and (definition['scale_division'] > 0):
83+
value //= definition['scale_division']
8184

8285
if 'validation' in definition:
8386
if not self.do_validate(title, value, definition['validation']):
@@ -116,6 +119,9 @@ def try_parse_unsigned (self, rawData, definition, start, length):
116119
value = value - definition['offset']
117120

118121
value = value * scale
122+
123+
if ('scale_division' in definition) and (definition['scale_division'] > 0):
124+
value //= definition['scale_division']
119125

120126
if 'validation' in definition:
121127
if not self.do_validate(title, value, definition['validation']):

customization.md

Lines changed: 127 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,127 @@
1-
# Customizing
2-
3-
The hart of this component is the parameter-definition file ex *deye_hybrid.yaml*. By changing the file, the behaviour is totally changed.
4-
5-
NOTE:
6-
In order to leave your customized file intact during upgrades, copy the most relevant yaml file to a file called "custom_parameters.yaml, and set the "lookup_file" option in configuration.yaml to point to it.
7-
8-
~~~ YAML
9-
sensor:
10-
- platform: ...
11-
name: ...
12-
inverter_host: ...
13-
inverter_port: ...
14-
inverter_serial: ...
15-
scan_interval: ...
16-
lookup_file: custom_parameters.yaml
17-
~~~
18-
19-
It has two sections:
20-
21-
## 1. Requests
22-
This section defines the requests that should be issued to the logger each time the component does a parameter update. The list below was created for a DEYE 5kW inverter, and could be customized for other models that are not 100% compatible with this inverter.
23-
24-
~~~ YAML
25-
requests:
26-
- start: 0x0003
27-
end: 0x000E
28-
mb_functioncode: 0x03
29-
- start: 0x003B
30-
end: 0x0070
31-
mb_functioncode: 0x03
32-
- start: 0x0096
33-
end: 0x00C3
34-
mb_functioncode: 0x03
35-
- start: 0x00f4
36-
end: 0x00f8
37-
mb_functioncode: 0x03
38-
39-
~~~
40-
41-
This block specifies that the component should issue three requests to the logger, the first one requesting parameters 0x0003 up to 0x000E, then a second request for parmeters 0x003B up to 0x0070, and the last for parameters 0x000f4 up to 0x00f8. All of the requests will be sent using Modbus Function Code 0x03.
42-
43-
## 2. Parameters
44-
This section defines the induvidual parameter definitions. For example:
45-
46-
~~~ YAML
47-
parameters:
48-
- group: solar
49-
items:
50-
- name: "PV1 Power"
51-
class: "power"
52-
state_class: "measurement"
53-
uom: "W"
54-
scale: 1
55-
rule: 1
56-
registers: [0x00BA]
57-
icon: 'mdi:solar-power'
58-
~~~
59-
60-
### group
61-
The group just groups parameters that belong together. The induvidual parameter-items has to be placed in a group. The *items* parameters contains the parameter definitions that belong in the group.
62-
63-
### Parameter-item
64-
65-
66-
|field||description|
67-
|-|-|-|
68-
|name||The *name* field of the home-assistant entity #|
69-
|class||The *class* field of the home-assistant entity #|
70-
|state_class||The *state_class* field of the home assistant entity ##|
71-
|uom||The *unit_of_measurement* field of the home-assistant entity #|
72-
|icon||The *icon* field of the home-assistant entity #|
73-
|| **The fields below define how the value from the logger is parsed** |
74-
|scale||Scaling factor for the value read from the logger (default: 1)|
75-
|rule||Method to interpret the data from the logger ###|
76-
|mask||A mask to filter only used bit fields. This is especialy useful for flag fields|
77-
|registers||Array of register fields that comprises the value. If the value is placed in a number of registers, this array will contain more than one item.|
78-
|lookup||Defines a key-value pair for values where an integer maps to a string field|
79-
||**The following is optional and could be used, if the inverter delivers sometimes non usable data (e.g. Total Production == 0.0)**|
80-
|validation| ||
81-
||min|Spefifies the minimum value to accept|
82-
||max|Specifies the maximum value to accept|
83-
||invalidate_all| Optional: invalidate complete dataset if specified. If not specified, it will only invalidate the specific parameter|
84-
85-
86-
Example yaml file for the example mentioned above:
87-
88-
~~~ YAML
89-
- name: "Total Production"
90-
class: "energy"
91-
state_class: "total_increasing"
92-
uom: "kWh"
93-
scale: 0.1
94-
rule: 3
95-
registers: [0x003F,0x0040]
96-
icon: 'mdi:solar-power'
97-
validation:
98-
min: 0.1
99-
invalidate_all:
100-
~~~
101-
102-
\# (see) https://developers.home-assistant.io/docs/core/entity/
103-
104-
\## see https://developers.home-assistant.io/docs/core/entity/sensor/#entities-representing-a-total-amount
105-
106-
### The rule field specifies how to interpret the binary data.
107-
108-
| Rule # | Description | Example |
109-
|--------|-----------------------|------------------------------------------------------------------------------------------------------------------------|
110-
| 1 | unsigned 16-bit value | |
111-
| 2 | signed 16 bit value | |
112-
| 3 | unsigned 32 bit value | |
113-
| 4 | signed 32 bit value | |
114-
| 5 | ascii value | |
115-
| 6 | bit field | |
116-
| 7 | Version | |
117-
| 8 | Date Time | |
118-
| 9 | Time | Time value as string<ul><li>Example 1: Register Value 2200 => Time Value: 22:00</li><li>Example 2: Register value: 400 => 04:00</li></ul> |
119-
1+
# Customizing
2+
3+
The heart of this component is the parameter-definition file, such as *deye_hybrid.yaml*. By changing the file, the behaviour is totally changed.
4+
5+
NOTE:
6+
In order to leave your customized file intact during upgrades, copy the most relevant yaml file to a file called `custom_parameters.yaml`, and set the "lookup_file" option in configuration.yaml to point to it (or just select the file in the configuration flow UI).
7+
8+
~~~ YAML
9+
sensor:
10+
- platform: ...
11+
name: ...
12+
inverter_host: ...
13+
inverter_port: ...
14+
inverter_serial: ...
15+
scan_interval: ...
16+
lookup_file: custom_parameters.yaml
17+
~~~
18+
19+
It has two sections:
20+
21+
## 1. Requests
22+
This section defines the requests that should be issued to the logger each time the component does a parameter update. The list below was created for a DEYE 5kW inverter, and could be customized for other models that are not 100% compatible with this inverter.
23+
24+
~~~ YAML
25+
requests:
26+
- start: 0x0003
27+
end: 0x000E
28+
mb_functioncode: 0x03
29+
- start: 0x003B
30+
end: 0x0070
31+
mb_functioncode: 0x03
32+
- start: 0x0096
33+
end: 0x00C3
34+
mb_functioncode: 0x03
35+
- start: 0x00f4
36+
end: 0x00f8
37+
mb_functioncode: 0x03
38+
~~~
39+
40+
This block specifies that the component should issue three requests to the logger, the first one requesting parameters 0x0003 up to 0x000E, then a second request for parmeters 0x003B up to 0x0070, and the last for parameters 0x000f4 up to 0x00f8. All of the requests will be sent using Modbus Function Code 0x03.
41+
42+
The **maximum number** of registers that can be queried using the protocol **for each request is 125** (see [here](https://github.com/jmccrohan/pysolarmanv5/issues/51#issuecomment-1902238661)), but some loggers may get errors like `CRC validation failed` if the length is too much; in that case, reduce the length (`end-start`) by doing multiple requests.
43+
44+
If you get `V5FrameError: V5 frame contains invalid sequence number` errors in the log, it might be caused by concurrency (i.e. more than one client connected to the same logger stick).
45+
46+
## 2. Parameters
47+
This section defines the individual parameter definitions: each parameter creates one sensor in Home Assistant. For example:
48+
49+
~~~ YAML
50+
parameters:
51+
- group: solar
52+
items:
53+
- name: "PV1 Power"
54+
class: "power"
55+
state_class: "measurement"
56+
uom: "W"
57+
scale: 1
58+
rule: 1
59+
registers: [0x00BA]
60+
icon: 'mdi:solar-power'
61+
~~~
62+
63+
The register must be included in the requests of the previous point, otherwise the sensor will have an `Unknown` value in Home Assistant.
64+
65+
Pay attention to the registers order when more than one are required; it could be descending when 2 registers are joint together or not, depending on the inverter.
66+
67+
### Group
68+
The group just groups parameters that belong together. The induvidual parameter-items has to be placed in a group. The *items* parameters contains the parameter definitions that belong in the group.
69+
70+
### Parameter-item
71+
72+
73+
|Field||Description|
74+
|-|-|-|
75+
|name||The *name* field of the home-assistant entity #|
76+
|class||The *class* field of the home-assistant entity #|
77+
|state_class||The *state_class* field of the home-assistant entity ##|
78+
|uom||The *unit_of_measurement* field of the home-assistant entity #|
79+
|icon||The *icon* field of the home-assistant entity #|
80+
|| **The fields below define how the value from the logger is parsed** |
81+
|scale||Scaling factor for the value read from the logger (default: 1)|
82+
|scale_division||If specified, divides the result of the scaling by this number (e.g. if the value of the register is in minutes and you want the home-assistant entity in hours, use `scale_division: 60` and `uom: "h"`)
83+
|rule||Method to interpret the data from the logger (see the table below)|
84+
|mask||A mask to filter only used bit fields; this is especialy useful for flag fields|
85+
|registers||Array of register fields that comprises the value; if the value is placed in a number of registers, this array will contain more than one item (note: order is important)|
86+
|lookup||Defines a key-value pair for values where an integer maps to a string field|
87+
||**The following is optional and could be used, if the inverter delivers sometimes non-usable data (e.g. Total Production == 0.0)**|
88+
|validation| ||
89+
||min|Spefifies the minimum value to accept|
90+
||max|Specifies the maximum value to accept|
91+
||invalidate_all| Optional: invalidate the complete dataset if specified; if not specified, it will only invalidate the specific parameter|
92+
93+
Example yaml file for the mentioned above:
94+
95+
~~~ YAML
96+
- name: "Total Production"
97+
class: "energy"
98+
state_class: "total_increasing"
99+
uom: "kWh"
100+
scale: 0.1
101+
rule: 3
102+
registers: [0x003F,0x0040]
103+
icon: 'mdi:solar-power'
104+
validation:
105+
min: 0.1
106+
invalidate_all:
107+
~~~
108+
109+
\# (see) https://developers.home-assistant.io/docs/core/entity/
110+
111+
\## see https://developers.home-assistant.io/docs/core/entity/sensor/#entities-representing-a-total-amount
112+
113+
### Rule
114+
The `rule` field specifies how to interpret the binary data contained in the register(s).
115+
116+
| Rule # | Description | Example |
117+
|--------|-----------------------|------------------------------------------------------------------------------------------------------------------------|
118+
| 1 | Unsigned 16-bit value | |
119+
| 2 | Signed 16 bit value | |
120+
| 3 | Unsigned 32 bit value | |
121+
| 4 | Signed 32 bit value | |
122+
| 5 | ASCII value | |
123+
| 6 | Bit field | |
124+
| 7 | Version | |
125+
| 8 | Date Time | |
126+
| 9 | Time | Time value as string<ul><li>Example 1: Register Value 2200 => Time Value: 22:00</li><li>Example 2: Register value: 400 => 04:00</li></ul>|
127+

0 commit comments

Comments
 (0)