ValueError: invalid literal for int() with base 10: 'Oompa Loompa\x07\x08' - tcp

I have the TCP server set up for receiving messages from connected clients, but when the message contains packed hex e.g "Oompa Loompa\x07\x08" it shows me this error:
ValueError: invalid literal for int() with base 10: 'Oompa Loompa\x07\x08'
I guess I have decoding issue in the code but I don't know how to fix it.
import socket
import threading
HEADER = 64
PORT = 5050
SERVER = "192.168.1.103"
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg == DISCONNECT_MESSAGE:
connected = False
print(f"[{addr}] {msg}")
conn.send("Msg received".encode(FORMAT))
conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[Active Clients] {threading.active_count() - 1}")
print("[BOOTING] server is starting...")
start()

It seems like hex is a strings and needs to be an int. Try sending that message in binary.

Related

pymodbus does not read registers

I am developing a program to read Modbus data via serial RTU using pymodbus.
My purpose is to read data from an ABB XRCG4 Xseries flow computing PC. I know that the COM port on the device side is COM1 and the serial protocol is RS232, on my PC, using a serial converter I am trying to connect to it.
I know the configuration as follows:
PROTOCOL= 'rtu'
USB_PORT = 'COM4'
PARITY = 'None'
BAUD_RATE = 9600
TIMEOUT = 3
For test purposes I made an Arduino board into a Modbus Slave. I can read the data from the board with QModMaster, Modbus Pool and SimplyModbusMaster but I am unable to do so with my script. For the board I am unable to read anything at all, not eve with the programs mentioned above.
When I use the above mentioneds program to read data from the Arduino, everything works fine, when I try with my script, I get the AttributeError: 'ModbusIOException' object has no attribute 'registers'
I also noticed that I get this error if I unplug the cable while connection is running.
What am I missing? My guess is that I might not have a hardware dealer for the dsrdtr exchange, according to page 24 of the pymodbus documentation or maybe on the board side, the Register Format is not ok for my code.
Here you can see the details from the ABB board
Port description part1
Port description part2
My code:
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.client.sync import *
from pymodbus.register_read_message import *
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.compat import iteritems
from pymodbus.exceptions import *
import time
import logging
import logging.handlers as Handlers
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
USB_PORT = 'COM4'
PARITY = 'N' #'N'
BAUD_RATE = 9600
TIMEOUT = 0.15
client = ModbusClient(method='rtu',
port=USB_PORT,
stopbits=1,
bytesize=8,
parity=PARITY,
baudrate=BAUD_RATE,
timeout=TIMEOUT, )
while True:
connection = client.connect()
#print(client.)
print(f"COM Details {client.socket}")
#client.socket.setRTS(True)
print(f"Connection status is: {connection} \nClient State: {client.state} \nTimeout: {client.timeout}")
#print(client.get_serial_settings)
try:
#################################### CITIM INPUT REGISTER (adresa,nr de registrii si unit ID
input_value = client.read_input_registers(count=0x01,address=10,unit=0x01)
#client.socket.setRTS(False)
print(input_value)
decoder = BinaryPayloadDecoder.fromRegisters(input_value.registers, byteorder=Endian.Little)
decoded = {
'string': decoder.decode_string(8),
'float': decoder.decode_32bit_float(),
'16uint': decoder.decode_16bit_uint(),
'ignored': decoder.skip_bytes(2),
#'8int': decoder.decode_8bit_int(),
'bits': decoder.decode_bits(),}
############### CITIM HOLDING REGISTER (exemplu, modelul vantilatorului)
holding_values = client.read_holding_registers(0xD1A5,6,unit=0x01)
holding_decoder = BinaryPayloadDecoder.fromRegisters(holding_values.registers, byteorder=Endian.Big)
holding_decoded = {
'string': holding_decoder.decode_string(8),
#'float': holding_decoder.decode_32bit_float(),
#'16uint': holding_decoder.decode_16bit_uint(),
'ignored': holding_decoder.skip_bytes(2),
#'8int': holding_decoder.decode_8bit_int(),
'bits': holding_decoder.decode_bits(),
}
print("-" * 60)
print("INPUT REGISTERS:")
print("-" * 60)
print(f"\nResponse: {input_value.registers} \nInput Registers Decoded values: \n")
for name, value in iteritems(decoded):
print ("%s\t" % name, value)
print(f"\n Decoded speed: {decoded['float']}")
print(f"Holding values registers:\n {holding_values.registers}")
print("-" * 60)
print("Holding Values Decoded Data")
print("-" * 60)
for name, value in iteritems(holding_decoded):
print ("%s\t" % name, value)
except ConnectionException as e:
print(f"USB Disconnected {e}")
time.sleep(2)
client.close()

