IP controlled relay board

If you have a question or need help, this is the place to be.
Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

IP controlled relay board

Post by Peter M » Sun Jul 07, 2019 6:44 am

Hi,

I'm quite new to EG and know no python at all. The last real coding I did was in Fortran under Unix on the first gen of Sun Sparcstations in the late 80's !! :shock:

I'm using Demopad to control a home theatre system and EG runs under Win10 on an Intel NUC. It's mainly used to control JRiver which plays multi-channel music and concert rips from a NAS drive.

The latest addition to the system is an IP controlled power box that I built around this board from DFRobot -

https://www.dfrobot.com/product-503.html

It's used to switch power on/off for the power amps which have no built-in control. Demopad controls the board well using simple commands over TCP/IP. It's the feedback from the board that's got me stumped. It returns a single byte which indicates the status of each of the 8 relays, but Demopad's feedback receiver demands a response terminator such as \x0D at the end of all communications, so Demopad can't directly catch the feedback. I've used Hercules to show that the board is responding correctly.

I'm hoping that EG may be able to solve my problem, using a procedure something like this -

1. On the Demopad power page there is a macro called Power Status repeating every 2 secs.
2. Into this macro add a command to EG called Amp Status.
3. This triggers a macro in EG which sends the Status command to the board (\x24 to 192.168.0.56 port 17494), receives one byte back from the board, appends \x0D to it, and sends it to Demopad using Broadcaster.
4. Demopad receives the feedback from EG and deals with it in the normal manner.

One of the guys in the Demopad thread at AVS Forum thought this would be doable with a python script. I don't really want to invest the time that I'm sure would be necessary to learn and understand python, so I guess I'm left with no option but to ask for someone to help me out.

Any and all assistance will be greatly appreciated !!

Cheers,
Peter M

User avatar
kgschlosser
Site Admin
Posts: 5504
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Sun Jul 07, 2019 9:20 pm

Ok it sounds as tho you have a bunch of components there.

I need to know who is talking to who.

I am not familiar with any of the products you are using so you are going to have to explain the orientation of the devices


If the device can be network controlled EG can handle any communications to and from it.

It sounds as tho the relay board has network communication capabilities. I am gathering the demopa does as well based on your statement that the demopad cannot handle a specific byte.

It sounds like you want control to be handled from the demopad and reporting by EG.. is this correct??

Or do you want EG to handle all communications to and from the relay board?? To do this EG will also have to have the ability to report state to the demopad and also receive when a control command from the demopad is used.

I have not seen a plug-in for a demopad. That does not mean that one does not exist. If there is a plug-in for it would you mind sending it to me so I can make a assessment of it's capabilities. The relay board is going to be a fairly simple API I would imagine simple one or 2 byte packets incoming or outgoing.


I will check out what a demopad is and also the relay board and see what I can put together
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 5504
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Sun Jul 07, 2019 9:39 pm

Ok I just looked at the API for the relay board. It has a very simple API.

Now.. the demo pad has sparked my interest. It is hard do determine what it exactly is. It appears to be a control4 type of a system with a controller and then the remotes. And the remotes talk to the controller and tells it what to do. But then on another place it appears as tho it is software based. So I am a little fuzzy on its functionality. But it appears as tho you can set the thing up to make network connections to devices and pass data to the device. I do not know the extent of it's ability to get state fr a device or if it has a poll loop that asks for the state or if the connection remains open and it will update state when data is set to the demopad.

One thing I can see being really useful with the demopad would be htpc control. Because the demopad is touchscreen based you could use the demopad as a touchpad to control mouse movements on an htpc. This would be really useful.
If you like the work I have been doing then feel free to Image

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Mon Jul 08, 2019 2:17 am

Demopad has three components -

1. A designer program which runs under Windows and is used to create the control system which is downloaded to -
2. An app that runs under iOS.
3. Hardware controllers (optional) which add functionality such as global variables for systems which include multiple instances of (2).

I'm only using (1) and (2).

If a device is IP controllable Demopad connects directly. If a device is RS232 or IR controllable then gateways (such as the Global Cache devices) are used to convert.

Demopad uses two way communications and as far as I know the connections remain open so that any communication from the device is handled by Demopad's feedback handler. The feedback handler has two methods - pattern match and data match. Pattern match is a full regex engine that can extract data from the feedback into either number or string variables. Data match just looks for a string match in the feedback and performs actions without extracting anything.

The API for the board is indeed very simple. The relays are being turned on/off by Demopad directly by sending commands such as -

