Shelly: Enable Pro 3EM in monophase mode (#17219)
This commit is contained in:
parent
964adbe797
commit
6836749cf5
5 changed files with 99 additions and 22 deletions
|
|
@ -19,6 +19,8 @@ type Connection struct {
|
|||
channel int
|
||||
gen int // Shelly api generation
|
||||
devicetype string // Shelly device type
|
||||
app string // Shelly device app code
|
||||
profile string // Shelly device profile
|
||||
}
|
||||
|
||||
// NewConnection creates a new Shelly device connection.
|
||||
|
|
@ -45,6 +47,8 @@ func NewConnection(uri, user, password string, channel int) (*Connection, error)
|
|||
channel: channel,
|
||||
gen: resp.Gen,
|
||||
devicetype: resp.Type,
|
||||
app: resp.App,
|
||||
profile: resp.Profile,
|
||||
}
|
||||
|
||||
conn.Client.Transport = request.NewTripper(log, transport.Insecure())
|
||||
|
|
|
|||
|
|
@ -42,18 +42,25 @@ func (sh *Switch) CurrentPower() (float64, error) {
|
|||
}
|
||||
|
||||
default:
|
||||
var resem Gen2EmStatusResponse
|
||||
var res Gen2StatusResponse
|
||||
if err := d.execGen2Cmd("Shelly.GetStatus", false, &res); err != nil {
|
||||
return 0, err
|
||||
if d.app == "Pro3EM" && d.profile == "monophase" {
|
||||
if err := d.execGen2Cmd("Shelly.GetStatus", false, &resem); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
if err := d.execGen2Cmd("Shelly.GetStatus", false, &res); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
switch d.channel {
|
||||
case 1:
|
||||
power = res.Switch1.Apower + res.Pm1.Apower
|
||||
power = res.Switch1.Apower + res.Pm1.Apower + resem.Em1.ActPower
|
||||
case 2:
|
||||
power = res.Switch2.Apower + res.Pm2.Apower
|
||||
power = res.Switch2.Apower + res.Pm2.Apower + resem.Em2.ActPower
|
||||
default:
|
||||
power = res.Switch0.Apower + res.Pm0.Apower
|
||||
power = res.Switch0.Apower + res.Pm0.Apower + resem.Em0.ActPower
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,18 +130,25 @@ func (sh *Switch) TotalEnergy() (float64, error) {
|
|||
energy = gen1Energy(d.devicetype, energy)
|
||||
|
||||
default:
|
||||
var resem Gen2EmStatusResponse
|
||||
var res Gen2StatusResponse
|
||||
if err := d.execGen2Cmd("Shelly.GetStatus", false, &res); err != nil {
|
||||
return 0, err
|
||||
if d.app == "Pro3EM" && d.profile == "monophase" {
|
||||
if err := d.execGen2Cmd("Shelly.GetStatus", false, &resem); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
if err := d.execGen2Cmd("Shelly.GetStatus", false, &res); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
switch d.channel {
|
||||
case 1:
|
||||
energy = res.Switch1.Aenergy.Total + res.Pm1.Aenergy.Total
|
||||
energy = res.Switch1.Aenergy.Total + res.Pm1.Aenergy.Total + resem.Em1Data.TotalActEnergy - resem.Em1Data.TotalActRetEnergy
|
||||
case 2:
|
||||
energy = res.Switch2.Aenergy.Total + res.Pm2.Aenergy.Total
|
||||
energy = res.Switch2.Aenergy.Total + res.Pm2.Aenergy.Total + resem.Em2Data.TotalActEnergy - resem.Em2Data.TotalActRetEnergy
|
||||
default:
|
||||
energy = res.Switch0.Aenergy.Total + res.Pm0.Aenergy.Total
|
||||
energy = res.Switch0.Aenergy.Total + res.Pm0.Aenergy.Total + resem.Em0Data.TotalActEnergy - resem.Em0Data.TotalActRetEnergy
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ type DeviceInfo struct {
|
|||
Model string `json:"model"`
|
||||
Type string `json:"type"`
|
||||
Mac string `json:"mac"`
|
||||
App string `json:"app"`
|
||||
Auth bool `json:"auth"`
|
||||
AuthEn bool `json:"auth_en"`
|
||||
NumMeters int `json:"num_meters"`
|
||||
Profile string `json:"profile"`
|
||||
}
|
||||
|
||||
type Gen2RpcPost struct {
|
||||
|
|
@ -40,17 +42,34 @@ type Gen2StatusResponse struct {
|
|||
Pm2 Gen2Switch `json:"pm3:2"`
|
||||
}
|
||||
|
||||
type Gen2Em struct {
|
||||
Current float64 `json:"current"`
|
||||
Voltage float64 `json:"voltage"`
|
||||
ActPower float64 `json:"act_power"`
|
||||
}
|
||||
|
||||
type Gen2EmData struct {
|
||||
TotalActEnergy float64 `json:"total_act_energy"`
|
||||
TotalActRetEnergy float64 `json:"total_act_ret_energy"`
|
||||
}
|
||||
|
||||
type Gen2EmStatusResponse struct {
|
||||
TotalPower float64 `json:"total_act_power"`
|
||||
CurrentA float64 `json:"a_current"`
|
||||
CurrentB float64 `json:"b_current"`
|
||||
CurrentC float64 `json:"c_current"`
|
||||
VoltageA float64 `json:"a_voltage"`
|
||||
VoltageB float64 `json:"b_voltage"`
|
||||
VoltageC float64 `json:"c_voltage"`
|
||||
PowerA float64 `json:"a_act_power"`
|
||||
PowerB float64 `json:"b_act_power"`
|
||||
PowerC float64 `json:"c_act_power"`
|
||||
TotalPower float64 `json:"total_act_power"`
|
||||
CurrentA float64 `json:"a_current"`
|
||||
CurrentB float64 `json:"b_current"`
|
||||
CurrentC float64 `json:"c_current"`
|
||||
VoltageA float64 `json:"a_voltage"`
|
||||
VoltageB float64 `json:"b_voltage"`
|
||||
VoltageC float64 `json:"c_voltage"`
|
||||
PowerA float64 `json:"a_act_power"`
|
||||
PowerB float64 `json:"b_act_power"`
|
||||
PowerC float64 `json:"c_act_power"`
|
||||
Em0 Gen2Em `json:"em1:0"`
|
||||
Em1 Gen2Em `json:"em1:1"`
|
||||
Em2 Gen2Em `json:"em1:2"`
|
||||
Em0Data Gen2EmData `json:"em1data:0"`
|
||||
Em1Data Gen2EmData `json:"em1data:1"`
|
||||
Em2Data Gen2EmData `json:"em1data:2"`
|
||||
}
|
||||
|
||||
type Gen2EmDataStatusResponse struct {
|
||||
|
|
|
|||
|
|
@ -67,4 +67,44 @@ func TestUnmarshalGen2StatusResponse(t *testing.T) {
|
|||
assert.Equal(t, 3551.682, res.Pm0.Aenergy.Total)
|
||||
assert.Equal(t, 1780.1, res.Pm0.Apower)
|
||||
}
|
||||
|
||||
{
|
||||
// Shelly Pro 3EM
|
||||
var res Gen2EmStatusResponse
|
||||
|
||||
jsonstr := `{"ble":{},"bthome":{"errors":["bluetooth_disabled"]},"cloud":{"connected":true},"em1:0":{"id":0,"current":3.705,"voltage":242.8,"act_power":598.9,"aprt_power":900.6,"pf":0.66,"freq":50.0,"calibration":"factory"},"em1:1":{"id":1,"current":0.194,"voltage":242.8,"act_power":0.0,"aprt_power":47.2,"pf":0.00,"freq":50.0,"calibration":"factory"},"em1:2":{"id":2,"current":0.027,"voltage":242.8,"act_power":0.0,"aprt_power":6.6,"pf":0.00,"freq":50.0,"calibration":"factory"},"em1data:0":{"id":0,"total_act_energy":3458.24,"total_act_ret_energy":1605.24},"em1data:1":{"id":1,"total_act_energy":2768.67,"total_act_ret_energy":25.49},"em1data:2":{"id":2,"total_act_energy":3.09,"total_act_ret_energy":0.71},"eth":{"ip":null},"modbus":{},"mqtt":{"connected":false},"sys":{"mac":"FCE8C0DBA850","restart_required":false,"time":"19:46","unixtime":1731404780,"uptime":563,"ram_size":247148,"ram_free":110596,"fs_size":524288,"fs_free":176128,"cfg_rev":21,"kvs_rev":0,"schedule_rev":3,"webhook_rev":1,"available_updates":{},"reset_reason":3},"temperature:0":{"id": 0,"tC":39.0, "tF":102.2},"wifi":{"sta_ip":"192.168.40.174","status":"got ip","ssid":"IoT","rssi":-67},"ws":{"connected":false}}`
|
||||
require.NoError(t, json.Unmarshal([]byte(jsonstr), &res))
|
||||
// Channel 0 (1)
|
||||
assert.Equal(t, 598.9, res.Em0.ActPower)
|
||||
assert.Equal(t, 3.705, res.Em0.Current)
|
||||
assert.Equal(t, 242.8, res.Em0.Voltage)
|
||||
assert.Equal(t, 3458.24, res.Em0Data.TotalActEnergy)
|
||||
assert.Equal(t, 1605.24, res.Em0Data.TotalActRetEnergy)
|
||||
// Channel 1 (2)
|
||||
assert.Equal(t, 0.0, res.Em1.ActPower)
|
||||
assert.Equal(t, 0.194, res.Em1.Current)
|
||||
assert.Equal(t, 242.8, res.Em1.Voltage)
|
||||
assert.Equal(t, 2768.67, res.Em1Data.TotalActEnergy)
|
||||
assert.Equal(t, 25.49, res.Em1Data.TotalActRetEnergy)
|
||||
// Channel 2 (3)
|
||||
assert.Equal(t, 0.0, res.Em2.ActPower)
|
||||
assert.Equal(t, 0.027, res.Em2.Current)
|
||||
assert.Equal(t, 242.8, res.Em2.Voltage)
|
||||
assert.Equal(t, 3.09, res.Em2Data.TotalActEnergy)
|
||||
assert.Equal(t, 0.71, res.Em2Data.TotalActRetEnergy)
|
||||
}
|
||||
}
|
||||
|
||||
// Test Shelly device info
|
||||
func TestUnmarshalDeviceInfoResponse(t *testing.T) {
|
||||
{
|
||||
// Shelly Pro 3EM
|
||||
var res DeviceInfo
|
||||
|
||||
jsonstr := `{"name":null,"id":"shellypro3em-fce8c0dba900","mac":"FCE8C0DBA900","slot":1,"model":"SPEM-003CEBEU","gen":2,"fw_id":"20241011-114455/1.4.4-g6d2a586","ver":"1.4.4","app":"Pro3EM","auth_en":false,"auth_domain":null,"profile":"monophase"}`
|
||||
require.NoError(t, json.Unmarshal([]byte(jsonstr), &res))
|
||||
|
||||
assert.Equal(t, "Pro3EM", res.App)
|
||||
assert.Equal(t, "monophase", res.Profile)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ template: shelly-1pm
|
|||
products:
|
||||
- brand: Shelly
|
||||
description:
|
||||
generic: 1PM, EM, Plug S
|
||||
generic: 1PM, EM, Plug S, Pro 3EM in monophase mode
|
||||
group: switchsockets
|
||||
params:
|
||||
- name: usage
|
||||
choice: ["pv", "charge"]
|
||||
choice: ["grid", "pv", "charge"]
|
||||
- name: host
|
||||
- name: user
|
||||
- name: password
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue