智能家居 – 控制 Shelly® 设备(第一部分)






4.10/5 (7投票s)
本文将介绍如何将 Shelly® 继电器集成到我的智能家居系统中,并通过 VB.NET 中的例程来控制这些设备。
在为我的女婿打造了一个智能新家之后,我也想为自己的家添置 Shelly® 继电器。
我主要通过 Amazon Echo Dot®(“Alexa
”)来控制这些设备,但出于兴趣,并且因为找不到好的文档,我决定创建基于 .NET 的例程,使其也能控制或查询这些设备。
本文将介绍我为此目的创建的例程,并指出我所使用的模块的一些特殊之处。
我家中使用的是 Shelly 2.5、Shelly Dimmer2、Shelly 1PM 和 Shelly 2PM 模块。我为这些模块创建了例程。当然,还有其他一些模块,但尊贵的读者可能需要自行创建它们的例程,或许可以参考这个模板。
由于我只有 Visual Studio 2010®,这里使用的框架是 .NET 4.0。
基础
基本上,与设备的通信是通过 HTML 命令进行的。设备本身的反馈以 JSON string
的形式提供,我已经将我感兴趣的信息存储在相应的子类中。不幸的是,部分命令因设备而异,因此我不得不为每个设备创建特定的例程。
这里我假设读者具备 JSON string
反序列化的基本知识。我将不再深入讲解 WebClient
的使用。
我“对话”的是哪个设备?
Private Class ShellyTyp
Public type As String
Public app As String
ReadOnly Property Typ() As String
Get
If type IsNot Nothing Then Return type
If app IsNot Nothing Then Return app
Return ""
End Get
End Property
End Class
Function Shelly_GetType(IpAdress As String) As ShellyType
Request = "http://" + IpAdress + "/shelly"
Dim myType As ShellyType = ShellyType.None
Try
Dim result As String = webClient.DownloadString(Request)
Dim JSON_Packet As ShellyTyp = _
JsonConvert.DeserializeObject(Of ShellyTyp)(result)
Select Case JSON_Packet.Typ
Case "SHSW-25" : myType = ShellyType.Shelly_25
Case "SHDM-2" : myType = ShellyType.Shelly_Dimmer2
Case "Plus1PM", "Plus1Mini" : myType = ShellyType.Shelly_1PM
Case "Plus2PM" : myType = ShellyType.Shelly_2PM
End Select
Return myType
Catch ex As Exception
Return ShellyType.None
End Try
End Function
private class JSON_ShellyType
{
public string type = "";
public string app = "";
public string Typ
{
get
{
if (type != "")
return type;
if (app != "")
return app;
return "";
}
}
}
public static ShellyType Shelly_GetType(string IpAdress)
{
Request = "http://" + IpAdress + "/shelly";
ShellyType myType = ShellyType.None;
try
{
string result = webClient.DownloadString(Request);
JSON_ShellyType JSON_Packet = JsonConvert.DeserializeObject<JSON_ShellyType>(result);
switch (JSON_Packet.Typ)
{
case "SHSW-25":
{
myType = ShellyType.Shelly_25;
break;
}
case "SHDM-2":
{
myType = ShellyType.Shelly_Dimmer2;
break;
}
case "Plus1PM":
case "Plus1Mini":
{
myType = ShellyType.Shelly_1PM;
break;
}
case "Plus2PM":
{
myType = ShellyType.Shelly_2PM;
break;
}
}
return myType;
}
catch (Exception)
{
return ShellyType.None;
}
}
从这里可以看出,对于所有设备的类型查询,都有一个通用的命令。根据设备的不同,类型响应再次存储在不同的 JSON 属性中,有些设备存储在 “type
” 项中,有些设备存储在 “app
” 项中。JSON 反序列化程序会将其中一个项填充到我的类中。
所示函数会返回相应的类型。我会在所有后续的查询/命令中使用此查询。
设备状态请求
Function Shelly_GetStatus(IpAdress As String) As IO_Status
Dim myType As ShellyType = Shelly_GetType(IpAdress)
Select Case myType
Case ShellyType.Shelly_25
Return Shelly_25_GetStatus(IpAdress)
Case ShellyType.Shelly_Dimmer2
Return Shelly_Dimmer2_GetStatus(IpAdress)
Case ShellyType.Shelly_1PM
Return Shelly_1PM_GetStatus(IpAdress)
Case ShellyType.Shelly_2PM
Return Shelly_2PM_GetStatus(IpAdress)
Case ShellyType.None
Return New IO_Status
End Select
Return New IO_Status
End Function
Class IO_Status
Public Connection As ShellyResult = ShellyResult.None
Public In0 As Boolean = False
Public In1 As Boolean = False
Public Out0 As Boolean = False
Public Out1 As Boolean = False
Public Mode As ShellyMode = ShellyMode.none
Public OutValue As Integer = -1
Overrides Function toString() As String
Dim s As String = Connection.ToString
Dim inActive As String = ""
If In0 Then inActive += "0"
If In1 Then inActive += "1"
If inActive < > "" Then s += ", in:" + inActive
Dim outActive As String = ""
If Out0 Then outActive += "0"
If Out1 Then outActive += "1"
If outActive < > "" Then s += ", out:" + outActive
If OutValue > = 0 Then s += ", " + Str(OutValue).Trim + "%"
If Mode < > ShellyMode.none Then s += ", mode:" + Mode.ToString
Return s
End Function
End Class
public static Shelly_IOStatus Shelly_GetStatus(string IpAdress)
{
ShellyType myType = Shelly_GetType(IpAdress);
switch (myType)
{
case ShellyType.Shelly_25:
{
return Shelly_25_GetStatus(IpAdress);
}
case ShellyType.Shelly_Dimmer2:
{
return Shelly_Dimmer2_GetStatus(IpAdress);
}
case ShellyType.Shelly_1PM:
{
return Shelly_1PM_GetStatus(IpAdress);
}
case ShellyType.Shelly_2PM:
{
return Shelly_2PM_GetStatus(IpAdress);
}
case ShellyType.None:
{
return new Shelly_IOStatus();
}
}
return new Shelly_IOStatus();
}
public class Shelly_IOStatus
{
public ShellyResult Connection = ShellyResult.None;
public bool In0 = false;
public bool In1 = false;
public bool Out0 = false;
public bool Out1 = false;
public ShellyMode Mode = ShellyMode.none;
public ShellyRollerState RollerState = ShellyRollerState.none;
public int OutValue = -1;
public override string ToString()
{
string s = Connection.ToString();
string inActive = "";
if (In0)
inActive += "0";
if (In1)
inActive += "1";
if (inActive != "")
s += ", in:" + inActive;
string outActive = "";
if (Out0)
outActive += "0";
if (Out1)
outActive += "1";
if (outActive != "")
s += ", out:" + outActive;
if (OutValue >= 0)
s += ", " + Convert.ToString(OutValue).Trim() + "%";
if (Mode != ShellyMode.none)
s += ", mode:" + Mode.ToString();
return s;
}
}
所示的 Shelly_GetStatus
函数返回指定 IP 地址的 Shelly 设备的当前状态。该函数本身会根据相应的 Shelly 类型分支到相应的子函数。
为了在此实现标准化,所有设备都有相同的 IO 状态,只有不存在的区域在子函数中不被赋值。
设备状态子函数
我将在此使用其中一个设备的示例来描述子函数本身。所有其他设备仅在命令和响应中收到的 JSON string
上有所不同。
在以下示例中,我将查询 Shelly-1PM
的状态。
Private Class JSON_Shelly12PM_Status
< Newtonsoft.Json.JsonProperty("switch:0") >
Public Switch0 As cRelay
< Newtonsoft.Json.JsonProperty("switch:1") >
Public Switch1 As cRelay
< Newtonsoft.Json.JsonProperty("cover:0") >
Public Cover0 As cCover
< Newtonsoft.Json.JsonProperty("input:0") >
Public Input0 As cInput
< Newtonsoft.Json.JsonProperty("input:1") >
Public Input1 As cInput
Partial Public Class cRelay
Public output As Boolean
End Class
Partial Public Class cCover
Public state As String
Public last_direction As String
Public current_pos As Integer
End Class
Partial Public Class cInput
Public state As Object
End Class
ReadOnly Property RelayState As Boolean()
Get
Dim myState(1) As Boolean
If Switch0 IsNot Nothing Then myState(0) = Switch0.output
If Switch1 IsNot Nothing Then myState(1) = Switch1.output
If Cover0 IsNot Nothing Then
Select Case Cover0.state
Case "stopped"
myState(0) = False
myState(1) = False
Case "opening"
myState(0) = True
myState(1) = False
Case "closing"
myState(0) = False
myState(1) = True
End Select
End If
Return myState
End Get
End Property
ReadOnly Property InputState As Boolean()
Get
Dim myState(1) As Boolean
If Not Boolean.TryParse(Input0.state, myState(0)) Then myState(0) = False
If Not Boolean.TryParse(Input1.state, myState(1)) Then myState(1) = False
Return myState
End Get
End Property
ReadOnly Property Mode As ShellyMode
Get
If Switch0 IsNot Nothing Then Return ShellyMode.Relay
If Cover0 IsNot Nothing Then Return ShellyMode.Roller
Return ShellyMode.none
End Get
End Property
ReadOnly Property RollerState As ShellyRollerState
Get
If Cover0 IsNot Nothing Then
If(Cover0.state = "stop") And (Cover0.last_direction = "opening") Then Return ShellyRollerState.Stop_AfterOpening
If(Cover0.state = "closing") Then Return ShellyRollerState.Closing
If(Cover0.state = "stop") And (Cover0.last_direction = "closing") Then Return ShellyRollerState.Stop_AfterClosing
If(Cover0.state = "opening") Then Return ShellyRollerState.Opening
End If
Return ShellyRollerState.none
End Get
End Property
End Class
Function Shelly_1PM_GetStatus(IpAdress As String) As IO_Status
Dim myStatus As New IO_Status
Request = "http://" + IpAdress + "/rpc/Shelly.GetStatus"
Try
Dim result As String = webClient.DownloadString(Request)
Dim JSON_Packet As JSON_Shelly12PM_Status =
JsonConvert.DeserializeObject(Of JSON_Shelly12PM_Status)(result)
myStatus.Out0 = JSON_Packet.RelayState(0)
myStatus.Out0 = False
myStatus.OutValue = -1
myStatus.Mode = "Relay"
myStatus.In0 = JSON_Packet.InputState(0)
myStatus.In1 = False
myStatus.Connection = ShellyResult.Connected
Return myStatus
Catch ex As Exception
myStatus.Connection = ShellyResult.ErrorConnection
Return myStatus
End Try
End Function
private class JSON_Shelly12PM_Status
{
[Newtonsoft.Json.JsonProperty("switch:0")]
public cRelay Switch0 = null;
[Newtonsoft.Json.JsonProperty("switch:1")]
public cRelay Switch1 = null;
[Newtonsoft.Json.JsonProperty("cover:0")]
public cCover Cover0 = null;
[Newtonsoft.Json.JsonProperty("input:0")]
public cInput Input0 = null;
[Newtonsoft.Json.JsonProperty("input:1")]
public cInput Input1 = null;
public partial class cRelay
{
public bool output = false;
}
public partial class cCover
{
public string state = "";
public string last_direction = "";
public int current_pos = 0;
}
public partial class cInput
{
public object state = null;
}
public bool[] RelayState
{
get
{
bool[] myState = new bool[2];
if (Switch0 != null)
myState[0] = Switch0.output;
if (Switch1 != null)
myState[1] = Switch1.output;
if (Cover0 != null)
{
switch (Cover0.state)
{
case "stopped":
{
myState[0] = false;
myState[1] = false;
break;
}
case "opening":
{
myState[0] = true;
myState[1] = false;
break;
}
case "closing":
{
myState[0] = false;
myState[1] = true;
break;
}
}
}
return myState;
}
}
public bool[] InputState
{
get
{
bool[] myState = new bool[2];
if (!bool.TryParse(Convert.ToString(Input0.state), out myState[0]))
{
myState[0] = false;
}
if (!bool.TryParse(Convert.ToString(Input1.state), out myState[1]))
{
myState[1] = false;
}
return myState;
}
}
public ShellyMode Mode
{
get
{
if (Switch0 != null)
return ShellyMode.Relay;
if (Cover0 != null)
return ShellyMode.Roller;
return ShellyMode.none;
}
}
public ShellyRollerState RollerState
{
get
{
if (Cover0 != null)
{
if ((Cover0.state == "stop") & (Cover0.last_direction == "opening"))
return ShellyRollerState.Stop_AfterOpening;
if ((Cover0.state == "closing"))
return ShellyRollerState.Closing;
if ((Cover0.state == "stop") & (Cover0.last_direction == "closing"))
return ShellyRollerState.Stop_AfterClosing;
if ((Cover0.state == "opening"))
return ShellyRollerState.Opening;
}
return ShellyRollerState.none;
}
}
}
private static Shelly_IOStatus Shelly_1PM_GetStatus(string IpAdress)
{
Shelly_IOStatus myStatus = new Shelly_IOStatus();
Request = "http://" + IpAdress + "/rpc/Shelly.GetStatus";
try
{
string result = webClient.DownloadString(Request);
JSON_Shelly12PM_Status JSON_Packet = JsonConvert.DeserializeObject<JSON_Shelly12PM_Status>(result);
myStatus.Out0 = JSON_Packet.RelayState[0];
myStatus.Out0 = false;
myStatus.OutValue = -1;
myStatus.Mode = ShellyMode.Relay;
myStatus.In0 = JSON_Packet.InputState[0];
myStatus.In1 = false;
myStatus.Connection = ShellyResult.Connected;
return myStatus;
}
catch (Exception)
{
myStatus.Connection = ShellyResult.ErrorConnection;
return myStatus;
}
}
Shelly-1PM
是一个单通道继电器,只有一个输入。但是,设备本身返回的 JSON string
与 Shelly-2PM
的没有区别,这就是为什么我对这两个设备使用相同的类来反序列化 JSON 字符串。
控制设备 / 发送命令
作为示例,我将展示控制 Shelly 继电器的函数。还可以选择控制调光器的亮度并将百叶窗移动到特定位置。但是,这些功能在基本原理上都没有区别。
Function Shelly_SetOutput(IpAdress As String, OutNr As Integer, State As Boolean ) As ShellyResult
Dim myType As ShellyType = Shelly_GetType(IpAdress)
Request = "http://" + IpAdress + "/relay/"
Select Case myType
Case ShellyType.Shelly_1PM
Request += "0?turn="
If Not State Then
Request += "off"
Else
Request += "on"
End If
Case ShellyType.Shelly_2PM, ShellyType.Shelly_25
Select Case OutNr
Case 0, 1
Request += Str(OutNr).Trim
Case Else
Return ShellyResult.ErrorShellyType
End Select
Request += "?turn="
If Not State Then
Request += "off"
Else
Request += "on"
End If
Case ShellyType.Shelly_Dimmer2
Request = "http://" + IpAdress + "/light/0?turn="
If Not State Then
Request += "off"
Else
Request += "on"
End If
Case Else
Return ShellyResult.NoAction
End Select
Try
Dim result As String = webClient.DownloadString(Request)
Return ShellyResult.Done
Catch ex As Exception
Return ShellyResult.ErrorConnection
End Try
Return ShellyResult.NoAction
End Function
public static ShellyResult Shelly_SetOutput(string IpAdress, int OutNr, bool State)
{
ShellyType myType = Shelly_GetType(IpAdress);
Request = "http://" + IpAdress + "/relay/";
switch (myType)
{
case ShellyType.Shelly_1PM:
{
Request += "0?turn=";
if (!State)
Request += "off";
else
Request += "on";
break;
}
case ShellyType.Shelly_2PM:
case ShellyType.Shelly_25:
{
switch (OutNr)
{
case 0:
case 1:
{
Request += Convert.ToString(OutNr).Trim();
break;
}
default:
{
return ShellyResult.ErrorShellyType;
}
}
Request += "?turn=";
if (!State)
Request += "off";
else
Request += "on";
break;
}
case ShellyType.Shelly_Dimmer2:
{
Request = "http://" + IpAdress + "/light/0?turn=";
if (!State)
Request += "off";
else
Request += "on";
break;
}
default:
{
return ShellyResult.NoAction;
}
}
try
{
string result = webClient.DownloadString(Request);
return ShellyResult.Done;
}
catch (Exception)
{
return ShellyResult.ErrorConnection;
} //return ShellyResult.NoAction;
}
集成到按钮控件
以下代码展示了如何将这些方法集成到按钮控件中。在这种情况下,我扩展了标准按钮的一些属性,并相应地集成了这些功能。
在单击事件中,按钮现在会调用 Shelly_ToggleOutput
方法,并根据所选 Shelly 设备的输出状态更改其颜色。
Imports System.ComponentModel
Public Class ShellyButton
Inherits Button
Sub New()
MyBase.BackColor = my_DefaultBackColor
MyBase.ForeColor = my_DefaultForeColor
End Sub
#Region "Properties"
' makes the Standard - Property unvisible inside the PropertyGrid
< Browsable(False), EditorBrowsable(EditorBrowsableState.Never) >
Shadows Property ForeColor As Color
' Replacement for the Standard - Property inside the PropertyGrid
< Category("Shelly"), Description("Default ForeColor of the Control") >
< DefaultValue(GetType(System.Drawing.Color), "Black") >
Property DefaultForeColor As Color
Get
Return my_DefaultForeColor
End Get
Set(ByVal value As Color)
my_DefaultForeColor = value
MyBase.BackColor = value
End Set
End Property
Private my_DefaultForeColor As Color = Color.Black
< Category("Shelly"), Description("ForeColor of the Control when animated") >
< DefaultValue(GetType(System.Drawing.Color), "White") >
Property AnimationForeColor As Color
Get
Return my_AnimationForeColor
End Get
Set(ByVal value As Color)
my_AnimationForeColor = value
End Set
End Property
Private my_AnimationForeColor As Color = Color.White
' makes the Standard - Property unvisible inside the PropertyGrid
< Browsable(False), EditorBrowsable(EditorBrowsableState.Never) >
Shadows Property BackColor As Color
' Replacement for the Standard - Property inside the PropertyGrid
< Category("Shelly"), Description("Default BackColor of the Control") >
< DefaultValue(GetType(System.Drawing.Color), "LightGray") >
Property DefaultBackColor As Color
Get
Return my_DefaultBackColor
End Get
Set(ByVal value As Color)
my_DefaultBackColor = value
MyBase.BackColor = value
Me.Invalidate()
End Set
End Property
Private my_DefaultBackColor As Color = Color.LightGray
< Category("Shelly"), Description("BackColor of the Control when animated") >
< DefaultValue(GetType(System.Drawing.Color), "Green") >
Property AnimationBackColor As Color
Get
Return my_AnimationBackColor
End Get
Set(ByVal value As Color)
my_AnimationBackColor = value
Me.Invalidate()
End Set
End Property
Private my_AnimationBackColor As Color = Color.Green
< Category("Shelly"), Description("Refresh-Interval for the Animation") >
< DefaultValue(1000) >
Property RefreshInterval As Integer
Get
Return my_Timer.Interval
End Get
Set(value As Integer)
If value > 500 Then
my_Timer.Interval = value
End If
End Set
End Property
< Category("Shelly"), Description("Enables the Refresh of the Animation") >
< DefaultValue(False) >
Property RefreshEnabled As Boolean
Get
Return my_RefreshEnabled
End Get
Set(value As Boolean)
my_RefreshEnabled = value
If Not DesignMode Then my_Timer.Enabled = value
End Set
End Property
Private my_RefreshEnabled As Boolean = False
< Category("Shelly"), Description("IpAdress of the Shelly-Device to work with") >
< RefreshProperties(RefreshProperties.All) >
Property IpAdress As String
Get
Return my_IPAdress
End Get
Set(value As String)
my_ShellyType = Shelly_GetType(value).ToString
If my_ShellyType < > "None" Then my_IPAdress = value
End Set
End Property
Private my_IPAdress As String = ""
< Category("Shelly"), Description("Output-Number of the Shelly-Device to work with") >
< DefaultValue(0) >
Property ShellyOutputNr As Integer
Get
Return my_ShellyOutputNr
End Get
Set(value As Integer)
If(value > = 0) And(value < = 1) Then my_ShellyOutputNr = value
End Set
End Property
Private my_ShellyOutputNr As Integer = 0
< Category("Shelly"), Description("shows the Type of the connected Shelly-Device") >
ReadOnly Property ShellyType As String
Get
Return my_ShellyType
End Get
End Property
Private my_ShellyType As String
#End Region
#Region "Methods"
' call the ToggleButton - Method with the Button - Click
Protected Overrides Sub OnClick(e As System.EventArgs)
Dim result As ShellyResult = Shelly_ToggleOutput(my_IPAdress, my_ShellyOutputNr)
End Sub
' the Timer - Tick does when activated the Animation of the Button
Sub Timer_Tick() Handles my_Timer.Tick
my_Status = Shelly_GetStatus(my_IPAdress)
my_OutActive =(my_ShellyOutputNr = 0 And my_Status.Out0)
Or (my_ShellyOutputNr = 1 And my_Status.Out1) If my_OutActive Then
MyBase.BackColor = my_AnimationBackColor
MyBase.ForeColor = my_AnimationForeColor
Else
MyBase.BackColor = my_DefaultBackColor
MyBase.ForeColor = my_DefaultForeColor
End If
End Sub
Private my_Status As Shelly_IOStatus
Private my_OutActive As Boolean = False
Private WithEvents my_Timer As New Timer With {.Enabled = False, .Interval = 1000}
#End Region
End Class
using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using ShellyConnect_C;
//using ShellyCom;
public class ShellyButton : System.Windows.Forms.Button
{
public ShellyButton()
{
my_Timer = new System.Windows.Forms.Timer()
{
Enabled = false,
Interval = 1000
};
my_Timer.Tick += Timer_Tick;
base.BackColor = my_DefaultBackColor;
base.ForeColor = my_DefaultForeColor;
}
// makes the Standard -Property unvisible inside the PropertyGrid
[Browsable(false)][EditorBrowsable(EditorBrowsableState.Never)]
public new Color ForeColor { get; set; }
// Replacement for the Standard-Property inside the PropertyGrid
[Category("Shelly")]
[Description("Default ForeColor of the Control ")]
[DefaultValue(typeof(System.Drawing.Color), "Black")]
public new Color DefaultForeColor
{
get
{
return my_DefaultForeColor;
}
set
{
my_DefaultForeColor = value;
base.BackColor = value;
}
}
private Color my_DefaultForeColor = Color.Black;
[Category("Shelly")]
[Description("ForeColor of the Control when animated ")]
[DefaultValue(typeof(System.Drawing.Color), "White")]
public Color AnimationForeColor
{
get
{
return my_AnimationForeColor;
}
set
{
my_AnimationForeColor = value;
}
}
private Color my_AnimationForeColor = Color.White;
// makes the Standard -Property unvisible inside the PropertyGrid
[Browsable(false)][EditorBrowsable(EditorBrowsableState.Never)]
public new Color BackColor { get; set; }
// Replacement for the Standard-Property inside the PropertyGrid
[Category("Shelly")]
[Description("Default BackColor of the Control ")]
[DefaultValue(typeof(System.Drawing.Color), "LightGray")]
public new Color DefaultBackColor
{
get
{
return my_DefaultBackColor;
}
set
{
my_DefaultBackColor = value;
base.BackColor = value;
this.Invalidate();
}
}
private Color my_DefaultBackColor = Color.LightGray;
[Category("Shelly")]
[Description("BackColor of the Control when animated ")]
[DefaultValue(typeof(System.Drawing.Color), "Green")]
public Color AnimationBackColor
{
get
{
return my_AnimationBackColor;
}
set
{
my_AnimationBackColor = value;
this.Invalidate();
}
}
private Color my_AnimationBackColor = Color.Green;
[Category("Shelly")]
[Description("Refresh-Interval for the Animation ")]
[DefaultValue(1000)]
public int RefreshInterval
{
get
{
return my_Timer.Interval;
}
set
{
if (value > 500)
my_Timer.Interval = value;
}
}
[Category("Shelly")]
[Description("Enables the Refresh of the Animation")]
[DefaultValue(false)]
public bool RefreshEnabled
{
get
{
return my_RefreshEnabled;
}
set
{
my_RefreshEnabled = value;
if (!DesignMode)
my_Timer.Enabled = value;
}
}
private bool my_RefreshEnabled = false;
[Category("Shelly")]
[Description("IpAdress of the Shelly - Device to work with ")]
[RefreshProperties(RefreshProperties.All)]
public string IpAdress
{
get
{
return my_IPAdress;
}
set
{
ShellyCom.ShellyType myType = ShellyCom.Shelly_GetType(value);
my_ShellyType = Convert.ToString(myType);
if (my_ShellyType != "None")
my_IPAdress = value;
}
}
private string my_IPAdress = "192.168.178.201";
[Category("Shelly")]
[Description("Output-Number of the Shelly - Device to work with ")]
[DefaultValue(0)]
public int ShellyOutputNr
{
get
{
return my_ShellyOutputNr;
}
set
{
if ((value >= 0) & (value <= 1))
my_ShellyOutputNr = value;
}
}
private int my_ShellyOutputNr = 0;
[Category("Shelly")]
[Description("shows the Type of the connected Shelly - Device ")]
public string ShellyType
{
get
{
return my_ShellyType;
}
}
private string my_ShellyType;
// call the ToggleButton -Method with the Button-Click
protected override void OnClick(System.EventArgs e)
{
ShellyCom.ShellyResult result = ShellyCom.Shelly_ToggleOutput(my_IPAdress, my_ShellyOutputNr);
}
// the Timer-Tick does when activated the Animation of the Button
public void Timer_Tick(object sender, System.EventArgs e)
{
my_Status = ShellyCom.Shelly_GetStatus(my_IPAdress);
my_OutActive = (my_ShellyOutputNr == 0 & my_Status.Out0) | (my_ShellyOutputNr == 1 & my_Status.Out1);
if (my_OutActive)
{
base.BackColor = my_AnimationBackColor;
base.ForeColor = my_AnimationForeColor;
}
else
{
base.BackColor = my_DefaultBackColor;
base.ForeColor = my_DefaultForeColor;
}
}
private ShellyCom.Shelly_IOStatus my_Status;
private bool my_OutActive = false;
private Timer my_Timer;
}
关注点
总体而言,包含以下方法:
Shelly_GetStatusString | 将完整且格式化的结果字符串传递给选定的请求。 |
Shelly_GetType | 获取指定 IP 地址的 Shelly 设备的类型。 |
Shelly_GetStatus | 将指定 IP 地址的 Shelly 设备的当前状态传输过来,相应的特性在 Shelly_IOStatus 中返回。根据设备类型,会使用子方法:
|
Shelly_SetOutput | 将指定 IP 地址的 Shelly 设备上选定的输出设置为选定的状态。 |
Shelly_ToggleOutput | 切换指定 IP 地址的 Shelly 设备上选定输出的状态。 |
Shelly_SetRoller | 将指定 IP 地址的 Shelly 设备上的百叶窗/卷帘设置为选定的位置。 |
Shelly_ToggleRoller | 切换指定 IP 地址的 Shelly 设备上百叶窗/卷帘的驱动状态到选定的位置。 |
Shelly_SetDimmer | 将指定 IP 地址的 Shelly 设备上的调光器控制到选定的亮度值。 |
返回类型包括:
Enum ShellyType | 可能的 Shelly 类型。 |
Enum ShellyResult | 请求可能的返回结果。 |
Enum ShellyMode | Shelly 设备可能的操作模式。 |
Enum ShellyRollerState | 百叶窗/卷帘驱动可能的状 |
Class Shelly IOStatus | 已请求的 Shelly 设备的 IO 状态。 |
最后的话
我感谢 @RichardDeeming 和 @Andre Oosthuizen 在我不知道的某些细节上提供的帮助。
我从 Shelly Support 页面获取了关于设备本身的基本信息。
我通过逆向工程自行确定了查询的项名称。
历史
- 2023年11月23日:初始版本