relay 1 ON - \x20\x01\x00
relay 1 OFF - \x21\x01\x00

The command for Get Status is \x24 which returns a single byte.

My problem is that if Demopad issues the Get Status command then it cannot catch the feedback as there is no \x0D at the end and Demopad demands some sort of terminator to any feedback.

So I want to insert EG into this loop.

1. Demopad commands EG to check the relay status.
2. EG issues the \x24 command and receives a single byte back.
3. EG appends \x0D to the byte and sends it to Demopad.

Apologies if I'm being repetitive ... just trying to be thorough.

Cheers,
Peter

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Mon Jul 08, 2019 2:30 am

kgschlosser wrote:
Sun Jul 07, 2019 9:39 pm
One thing I can see being really useful with the demopad would be htpc control. Because the demopad is touchscreen based you could use the demopad as a touchpad to control mouse movements on an htpc. This would be really useful.
I've not tried this but Demopad does allow X,Y tracking on buttons which would should work for controlling a mouse. Set up a large button as a mouse touch pad and then the X,Y coordinates would be issued as commands to EG.

Cheers,
Peter

User avatar
kgschlosser
Site Admin
Posts: 5504
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Mon Jul 08, 2019 3:16 am

I am going to hit you with the solution that you already stated... now don't smack your head to hard when i tell you this.
Data match just looks for a string match in the feedback and performs actions without extracting anything.
you have 8 relays. and 2 possible states.. ON and OFF. so that makes for a total of 16 different bytes that can/will be returned. find out what those bytes are and do the data match to act accordingly.

Data match should not need a termination character. it will continue to stack bytes received until there is a match once it has a match then it will start the buffer process over from the beginning again. I do not know why they would require a termination character if they are simply matching characters.. there would be no need for it. and because of the very limited API instruction set for that relay board i would not imagine that any of the bytes would conflict. I am going to do some digging now that i am home. it is not easy to read code from a phone.
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 5504
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Mon Jul 08, 2019 4:42 am

ok so here is a code snippit you can paste into a python script and run.


You need to change the IP_ADDRESS variable to have the ip address of the relay board
If you have your device set up to use a password then you will need to change PASSWORD to be the password you are using

once you run the script it should display a new application window and there will be buttons for each of the eight relays. You can toggle the buttons on and off and it will turn a relay on and off.. what i am interested in is the data that gets spit out into the log when you do this. you will need to copy that data and paste it here for me to check out. we need to know what the data is that is being returned from the get command

Code: Select all

IP_ADDRESS = '192.168.1.1'
PASSWORD = 'SOME_PASSWORD'

import wx
import socket
from threading import Timer

def relay_property(func):
    relay_num = int(func.__name__[-1:])

    def fget(self):
        response = self.send('\x24')
        return response

    def fset(self, state):
        if state:
            command = [0x20]
        else:
            command = [0x21]

        command += [relay_num, 0x0]
        command = ''.join(chr(c) for c in command)
        response = self.send(command)

        if response is None:
            return

        if ord(response):
            print 'Command for relay {0} failed'.format(relay_num)
        else:
            print 'Command for relay {0} success'.format(relay_num)

    return property(fget=fget, fset=fset)

