Skip to content

Commit 0afa7dc

Browse files
committed
fix: fill profile implements
1 parent 0e0cf78 commit 0afa7dc

10 files changed

Lines changed: 334 additions & 158 deletions

File tree

β€ŽREADME.mdβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ The blueprint is an entity containing all aspects pertaining to device integrati
4646
- [`manifest.yml`](https://developers.enapter.com/docs/reference) describes your device interfaces (telemetry it sends, commands it executes, alerts it raises);
4747
- `firmware.lua` implements these interfaces for the specific piece of hardware using the [Lua](https://www.lua.org) programming language and high-level platform APIs.
4848

49+
Blueprints can implement [profiles](https://github.com/Enapter/profiles) β€” standardized interfaces that define common telemetry, properties, and commands for specific device categories (e.g. battery inverters, PV inverters). When a blueprint declares a profile in its `implements` section, it must provide all telemetry defined by that profile with matching types and enum values.
50+
4951
There are two types of hardware that can run your blueprint:
5052

5153
- a physical [Enapter UCM](https://handbook.enapter.com/modules/modules.html) that implements communication through [RS-485](https://handbook.enapter.com/modules/ENP-RS485/ENP-RS485.html), [CAN](https://handbook.enapter.com/modules/ENP-CAN/ENP-CAN.html), your own hardware based on [UCM Kit](https://go.enapter.com/ucmkit-enpkit) and other standards,

β€Žbattery_inverters/sma_sunny_island_v3/manifest.ymlβ€Ž

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,14 @@ properties:
7373
- flow
7474
- sodium_based
7575
- other
76+
battery_nominal_voltage:
77+
display_name: Battery Nominal Voltage
78+
description: Nominal DC bus voltage of the battery system.
79+
type: float
80+
unit: V
7681
battery_nameplate_capacity:
7782
display_name: Battery Nameplate Capacity
78-
type: float
83+
type: integer
7984
unit: Wh
8085
country_code:
8186
display_name: Country Code
@@ -91,59 +96,91 @@ telemetry:
9196
status:
9297
display_name: Status
9398
type: string
94-
description: Current operational status of the inverter
9599
enum:
96-
"off":
97-
display_name: "Off"
98-
color: purple-lighter
99-
description: Inverter is switched off
100+
- standby
101+
- fault
102+
- waiting_pv_voltage
103+
- start
104+
- shutdown
105+
- waiting_utilities
106+
- bolted
107+
- standalone
108+
- derating
109+
- mpp
110+
- "off"
111+
- stop
112+
- const_voltage
113+
- warning
114+
- run
115+
inverter_status:
116+
display_name: Inverter Status
117+
type: string
118+
description: Current operational status of the inverter.
119+
enum:
120+
idle:
121+
display_name: Idle
122+
description: >
123+
Inverter is powered and ready to operate but is not converting power.
124+
It will not start until commanded by a user or a rule.
100125
standby:
101126
display_name: Standby
102-
color: blue
103127
description: >
104-
Inverter is in standby mode waiting for startup conditions.
128+
Inverter is not converting power but will autonomously resume
129+
operation when conditions are met. No command is required.
105130
starting:
106131
display_name: Starting
107-
color: pink-light
108-
description: Inverter is going through startup procedure
132+
description: >
133+
Inverter is executing its startup sequence.
109134
operating:
110135
display_name: Operating
111-
color: cyan
112-
description: Inverter is actively operating
113-
shutting_down:
114-
display_name: Shutting Down
115-
color: pink-light
116-
description: Inverter is going through shutdown procedure
136+
description: >
137+
Inverter is actively converting power at its operating setpoint.
138+
throttled:
139+
display_name: Throttled
140+
description: >
141+
Inverter is operating at reduced power output due to an external
142+
constraint or internal condition.
143+
stopping:
144+
display_name: Stopping
145+
description: >
146+
Inverter is executing a controlled stop sequence.
117147
fault:
118148
display_name: Fault
119-
color: red
120-
description: Inverter has detected a fault and is not operating
149+
description: >
150+
Inverter has detected a condition that prevents normal operation.
151+
Operator attention is required before the device can resume.
152+
maintenance:
153+
display_name: Maintenance
154+
description: >
155+
Inverter is in a maintenance or configuration mode.
156+
battery_charge_status:
157+
display_name: Battery Charge Status
158+
type: string
159+
description: Current charge direction or mode of the battery.
160+
implements:
161+
- lib.energy.battery.charge_status.battery_charge_status
162+
enum:
163+
idle:
164+
display_name: Idle
165+
description: Battery is not charging or discharging.
166+
charging:
167+
display_name: Charging
168+
description: Battery is actively absorbing energy.
169+
discharging:
170+
display_name: Discharging
171+
description: Battery is actively delivering energy.
172+
float:
173+
display_name: Float
174+
description: >
175+
Battery is fully charged and receiving trickle current to
176+
maintain full state of charge.
121177
health:
122178
display_name: Health Status
123179
type: string
124180
enum:
125181
- ok
126182
- warning
127183
- fault
128-
operating_status:
129-
display_name: Operating Status
130-
type: string
131-
enum:
132-
- standby
133-
- fault
134-
- waiting_pv_voltage
135-
- start
136-
- shutdown
137-
- waiting_utilities
138-
- bolted
139-
- standalone
140-
- derating
141-
- mpp
142-
- "off"
143-
- stop
144-
- const_voltage
145-
- warning
146-
- run
147184
recom_action:
148185
display_name: Recommended Action
149186
type: string
@@ -251,10 +288,11 @@ telemetry:
251288
ac_power_factor:
252289
display_name: AC Power Factor
253290
type: float
291+
unit: "1"
254292
residual_current:
255293
display_name: Residual Current
256294
type: float
257-
unit: A
295+
unit: mA
258296
implements: lib.energy.inverter.residual_current.inverter_residual_current
259297
internal_temperature:
260298
display_name: Internal Temperature

β€Žbattery_inverters/sma_sunny_island_v3/src/main.luaβ€Ž

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ function send_properties()
5555
properties.inverter_nameplate_capacity = 8000
5656
properties.grid_mode = 'off_grid'
5757
properties.battery_type = parse_battery_type(conn:read_u32_enum(40035))
58-
properties.battery_nameplate_capacity = (conn:read_u32_fix0(40031) or 0) * 48
58+
properties.battery_nominal_voltage = 48
59+
properties.battery_nameplate_capacity = (conn:read_u32_fix0(40031) or 0) * properties.battery_nominal_voltage
5960
properties.country_code = parse_country_code(conn:read_u32_fix0(40109))
6061
if conn_cfg then
6162
properties.address = conn_cfg.address
@@ -87,9 +88,10 @@ function send_realtime_telemetry()
8788
local telemetry = {
8889
alerts = parse_alerts(conn:read_u32_enum(30213), conn:read_u32_enum(30247)),
8990
health = parse_health_status(conn:read_u32_enum(30201)),
90-
status = convert_operating_status_to_status(operating_status),
91-
operating_status = operating_status,
91+
status = operating_status,
92+
inverter_status = to_inverter_status(operating_status),
9293

94+
battery_charge_status = to_battery_charge_status(battery_current),
9395
battery_soc = conn:read_u32_fix0(30845),
9496
battery_soh = conn:read_u32_fix0(30847),
9597
battery_voltage = battery_voltage,
@@ -134,7 +136,7 @@ function send_detailed_telemetry()
134136
ac_power_apparent = conn:read_s32_fix0(30813),
135137
ac_power_factor = conn:read_u32_fix3(30949),
136138

137-
residual_current = conn:read_s32_fix3(31247),
139+
residual_current = (conn:read_s32_fix3(31247) or 0) * 1000,
138140
internal_temperature = conn:read_s32_fix1(34113),
139141

140142
load_power = conn:read_s32_fix0(30861),
@@ -239,30 +241,41 @@ function parse_operating_status(value)
239241
return tostring(value)
240242
end
241243

242-
function convert_operating_status_to_status(value)
244+
function to_inverter_status(value)
243245
if not value then
244246
return
245247
end
246248

247249
if value == 'off' or value == 'stop' then
248-
return 'off'
250+
return 'idle'
249251
elseif value == 'standby' or value == 'waiting_pv_voltage' or value == 'waiting_utilities' or value == 'bolted' then
250252
return 'standby'
251253
elseif value == 'start' then
252254
return 'starting'
253-
elseif
254-
value == 'derating'
255-
or value == 'mpp'
256-
or value == 'run'
257-
or value == 'standalone'
258-
or value == 'const_voltage'
259-
or value == 'warning'
260-
then
255+
elseif value == 'run' or value == 'mpp' or value == 'const_voltage' or value == 'warning' then
261256
return 'operating'
257+
elseif value == 'derating' then
258+
return 'throttled'
262259
elseif value == 'shutdown' then
263-
return 'shutting_down'
260+
return 'stopping'
264261
elseif value == 'fault' then
265262
return 'fault'
263+
else
264+
enapter.log('unmapped vendor status: ' .. tostring(value), 'warn')
265+
end
266+
end
267+
268+
function to_battery_charge_status(current)
269+
if not current then
270+
return
271+
end
272+
273+
if current > 0 then
274+
return 'charging'
275+
elseif current < 0 then
276+
return 'discharging'
277+
else
278+
return 'idle'
266279
end
267280
end
268281

β€Žpower_meters/schneider_electric_pm2100_v3/manifest.ymlβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ telemetry:
6565
type: float
6666
unit: Wh
6767
display_name: Active Energy Consumed by Loads
68+
implements: energy.power_meter.ac.3_phase.energy_lifetime
6869
total_power:
6970
type: float
7071
unit: W

β€Žsolar_inverters/deye_sunsynk/main.luaβ€Ž

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ function parse_metrics1(telemetry, data)
112112
local base = 500
113113
telemetry.grid_status = get_grid_status(data, base)
114114
telemetry.status = get_device_status(data, base)
115+
telemetry.inverter_status = to_inverter_status(telemetry.status)
115116
telemetry.alerts = get_alerts(data, base)
116117
-- XXX: check again on low/high word registers
117118
telemetry.internal_temperature = data[540 - base + 1] * 0.1 - 100
@@ -122,6 +123,7 @@ function parse_metrics1(telemetry, data)
122123
telemetry.battery_soc = data[588 - base + 1]
123124
telemetry.battery_power = s16(data[590 - base + 1])
124125
telemetry.battery_current = s16(data[591 - base + 1]) * 0.01
126+
telemetry.battery_charge_status = to_battery_charge_status(telemetry.battery_power)
125127

126128
telemetry.battery_charged_energy_total = ((data[517 - base + 1] << 16) + data[516 - base + 1]) * 0.1 * 1000
127129
telemetry.battery_discharged_energy_total = ((data[519 - base + 1] << 16) + data[518 - base + 1]) * 0.1 * 1000
@@ -215,6 +217,38 @@ function get_device_status(data, base)
215217
end
216218
end
217219

220+
function to_battery_charge_status(power)
221+
if not power then
222+
return
223+
end
224+
225+
if power > 0 then
226+
return 'charging'
227+
elseif power < 0 then
228+
return 'discharging'
229+
else
230+
return 'idle'
231+
end
232+
end
233+
234+
function to_inverter_status(value)
235+
if not value then
236+
return
237+
end
238+
239+
if value == 'standby' then
240+
return 'standby'
241+
elseif value == 'starting' then
242+
return 'starting'
243+
elseif value == 'operating' then
244+
return 'operating'
245+
elseif value == 'fault' then
246+
return 'fault'
247+
else
248+
enapter.log('unmapped vendor status: ' .. tostring(value), 'warn')
249+
end
250+
end
251+
218252
function get_alerts(data, base)
219253
if not data then
220254
return

0 commit comments

Comments
Β (0)