why do I see TypeError for python socket module?

I am learning python, and these days I am trying to work with socket module. Below is the client side logic.
import socket
from threading import Thread
import ipaddress
lic_server_host = input("Please enter the hostname: ")
port = input("Please enter the License service port number: ")
client_socket = socket.socket()
client_socket.connect((lic_server_host, port))
def receive_data():
while True:
data = client_socket.recv(1000)
print(data.decode())
def sending_data():
while True:
user_input = input()
client_socket.sendall(user_input.encode())
t = Thread(target=receive_data)
t.start()
sending_data()
Here I am taking user's input as a hostname. However. The above porgram is not able to convert the hostname to integer. I am getting below error
client_socket.connect((lic_server_hostname, port))
TypeError: an integer is required (got type str)
I tried to use some python way to get rid of the issue by introducing for loop on the user's input as below
lic_server_host = input("Please enter the License server hostname: ")
for info in lic_server_hostname:
if info.strip():
n = int(info)
port = input("Please enter the License service port number: ")
client_socket = socket.socket()
client_socket.connect((n, port))
But now I get below error:
client_socket.connect((n, port))
TypeError: str, bytes or bytearray expected, not int
So based on the error I used str() function on "n". But when I do that I get below error:
n = int(info)
ValueError: invalid literal for int() with base 10: 'l'
I have also searched for the above error available on the internet but the solutions not helping me.
Please help me understand my mistake.
Thank you
input returns a string when connect requires port as int.
client_socket.connect((lic_server_host, int(port)))

GUI user input send TCP command

I would like to create a pop up window that queries for input that will route that input as a string to port 9090. What is wrong with my code?
import socket
host = "127.0.0.1"
port = 9090
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
def goto(prompt):
cue = input(prompt)
while cue not in ("exit", "done"):
cue = input(prompt)
byt = cue.encode()
s.send(byt)
return cue
print(goto("cue?"))
from Tkinter import *
root = Tk()
root.title('Name')
e = Entry(root)
e.pack()
e.focus_set()
b = Button(root,text='okay',command=goto())
b.pack(side='bottom')
root.mainloop()

Tornado receive UDP packets from multicast group