class ETH008(object):

    def __init__(self, ip):
        self.sock = None
        self.ip = ip
        self.timer = None
        self.password = None

    def connect(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.connect((self.ip, 17494))
            return True
        except socket.error:
            return False

    def logout(self):
        if self.timer is not None:
            self.timer.cancel()
            self.sock.send('\x7B')

        self.sock.shutdown(socket.SHUT_RDWR)
        self.sock.close()

    @relay_property
    def relay1(self):
        pass

    @relay_property
    def relay2(self):
        pass

    @relay_property
    def relay3(self):
        pass

    @relay_property
    def relay4(self):
        pass

    @relay_property
    def relay5(self):
        pass

    @relay_property
    def relay6(self):
        pass

    @relay_property
    def relay7(self):
        pass

    @relay_property
    def relay8(self):
        pass

    def _login(self, password, delay):
        try:
            self.sock.sendall('\x79' + password)
        except (socket.error, AttributeError):
            if self.connect():
                self.sock.sendall('\x79' + password)
            else:
                print 'Socket Connection problem'
                return

        self.timer = Timer(delay, self._login, args=[password, 30.0])
        self.timer.start()

    def login(self, password=None):
        try:
            self.sock.sendall('\x7A')
        except (socket.error, AttributeError):
            if self.connect():
                self.sock.sendall('\x7A')
            else:
                print 'Socket Connection problem'
                return False

        data = self.sock.recv(4096)
        if not data:
            print 'Socket Connection closed'
            return False

        if ord(data) != 255:
            if password is None:
                print 'Password is needed to login'
                return False

            data = ord(data)

            if data == 0:
                data = 30
            self._login(password, data)
            self.password = password

        else:
            if self.timer is not None:
                self.timer.cancel()
                self.timer = None
            self.password = None

        return True

    def send(self, command):
        try:
            self.sock.sendall(command)
        except (socket.error, AttributeError):
            if self.login(self.password):
                self.sock.sendall(command)
            else:
                print 'Socket Connection problem'
                return None

        data = self.sock.recv(4096)
        if not data:
            print 'Socket Connection closed'
            return None

        print ', '.join(hex(ord(char)) for char in list(data))
        return data


class Frame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, -1, size=(300, 100))

        eth008 = ETH008(IP_ADDRESS)
        eth008.login(PASSWORD)

        sizer = wx.BoxSizer(wx.HORIZONTAL)

        from wx.lib import buttons

        relay1 = buttons.GenToggleButton(self, -1, 'Relay 1')

        def on_relay_1(evt):
            eth008.relay1 = relay1.GetToggle()
            print eth008.relay1

        relay1.Bind(wx.EVT_BUTTON, on_relay_1)
        sizer.Add(relay1, 0, wx.EXPAND | wx.ALL, 5)

        relay2 = buttons.GenToggleButton(self, -1, 'Relay 2')

        def on_relay_2(evt):
            eth008.relay2 = relay2.GetToggle()
            print eth008.relay2

        relay2.Bind(wx.EVT_BUTTON, on_relay_2)
        sizer.Add(relay2, 0, wx.EXPAND | wx.ALL, 5)

        relay3 = buttons.GenToggleButton(self, -1, 'Relay 3')

        def on_relay_3(evt):
            eth008.relay3 = relay3.GetToggle()
            print eth008.relay3

        relay3.Bind(wx.EVT_BUTTON, on_relay_3)
        sizer.Add(relay3, 0, wx.EXPAND | wx.ALL, 5)

        relay4 = buttons.GenToggleButton(self, -1, 'Relay 4')

        def on_relay_4(evt):
            eth008.relay4 = relay4.GetToggle()
            print eth008.relay4

        relay4.Bind(wx.EVT_BUTTON, on_relay_4)
        sizer.Add(relay4, 0, wx.EXPAND | wx.ALL, 5)

        relay5 = buttons.GenToggleButton(self, -1, 'Relay 5')

        def on_relay_5(evt):
            eth008.relay5 = relay5.GetToggle()
            print eth008.relay5

        relay5.Bind(wx.EVT_BUTTON, on_relay_5)
        sizer.Add(relay5, 0, wx.EXPAND | wx.ALL, 5)

        relay6 = buttons.GenToggleButton(self, -1, 'Relay 6')

        def on_relay_6(evt):
            eth008.relay6 = relay6.GetToggle()
            print eth008.relay6

        relay6.Bind(wx.EVT_BUTTON, on_relay_6)
        sizer.Add(relay6, 0, wx.EXPAND | wx.ALL, 5)

        relay7 = buttons.GenToggleButton(self, -1, 'Relay 7')

        def on_relay_7(evt):
            eth008.relay7 = relay7.GetToggle()
            print eth008.relay7

        relay7.Bind(wx.EVT_BUTTON, on_relay_7)
        sizer.Add(relay7, 0, wx.EXPAND | wx.ALL, 5)

        relay8 = buttons.GenToggleButton(self, -1, 'Relay 8')

        def on_relay_8(evt):
            eth008.relay8 = relay8.GetToggle()
            print eth008.relay8

        relay8.Bind(wx.EVT_BUTTON, on_relay_8)
        sizer.Add(relay8, 0, wx.EXPAND | wx.ALL, 5)

        self.SetSizer(sizer)
        
        def on_close(evt):
            eth008.logout()                       
            evt.Skip()
            
        self.Bind(wx.EVT_CLOSE, on_close)
        self.Show()


if hasattr(eg.globals, 'frame'):
    try:
        eg.globals.frame.Destroy()
    except:
        pass

eg.globals.frame = Frame()
If you like the work I have been doing then feel free to Image

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Mon Jul 08, 2019 5:25 am

kgschlosser wrote:
Mon Jul 08, 2019 3:16 am
I am going to hit you with the solution that you already stated... now don't smack your head to hard when i tell you this.
Data match just looks for a string match in the feedback and performs actions without extracting anything.
you have 8 relays. and 2 possible states.. ON and OFF. so that makes for a total of 16 different bytes that can/will be returned. find out what those bytes are and do the data match to act accordingly.

