HomeGenie Forum
Automation Program Plugins and Wizard Scripting => Help => Topic started by: kobi.beja on March 16, 2015, 10:56:40 AM
-
Hi
I got two products of P5 (http://p5.hu/index.php/products/ethernet-modules (http://p5.hu/index.php/products/ethernet-modules))
8 Relay (FNIP-8x10A)
4 ch Shading (FNIP-4xSH)
The commands for this 2 products it's very simple.
I tried to fit my code from this post http://www.homegenie.it/forum/index.php?topic=693.0 (http://www.homegenie.it/forum/index.php?topic=693.0) but I can't handle with the received commands and change the real state of the switch.
if someone can help it will be great.
This what i have and working.
//Relays control commands
var relay01on = "FN,ON,1\x0D";
var relay02on = "FN,ON,2\x0D";
var relay03on = "FN,ON,3\x0D";
var relay04on = "FN,ON,4\x0D";
var relay05on = "FN,ON,5\x0D";
var relay06on = "FN,ON,6\x0D";
var relay07on = "FN,ON,7\x0D";
var relay08on = "FN,ON,8\x0D";
var relay01off = "FN,OFF,1\x0D";
var relay02off = "FN,OFF,2\x0D";
var relay03off = "FN,OFF,3\x0D";
var relay04off = "FN,OFF,4\x0D";
var relay05off = "FN,OFF,5\x0D";
var relay06off = "FN,OFF,6\x0D";
var relay07off = "FN,OFF,7\x0D";
var relay08off = "FN,OFF,8\x0D";
Action<string> HandleStringReceived = (string message) => {
};
Action<byte[]> HandleMessageReceived = (byte[] message) => {
// this will be called every time a message is received from the tcp channel
//Program.Notify("Server Bytes", BitConverter.ToString(message));
string heartbeat=BitConverter.ToString(message);
if (heartbeat=="3E") // Relay module send this command every 5s (The identifier can be specified in the admin interface device!)
{
//Get status command
//byte[] getstatus = new byte[] {0x46, 0x4e, 0x2c, 0x53, 0x52, 0x45, 0x5c, 0x58, 0x30, 0x44};
TcpClient.SendMessage("FN,SRE\r");;
}
else if ((message.Length == 17)&& message[6] == 128 /*HEX 80*/) //status message received
{
int value = message[14];
var relayarray = Convert.ToString(value, 2).PadLeft(8, '0').ToArray();
for (int i = 0; i < 8; i++)
{
var module = SettingSwitchModules.WithAddress((8-i).ToString()).Get();
// Relay status changed by wall switch (!=)
if ((module.Parameter("Status.Level").DecimalValue).ToString() != relayarray[i].ToString())
{
//Switch the virtual switches status to relays status
module.Toggle();
}
}
}
};
Kobi
-
Hi!
What is your response to the status request message?
Because my response message is "55 00 10 01 01 AA 80 07 2F 00 00 04 00 00 04 CF 16" in hex, and my status is the 15. hex pair.
message part: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Response message: 55 00 10 01 01 AA 80 07 2F 00 00 04 00 00 04 CF 16
In my case, this includes the relay status bits converted.
Relay: 01234567
Status: 11001101
Where 1, the relay is on.
This is handled by this code:
else if ((message.Length == 17)&& message[6] == 128 /*HEX 80*/) //status message received
{
int value = message[14];
var relayarray = Convert.ToString(value, 2).PadLeft(8, '0').ToArray(); // Convert message[14] to bits (for example: 11000101)
for (int i = 0; i < 8; i++)
{
var module = SettingSwitchModules.WithAddress((8-i).ToString()).Get();
// Relay status changed by wall switch (!=)
if ((module.Parameter("Status.Level").DecimalValue).ToString() != relayarray[i].ToString())
{
//Switch the virtual switches status to relays status
module.Toggle();
}
}
}
-
Hi
In my case
the message for status is (FN,SRE\r)
and the response for that is (>FN,OUT,OFF,1{0A}{0D}>FN,OUT,OFF,2{0A}{0D}>FN,OUT,OFF,3{0A}{0D}>FN,OUT,OFF,4{0A}{0D}>FN,OUT,OFF,5{0A}{0D}>FN,OUT,OFF,6{0A}{0D}>FN,OUT,OFF,7{0A}{0D}>FN,OUT,OFF,8{0A}{0D}>)
it's can be ON or OFF (FN,OUT,OFF,1) or (FN,OUT,ON,1)
as you can see its ASCII
Thanks
Kobi
-
Hi!
If your status message is string, than you receive a message this section:
Action<string> HandleStringReceived = (string message) => {
// this will be called every time a message is received from the tcp channel
Program.Notify("Server String", message);
So, you must replace this code to this:
Action<string> HandleStringReceived = (string message) => {
// this will be called every time a message is received from the tcp channel
Program.Notify("Server String", message);
string status = "";
if (message=="3E") // Relay module send this command every 5s (The identifier can be specified in the admin interface device!)
{
TcpClient.SendMessage("FN,SRE\r");; //Get status message
}
else if (message.Length >130) //This should be a condition that is certainly, on the basis that this status message. I think that the status message is longer than 130 characters.
{
for (int i =0; i <message.Length; i++)
{
if ((message[i].ToString()==">") && (i>9))
{
if (message[i-11].ToString() == "F")
{
status = "0";
}
else
{
status = "1";
}
var module = SettingSwitchModules.WithAddress((Convert.ToByte(message[i-9])).ToString()).Get();
if ((module.Parameter("Status.Level").DecimalValue).ToString() != status)
{
//Switch the virtual switches status to relays status
module.Toggle();
}
}
}
}
};
I think this will work for you.
-
Hi
Thanks a lot! 8)
The status feedback still not working, i tried the code but only the send function working
The command for checking is ok but it's not update the real status if i do something manually on the P5
i'm understand it's starting with ">" and the ends with "F"
but how it's recognize the channel number?
the log of what the P5 send
2:22:36.997 AM Program.Notification {"Title":"Server String","Message":">FN,OUT,ON,8"} 1000 HomeAutomation.HomeGenie.Automation
2:22:36.997 AM Program.Notification {"Title":"Server String","Message":">FN,OUT,ON,7"} 1000 HomeAutomation.HomeGenie.Automation
2:22:36.997 AM Program.Notification {"Title":"Server String","Message":">FN,OUT,ON,6"} 1000 HomeAutomation.HomeGenie.Automation
2:22:36.997 AM Program.Notification {"Title":"Server String","Message":">FN,OUT,ON,5"} 1000 HomeAutomation.HomeGenie.Automation
2:22:36.996 AM Program.Notification {"Title":"Server String","Message":">FN,OUT,ON,4"} 1000 HomeAutomation.HomeGenie.Automation
2:22:36.996 AM Program.Notification {"Title":"Server String","Message":">FN,OUT,ON,3"} 1000 HomeAutomation.HomeGenie.Automation
2:22:36.996 AM Program.Notification {"Title":"Server String","Message":">FN,OUT,ON,2"} 1000 HomeAutomation.HomeGenie.Automation
2:22:36.996 AM Program.Notification {"Title":"Server String","Message":">>FN,OUT,OFF,1"}
the code
//Alpha Smart Home remote controller (8 relays)
var remoteServer = "192.168.1.147"; //server IP address
var remotePort = 7078; //TCP port
var SettingSwitchModules = Modules.InDomain("HomeAutomation.SettingSwitch");
//Relays control commands
var relay01on = "FN,ON,1\x0D";
var relay02on = "FN,ON,2\x0D";
var relay03on = "FN,ON,3\x0D";
var relay04on = "FN,ON,4\x0D";
var relay05on = "FN,ON,5\x0D";
var relay06on = "FN,ON,6\x0D";
var relay07on = "FN,ON,7\x0D";
var relay08on = "FN,ON,8\x0D";
var relay01off = "FN,OFF,1\x0D";
var relay02off = "FN,OFF,2\x0D";
var relay03off = "FN,OFF,3\x0D";
var relay04off = "FN,OFF,4\x0D";
var relay05off = "FN,OFF,5\x0D";
var relay06off = "FN,OFF,6\x0D";
var relay07off = "FN,OFF,7\x0D";
var relay08off = "FN,OFF,8\x0D";
Action<string> HandleStringReceived = (string message) => {
// this will be called every time a message is received from the tcp channel
Program.Notify("Server String", message);
string status = "";
if (message == ">FN,OUT,OFF,1") // Relay module send this command every 5s (The identifier can be specified in the admin interface device!)
{
TcpClient.SendMessage("FN,SRE\x0D");; //Get status message
}
else if (message.Length >1) //This should be a condition that is certainly, on the basis that this status message. I think that the status message is longer than 130 characters.
{
for (int i =0; i <message.Length; i++)
{
if ((message[i].ToString() == ">") && (i>9))
{
if (message[i-11].ToString() == "F")
{
status = "0";
}
else
{
status = "1";
}
var module = SettingSwitchModules.WithAddress((Convert.ToByte(message[i-9])).ToString()).Get();
if ((module.Parameter("Status.Level").DecimalValue).ToString() != status)
{
//Switch the virtual switches status to relays status
module.Toggle();
}
}
}
}
};
Action<byte[]> HandleMessageReceived = (byte[] message) => {
// this will be called every time a message is received from the tcp channel
//Program.Notify("Server Bytes", BitConverter.ToString(message));
};
Action<bool> HandleStatusChanged = (bool connected) => {
// this will be called whenever the tcp connection status has changed
Program.Notify("TCP Client", "Connected = " + connected);
};
Program.Notify("TCP Client", "Starting");
// open the TCPIP port channel and register handlers
TcpClient.EndOfLine = "\n\r"; // default is "\n"
TcpClient
.OnStringReceived( HandleStringReceived )
.OnMessageReceived( HandleMessageReceived )
.OnStatusChanged( HandleStatusChanged )
.Service( remoteServer )
.Connect( remotePort );
Program.Notify("TCP Client", "Started");
Program.Parameter("Status.Level").Value = "0";
// We want to do further processing whenever a module prop changes
When.ModuleParameterChanged( (module, property) => {
return true;
});
When.WebServiceCallReceived("HomeAutomation.SettingSwitch", ( args ) =>
{
string[] reqs = ((string)args).Split('/');
string switchnumber = reqs[1];
string command = reqs[2];
if (TcpClient.IsConnected)
{
var module = SettingSwitchModules.WithAddress(switchnumber).Get();
//
switch(command)
{
case "Control.On":
Program.RaiseEvent(module, "Status.Level", "1", "SettingSwitch");
switch(switchnumber)
{
case "1":
TcpClient.SendMessage(relay01on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "2":
TcpClient.SendMessage(relay02on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "3":
TcpClient.SendMessage(relay03on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "4":
TcpClient.SendMessage(relay04on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "5":
TcpClient.SendMessage(relay05on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "6":
TcpClient.SendMessage(relay06on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "7":
TcpClient.SendMessage(relay07on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "8":
TcpClient.SendMessage(relay08on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
}
break;
case "Control.Off":
Program.RaiseEvent(module, "Status.Level", "0", "SettingSwitch");
switch(switchnumber)
{
case "1":
TcpClient.SendMessage(relay01off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "2":
TcpClient.SendMessage(relay02off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "3":
TcpClient.SendMessage(relay03off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "4":
TcpClient.SendMessage(relay04off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "5":
TcpClient.SendMessage(relay05off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "6":
TcpClient.SendMessage(relay06off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "7":
TcpClient.SendMessage(relay07off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "8":
TcpClient.SendMessage(relay08off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
}
break;
case "Control.Toggle":
if (module.Parameter("Status.Level").DecimalValue == 0)
{
Program.RaiseEvent(module, "Status.Level", "1", "SettingSwitch");
switch(switchnumber)
{
case "1":
TcpClient.SendMessage(relay01on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "2":
TcpClient.SendMessage(relay02on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "3":
TcpClient.SendMessage(relay03on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "4":
TcpClient.SendMessage(relay04on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "5":
TcpClient.SendMessage(relay05on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "6":
TcpClient.SendMessage(relay06on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "7":
TcpClient.SendMessage(relay07on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
case "8":
TcpClient.SendMessage(relay08on);
Program.Notify("Control",(module.Instance.Name)+" On");
break;
}
}
else
{
Program.RaiseEvent(module, "Status.Level", "0", "SettingSwitch");
switch(switchnumber)
{
case "1":
TcpClient.SendMessage(relay01off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "2":
TcpClient.SendMessage(relay02off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "3":
TcpClient.SendMessage(relay03off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "4":
TcpClient.SendMessage(relay04off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "5":
TcpClient.SendMessage(relay05off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "6":
TcpClient.SendMessage(relay06off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "7":
TcpClient.SendMessage(relay07off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
case "8":
TcpClient.SendMessage(relay08off);
Program.Notify("Control",(module.Instance.Name)+" Off");
break;
}
}
break;
}
return "{ 'ResponseValue' : 'OK' }";
}
else
{
Program.Notify("TCP client disconnected", "Unable to deliver message.");
}
return true;
});
Program.GoBackground();
-
The previous code did not work because it explores this issue:
"(>FN,OUT,OFF,1{0A}{0D}>FN,OUT,OFF,2{0A}{0D}>FN,OUT,OFF,3{0A}{0D}>FN,OUT,OFF,4{0A}{0D}>FN,OUT,OFF,5{0A}{0D}>FN,OUT,OFF,6{0A}{0D}>FN,OUT,OFF,7{0A}{0D}>FN,OUT,OFF,8{0A}{0D}>)"
The previous code goes through the text, and ">" character looking for (The first was skipped). If found, stop, then back nine characters. That will be the number of the relay. Then back eleven characters, there is examining the last character of the state. If character is "F" (Off), the status is "0". Otherwise, the character is "N" (On), the status is "1".
These compare the state of the relay. And if it does not match, then it will switch over.
Then go on to the next ">" characters.
But you do not get the reply message in the long form.
But rather this: ">FN,OUT,ON,8"
So following code will be good:
Action<string> HandleStringReceived = (string message) => {
// this will be called every time a message is received from the tcp channel
Program.Notify("Server String", message);
string status = "";
if (message=="3E") // Relay module send this command every 5s (The identifier can be specified in the admin interface device!)
{
TcpClient.SendMessage("FN,SRE\r"); //Get status message
}
else if (message[0].ToString() == ">") //This should be a condition that is certainly, on the basis that this status message. I think that the status message first character is ">".
{
if (((message.Length)-3).ToString() == "F")
{
status = "0";
}
else
{
status = "1";
}
var module = SettingSwitchModules.WithAddress((Convert.ToByte(message.Length-1)).ToString()).Get();
if ((module.Parameter("Status.Level").DecimalValue).ToString() != status)
{
//Switch the virtual switches status to relays status
module.Toggle();
}
}
};
-
Hi
After a lot of testing it works, but
Channel 1 not received the status from the unit.
channel 2 to 8 change to the real position.
You can see in the log it's accept the changing in the CH 1 and return from true to false but it isn't change the status.
log for ch1 on/off and ch2 on.
1:39:24.433 PM Program.Notification {"Title":"module:","Message":"HomeGenie.Automation.Scripting.ModuleHelper"} 27 HomeAutomation.HomeGenie.Automation
1:39:24.432 PM Program.Notification {"Title":"in else:","Message":"True"} 27 HomeAutomation.HomeGenie.Automation
1:39:24.432 PM Program.Notification {"Title":"staus:","Message":"True"} 27 HomeAutomation.HomeGenie.Automation
1:39:24.431 PM Program.Notification {"Title":"messsage:","Message":"FN,OUT,ON,1"} 27 HomeAutomation.HomeGenie.Automation
1:39:24.431 PM Program.Notification {"Title":"Server String","Message":"FN,OUT,ON,1"}
1:40:20.711 PM Program.Notification {"Title":"module:","Message":"HomeGenie.Automation.Scripting.ModuleHelper"} 27 HomeAutomation.HomeGenie.Automation
1:40:20.710 PM Program.Notification {"Title":"in else:","Message":"False"} 27 HomeAutomation.HomeGenie.Automation
1:40:20.709 PM Program.Notification {"Title":"staus:","Message":"False"} 27 HomeAutomation.HomeGenie.Automation
1:40:20.709 PM Program.Notification {"Title":"messsage:","Message":"\r>FN,OUT,OFF,1"} 27 HomeAutomation.HomeGenie.Automation
1:40:20.709 PM Program.Notification {"Title":"Server String","Message":"\r>FN,OUT,OFF,1"}
1:41:03.109 PM Program.Notification {"Title":"Control","Message":" On"} 27 HomeAutomation.HomeGenie.Automation
1:41:03.109 PM Status.Level 1 2 HomeAutomation.SettingSwitch
1:41:03.108 PM Program.Notification {"Title":"module:","Message":"HomeGenie.Automation.Scripting.ModuleHelper"} 27 HomeAutomation.HomeGenie.Automation
1:41:03.107 PM Program.Notification {"Title":"in else:","Message":"True"} 27 HomeAutomation.HomeGenie.Automation
1:41:03.107 PM Program.Notification {"Title":"staus:","Message":"True"} 27 HomeAutomation.HomeGenie.Automation
1:41:03.107 PM Program.Notification {"Title":"messsage:","Message":"\r>FN,OUT,ON,2"} 27 HomeAutomation.HomeGenie.Automation
1:41:03.107 PM Program.Notification {"Title":"Server String","Message":"\r>FN,OUT,ON,2"}
code
var remoteServer = "192.168.1.147"; //server IP address
var remotePort = 7078; //TCP port
var SettingSwitchModules = Modules.InDomain("HomeAutomation.SettingSwitch");
//Relays control commands
var relay01on = "FN,ON,1\x0D";
var relay02on = "FN,ON,2\x0D";
var relay03on = "FN,ON,3\x0D";
var relay04on = "FN,ON,4\x0D";
var relay05on = "FN,ON,5\x0D";
var relay06on = "FN,ON,6\x0D";
var relay07on = "FN,ON,7\x0D";
var relay08on = "FN,ON,8\x0D";
var relay01off = "FN,OFF,1\x0D";
var relay02off = "FN,OFF,2\x0D";
var relay03off = "FN,OFF,3\x0D";
var relay04off = "FN,OFF,4\x0D";
var relay05off = "FN,OFF,5\x0D";
var relay06off = "FN,OFF,6\x0D";
var relay07off = "FN,OFF,7\x0D";
var relay08off = "FN,OFF,8\x0D";
Action<string> HandleStringReceived = (string message) => {
// this will be called every time a message is received from the tcp channel
Program.Notify("Server String", message);
//string status = "";
var tokens = message.Split(',');
var status = tokens[tokens.Length-2].Equals("ON");
var channel = double.Parse(tokens[tokens.Length-1]);
Program.Notify("messsage:", message);
Program.Notify("staus:", status.ToString());
if (message.StartsWith("") || (message.StartsWith("\r>") || (message.StartsWith("\r>FN,OUT")))) //This should be a condition that is certainly, on the basis that this status message. I think that the status message first character is ">".
{
Program.Notify("in else:", status.ToString());
var module = SettingSwitchModules.WithAddress(channel.ToString()).Get();
Program.Notify("module:", module.ToString());
if (module.Parameter("Status.Level").DecimalValue != channel)
{
if (status)
module.Command("Control.On").Execute();
else
module.Command("Control.Off").Execute();
}
}
};
Br
kobi
-
I think, it's wrong:
if (module.Parameter("Status.Level").DecimalValue != channel)
Here, the switch status is compared with the switch ID.
So,
The status can be 0 or 1.
The channel ID can be 1,2,3,4,5,6,7,8