Turn Relay Switch On and Off from Python 3

I have a High-Power Relay Controller 2-Channel + 8 Channel ADC ProXR Lite. In NCD Base Comm Operator I am able to open a TCP client connection and send API codes in decimal format to turn it on and off. Turn on 254 108 1 and to turn it off I send 254 100 1. Is there a way to turn on and off this relay switch in python? Below is what I have been trying in python but seem to have no luck! Any help would be greatly appreciated!

#importing packages 
import socket
import serial
from industrial_relay.ncd_industrial_relay import Relay_Controller

#connect the socket using IP address and Port
IP_ADD = '192.168.1.54'
PORT = 2101

#set up socket with desired settings
#AF_INET refers to the address family ipv4
#SOCK_STREAM means connection oriented TCP protocol
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

board = Relay_Controller(sock)

sock.connect((IP_ADD, PORT))

board.turn_on_relay_by_index(1)

#sock.close()

Am I using the ncd industrial relay package wrong? Or is there a way that I can send the API code directly to the controller once the socket is open? All I need to to is turn the controller on and off.

Thanks!

Can you post the error message you’re getting when you run this code?

You’re not closing the socket at the end of the script. While garbage collection will clean it up on your system, if the ethernet or WiFi device you’re controlling doesn’t receive a graceful socket closure it can be left assuming the socket is still open. I usually recommend setting a timeout on the module to avoid this just in case.

Also if Comm Operator still has a socket open to the board then nothing else will be able to access that port on the board.

@jacob
Here is the code that I ran with the error message. I ran it with sock.close() this time. I also made sure that comm operator was closed.

import socket
import serial
from industrial_relay.ncd_industrial_relay import Relay_Controller

#connect the socket using IP address and Port
IP_ADD = '192.168.1.54'
PORT = 2101

#ON_SWITCH = '254 108 1'.decode('dec')

#set up socket with desired settings
#AF_INET refers to the address family ipv4
#SOCK_STREAM means connection oriented TCP protocol
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

board = Relay_Controller(sock)


sock.connect((IP_ADD, PORT))


board.turn_on_relay_by_index(1)

sock.close()


  File "C:\Users\Documents\relay_switch\codes\industrial_relay\ncd_industrial_relay.py", line 122, in send_command
    self.combus.send(command)

TypeError: a bytes-like object is required, not 'list'

Can you try going into the library and uncommenting line 117: command = self.convert_data(command)

There is an incompatibility with some environments where it requires this.

If that doesn’t fix it, send me over the OS you’re running and the version of python including minor version number and I’ll see if I can troubleshoot this.

Actually even if it does work let me know what OS and Python version you’re running if you would.

This would help me track down the incongruity.

I uncommented line 117 and got this error.
Windows 10 Python 3.6.8 |Anaconda, Inc.| (default, Feb 11 2019, 15:03:47) [MSC v.1915 64 bit (AMD64)]

  File "C:\Users\Documents\relay_switch\codes\industrial_relay\ncd_industrial_relay.py", line 121, in send_command
    self.combus.send(command)

TypeError: a bytes-like object is required, not 'str'

Would there be a way to just send the decimal format to the switch (254 108 1) like in the comm operator?

Thank you for the information.

You can once you open the TCP socket you can simply use sock.send(). Just make sure that you are sending raw bytes to the board over the socket or it won’t understand the command.

Thanks!

How do you convert 254 108 1 to raw bytes?

Generally you can use bytearray(254,108,1), but socket.send may not like that.

I just tested on a windows machine I had laying around and if you change line 123:
return self.combus.recv(bytes_back)
to:
return self.combus.recv(bytearray(bytes_back))
it should work for you.

Thanks for your help! I changed line 123 but it still did not work for me. I got an error saying:

  File "C:\Users\Documents\relay_switch\codes\industrial_relay\ncd_industrial_relay.py", line 122, in send_command
    self.combus.send(command)

TypeError: a bytes-like object is required, not 'str'

It worked sending the byte array though!

my_bytes = bytearray()
my_bytes.append(254)
my_bytes.append(108)
my_bytes.append(1)
sock.send(my_bytes)

That’s great!

I also messed up and sent the wrong line of code to alter.

It should have been line 122:
self.combus.send(bytearray(command))

My bad there.

I’ll try and find some time to test this on my mac and a Raspberry Pi as this may solve the incongruities between environments. Also need to update the examples to Python3 (old habit not to function wrap prints())