Data match should not need a termination character. it will continue to stack bytes received until there is a match once it has a match then it will start the buffer process over from the beginning again. I do not know why they would require a termination character if they are simply matching characters.. there would be no need for it. and because of the very limited API instruction set for that relay board i would not imagine that any of the bytes would conflict. I am going to do some digging now that i am home. it is not easy to read code from a phone.
It really does return only one byte in response to the \x24 command ... when converted to binary the 8 bits give the status of the 8 relays ... 0 for relay off, 1 for relay on.

Demopad support have confirmed via email that without a termination character it will not capture and process any feedback.

Cheers,
Peter

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Mon Jul 08, 2019 5:41 am

kgschlosser wrote:
Mon Jul 08, 2019 4:42 am
ok so here is a code snippit you can paste into a python script and run.

You need to change the IP_ADDRESS variable to have the ip address of the relay board
If you have your device set up to use a password then you will need to change PASSWORD to be the password you are using

once you run the script it should display a new application window and there will be buttons for each of the eight relays. You can toggle the buttons on and off and it will turn a relay on and off.. what i am interested in is the data that gets spit out into the log when you do this. you will need to copy that data and paste it here for me to check out. we need to know what the data is that is being returned from the get command
Thanks. Will give this a go tonight.

I've previously used the board's web interface and captured the comms with Wireshark, but I couldn't make sense of it. I tried a GET command and rather than returning the status it turned all the relays off !

If we can figure out the correct GET command I can issue that directly from Demopad and hopefully it will be able to parse the resulting feedback.

Cheers,
Peter

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Mon Jul 08, 2019 10:28 am

I've copied and pasted the code. The board is configured to not require a password so I've commented out that line, but obviously there's more to be done as this is the resulting log -

Traceback (most recent call last):
Python script "10", line 258, in <module>
eg.globals.frame = Frame()
Python script "10", line 164, in __init__
eth008.login(PASSWORD)
NameError: global name 'PASSWORD' is not defined

I then tried this -

PASSWORD = ''

And this is the log -

Traceback (most recent call last):
Python script "11", line 258, in <module>
eg.globals.frame = Frame()
Python script "11", line 164, in __init__
eth008.login(PASSWORD)
Python script "11", line 106, in login
self.sock.sendall('\x7A')
AttributeError: 'NoneType' object has no attribute 'sendall'

Cheers,
Peter

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Mon Jul 08, 2019 10:33 am

I then commented out lines 2 and 164.

This time it ran and the application window opened. Clicking on a relay button gave this -

Traceback (most recent call last) (1722):
File "12", line 173, in on_relay_1
File "12", line 23, in fset
File "12", line 141, in send
AttributeError: 'NoneType' object has no attribute 'sendall'

Cheers,
Peter

User avatar
kgschlosser
Site Admin
Posts: 5504
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Wed Jul 10, 2019 2:31 am

ok i updated the script in the previous post..

the PASSWOD must stay. if you do not have the password feature turned on then just ignore doing anything with it. the script will handle what needs to be done.
If you like the work I have been doing then feel free to Image

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Wed Jul 10, 2019 7:38 am

Running the code and clicking on four separate buttons gave this log -

Socket Connection problem
Socket Connection problem
Socket Connection problem
Socket Connection problem
Socket Connection problem
None
Socket Connection problem
Socket Connection problem
Socket Connection problem
Socket Connection problem
None
Socket Connection problem
Socket Connection problem
Socket Connection problem
Socket Connection problem
None
Socket Connection problem
Socket Connection problem
Socket Connection problem
Socket Connection problem
None

It was also very slow to respond to anything I did.

Cheers,
Peter

Peter M
Posts: 46
Joined: Tue Jun 18, 2019 5:13 am

Re: IP controlled relay board

Post by Peter M » Wed Jul 10, 2019 7:40 am

Trying to close the app window gave this log -

Traceback (most recent call last) (1722):
File "2", line 245, in on_close
File "2", line 56, in logout
File "<string>", line 1, in shutdown
error: [Errno 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied

Cheers,
Peter

User avatar
kgschlosser
Site Admin
Posts: 5504
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: IP controlled relay board

Post by kgschlosser » Wed Jul 10, 2019 9:23 am

it was late when i wrote that thing. I will have a gander at it tomorrow morning.
If you like the work I have been doing then feel free to Image

Post Reply