more G-Labs products

Author Topic: 8 Channel Ethernet Relay Switch by P5 (Help to build module)  (Read 2734 times)

March 16, 2015, 10:56:40 AM
Read 2734 times

kobi.beja

  • *
  • Information
  • Newbie
  • Posts: 21
Hi
I got two products of P5 (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 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.

Code: [Select]
//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

March 16, 2015, 07:22:56 PM
Reply #1

KaZe

  • ****
  • Information
  • Sr. Member
  • Posts: 219
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:
Code: [Select]
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();  
                  }
                }                 
    }
« Last Edit: March 16, 2015, 08:13:35 PM by KaZe »

March 18, 2015, 07:41:21 AM
Reply #2

kobi.beja

  • *
  • Information
  • Newbie
  • Posts: 21
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

March 19, 2015, 08:12:09 PM
Reply #3

KaZe

  • ****
  • Information
  • Sr. Member
  • Posts: 219
Hi!

If your status message is string, than you receive a message this section:

Code: [Select]
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:

Code: [Select]
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.

March 20, 2015, 01:24:05 AM
Reply #4

kobi.beja

  • *
  • Information
  • Newbie
  • Posts: 21
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

Code: [Select]
//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();

« Last Edit: March 20, 2015, 01:27:07 AM by kobi.beja »

March 20, 2015, 08:56:52 AM
Reply #5

KaZe

  • ****
  • Information
  • Sr. Member
  • Posts: 219
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:
Code: [Select]
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();  
          }
       
     }
 
};
« Last Edit: March 20, 2015, 11:37:41 AM by KaZe »

March 26, 2015, 12:51:50 PM
Reply #6

kobi.beja

  • *
  • Information
  • Newbie
  • Posts: 21
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

Code: [Select]
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

March 27, 2015, 08:41:33 AM
Reply #7

KaZe

  • ****
  • Information
  • Sr. Member
  • Posts: 219
I think, it's wrong:
Code: [Select]
         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