I have a server where I want to receive data from multicast group. Is there any inbuilt function that I can use to receive this multicast UDP packets?
Edit: Code implementation
I have implemented the code and that follows like this:
#!/usr/bin/env python
import socket
import struct
import os
import errno
import binascii
import tornado.ioloop
from tornado.ioloop import IOLoop
from tornado.platform.auto import set_close_exec
class UDPHandler():
"""
Connect to multicast group
"""
def __init__(self, ip, port, io_loop):
self.io_loop = io_loop
self._multiIP = ip
self.port = port
self._sock = None
self._socket = {} # fd -> socket object
def conn(self):
"""
Listner to multicast group
"""
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._sock.settimeout(3)
self._sock.bind(('', self.port))
self._sock.setblocking(0)
group = socket.inet_aton(self._multiIP)
mreq = struct.pack('4sL', group, socket.INADDR_ANY)
self._sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
self._socket[self._sock.fileno()] = self._sock
print("self._sock:", self._sock)
def onRx(self, data, addr):
print("addr, data:", addr, len(str(data)))
print(data)
def r(self):
self.conn()
add_socket_handler(self._sock, self.onRx, self.io_loop)
def add_socket_handler(sock, callback, io_loop):
def accept_handler(fd, events):
while True:
try:
data, address = sock.recvfrom(1024)
except socket.error as e:
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
callback(None, None)
except Exception as e:
print("except:", e)
callback(None, None)
callback(data, address)
io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ)
def periodic():
# print("periodic")
None
def main():
MULTICAST_IP = "224.1.1.10"
RECEIVE_PORT = 10003
udpRx = UDPHandler(MULTICAST_IP, RECEIVE_PORT, tornado.ioloop.IOLoop.current())
udpRx.r()
tornado.ioloop.PeriodicCallback(periodic, 1000).start()
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()
Now the problem is is am getting same packet in a loop even if I receive one packet I am receiving the same packet over and over again. Is there something wrong with the code? Especially with add_socket_handler?
Edit 2:
I have added a break statement in the while loop that I had in add_socket_handler and now it seems to be working good.
def add_socket_handler(sock, callback, io_loop):
def accept_handler(fd, events):
while True:
try:
data, address = sock.recvfrom(1024)
callback(data, address)
except socket.error as e:
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
raise
except Exception as e:
raise
break ## change in here
io_loop.add_handler(sock.fileno(), accept_handler, io_loop.READ)
Is this how it is suppose to be done ?
The break in your add_socket_handler looks backwards. You want to loop until you get EWOULDBLOCK/EAGAIN. (with the break as written, it will still work, but it will be slightly less efficient and might miss packets).
def add_socket_handler(sock, callback, io_loop):
def read_handler(fd, events):
while True:
try:
data, address = sock.recvfrom(1024)
callback(data, address):
except socket.error as e:
if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN):
return
raise
io_loop.add_handler(sock, read_handler, io_loop.READ)
Other than that, this looks right, although I haven't worked with multicast UDP myself.

Operating Micropython-running WeMos D1 mini (ESP8266) pins with HTTP requests

What I am trying to ultimately achieve is to control my garage door opener with a relay connected to a WeMos D1 Mini, connected to my home WiFi. I am using the openGarageDoor() function. Everything works fine with serial connection.
I have been trying to run HTTP server on a WeMos D1 Mini with this script.
customertagsAction() -- try:
import usocket as socket
except:
import socket
CONTENT = b"""\
HTTP/1.0 200 OK
Hello #%d from MicroPython!
"""
def main(micropython_optimize=False):
s = socket.socket()
# Binding to all interfaces - server will be accessible to other hosts!
ai = socket.getaddrinfo("0.0.0.0", 8080)
print("Bind address info:", ai)
addr = ai[0][-1]
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(5)
print("Listening, connect your browser to http://<this_host>:8080/")
counter = 0
while True:
res = s.accept()
client_sock = res[0]
client_addr = res[1]
print("Client address:", client_addr)
print("Client socket:", client_sock)
if not micropython_optimize:
# To read line-oriented protocol (like HTTP) from a socket (and
# avoid short read problem), it must be wrapped in a stream (aka
# file-like) object. That's how you do it in CPython:
client_stream = client_sock.makefile("rwb")
else:
# .. but MicroPython socket objects support stream interface
# directly, so calling .makefile() method is not required. If
# you develop application which will run only on MicroPython,
# especially on a resource-constrained embedded device, you
# may take this shortcut to save resources.
client_stream = client_sock
print("Request:")
req = client_stream.readline()
print(req)
while True:
h = client_stream.readline()
if h == b"" or h == b"\r\n":
break
print(h)
client_stream.write(CONTENT % counter)
client_stream.close()
if not micropython_optimize:
client_sock.close()
counter += 1
print()
main()
The requests are received properly and the GET variables are shown on the print(). The best i have been able to do is
req = client_stream.readline()
print(req)
while True:
h = client_stream.readline()
if h == b"" or h == b"\r\n":
break
print(h)
client_stream.write(CONTENT % counter)
//my function here:
if 'opengaragedoor=1' in req:
openGarageDoor()
client_stream.close()
I don't know how to parse the request properly. I only have come up with this dirty solution. This probably causes a timeout on the requesting system, as Postman or such needs to wait for the function to run through.

Resources