String element counting doesn't work [Python] - python

I'm programming a simple server socket interface (like a console). I tryed to implement a SEND TO xxx.xxx.xxx.xxx command to send some information or commands to the client at ip address xxx.xxx.xxx.xxx. So I tryed writing this code (it is inside a class and this is the reason why appears the self parameter):
while True:
# other statements
# asking an input from the user
command = input(f"[Server] >>> ")
if command.startswith("SEND TO ") and \
re.match(r"^([A-Z\s]){7}\s([0-9]{1,3}\.){3}([0-9]{1,3})$", command):
# getting the ip address
ip_address = command[8:]
# ip lists (from self.__clients which is the list of connected
# clients)
ip_list = [str(c.getpeername()[0]) for c in self.__clients]
# count the occurrencies of the chosen ip (this because there can be
# multiple client connected from the same computer)
matching_ip = ip_list.count(str(ip_address))
# trying to print the results for debugging the code
print(matching_ip)
print(ip_list)
print(ip_address)
And this is the console:
[Server] >>> SEND TO 111.111.1.11
0
['111.111.1.11', '111.111.1.11']
111.111.1.11
I can't figure out why even if there are 2 occurrencies of the same ip, the matching ip variable remains to the value 0. When I try to copy the ip from the previous output (using the mouse and CTRL+C) and paste (CTRL-V) to a new line, using the same SEND TO command it works, and it is returned:
# where 111.111.1.11 is copied from the previous output (this works even if
# I copy 111.111.1.11 from a previous program run and i paste it for the
# first time in the current run)
[Server] >>> SEND TO 111.111.1.11
2
['111.111.1.11', '111.111.1.11']
111.111.1.11
Any advices to fix this?
Thank you very much for your time and excuse my English, I'm still practising it

Related

Tkinter Entry box data format

Getting a set of variables on a tkinter (Python GUI) entry box (on a RPi) in order to ping an ip address, check a usb device's presence(with VID & PID) and to check a com port.
However when the GUI takes in the data, the function runs, but the variables taken from the entry are not executed properly.
i tried converting the input of ip address to string and vid and pid to int, same for com port entries. but the code still won't run.
scripts to ping IP and to check for usb devices(not the full code):
response = os.system("ping -c 1 " + self.ip_address)
pings ip and returns answer according to response
dev = usb.core.find(idVendor=self.vid, idProduct= self.pid)
checks usb and returns answer according to response
tkinter settings:
entry_IP = Entry(second_frame, bg="white")
entry_IP.grid(row=4,column=1,padx=0,pady=5)
str_IP=entry_IP.get()
main code:
RM=classname(str_IP,int_VID,int_PID)
RM.check_IP()
RM.check_USB()
i expected the code to run or not, but instead its always telling me the device(s) is not there.
when i run the function alone without a tkinter entry it works just fine !
When you define str_IP, the entry contains nothing, and so it will equal to an empty string. You should retrieve the IP directly by passing RM=class name(entry.get(),...)

Python's pyserial with interrupt mode

I have a device which works on serial communication. I am writing python code which will send some commands to get the data from the device.
There are three commands.
1.COMMAND - sop
Device does its internal calculation and sends below data
Response - "b'SOP,0,921,34,40,207,0,x9A\r\n'"
2.COMMAND - time
This gives a date time values which normally do not change untill the device is restarted
3.START - "\r\r" or (<cr><cr>)
This command puts the device in responsive mode after which it responds to above commands. This command is basically entering <enter> twice & only have to do once at the start.
Now the problem which I am facing is that, frequency of data received from sop command is not fixed and hence the data is received anytime. This command can also not be stopped once started, so if I run another command like time, and read the data, I do not receive time values and they are merged with the sop data sometime. Below is the code, I am using:
port = serial.Serial('/dev/ttyS0',115200) #Init serial port
port.write(("\r\r".encode())) #Sending the start command
bytesToRead = port.in_waiting #Checking data bytesize
res = port.read(bytesToRead) #Reading the data which is normally a welcome msg
port.reset_input_buffer() #Clearing the input serial buffer
port.reset_output_buffer() #Clearing the output serial buffer
port.write(("sop\r".encode())) #Sending the command sop
while True:
time.sleep(5)
bytesToRead = port.in_waiting
print(bytesToRead)
res = port.read(bytesToRead)
print(res)
port.reset_input_buffer()
port.write(("time\r".encode()))
res = port.readline()
print(res)
Using the above command I sometimes do not receive the value of time after executing its command or sometimes it is merged with the sop command. Also with the sop command, I received a lot of data during the sleep(5) out of which I need to get the latest data. If I do not include sleep(5), I miss the sop data and it is then received after executing the time command.
I was hoping if anyone can point me to right direction of how to design it in a better way. Also, I think this can easily be done using interrupt handler but I didn't found any code about pyserial interrupts. Can anyone please suggest some good code for using interrupts in pyserial.
Thanks
Instead of using time.sleep(), its preferred to use serialport.in_waiting which help to check the number of bytes available in rcv buffer.
So once there is some data is rcv buffer then only read the data using read function.
so following code sequence can be followed without having any delay
while True:
bytesToRead = port.in_waiting
print(bytesToRead)
if(bytestoRead > 0):
res = port.read(bytesToRead)
print(res)
port.reset_input_buffer()
# put some check or filter then write data on serial port
port.write(("time\r".encode()))
res = port.readline()
print(res)
I am taking a stab here: Your time.sleep(5) might be too long. Have you tried making the sleep really short, for example time.sleep(.300)? If the time data gets written back between the sop returns you will catch it before it gets merged with sop, but I am making an assumption here that it will send time data back, else there is anyway nothing more you can do on the server side (the python) code. I do believe it won't hurt to make the sleep less, it is anyway just sitting there waiting (polling) for communication.
Not having the having the same environment on my side, makes it difficult to answer, because I can't test my answer, so I hope this might help.

Best way to handle no-blocking socket service result

I want to talk with a proxy soft, here is official socket example.
This soft would send traffic statistic to connected cli every 10 seconds. I also need to send commands and get command results on same connection.
It cost me some time to figure out that I can't create two socket clients and connect to same server to get different results.
My problem: how do I manage user config while recording traffic statistic ?
Test:
When add a port, would get ok after several cli.recv(1506) (because the stat send every 10 second, it I don't read all the time, ok would behind of many stat) :
>>> cli.send(b'add: {"server_port":8003, "password":"123123"}')
46
>>> print(cli.recv(1506))
stat: {"8002":164}
>>> print(cli.recv(1506))
stat: {"8002":336}
>>> print(cli.recv(1506))
ok
>>> print(cli.recv(1506))
stat: {"8002":31}
>>> print(cli.recv(1506))
# hang here wait for next result
So if I send many command, I can't recognise the which result map which command.
The solution I came up with is:
# client main code
while True:
# need open another sock port to recieve command
c = self.on_new_command()
if c:
self.cli.send(c)
# does python socket server ensure response is FIFO when `setblocking(False)`
self.queue.append(c)
ret = self.cli.recv(1524)
if 'stat' in ret:
self.record(ret)
else :
self.log(self.queue.pop(), ret)
I need open another sock port to receive command in this client, and have to write another client which sends commands to this... I just don't feel it is good.
Because it is my first time to play with socket programming, is my solution the best for this situation? Is there any better way to achieve my goal?

Socket issues in Python

I'm building a simple server-client app using sockets. Right now, I am trying to get my client to print to console only when it received a specific message (actually, when it doesn't receive a specific message), but for some reason, every other time I run it, it goes through the other statement in my code and is really inconsistent - sometimes it will work as it should and then it will randomly break for a couple uses.
Here is the code on my client side:
def post_checker(client_socket):
response = client_socket.recv(1024)
#check if response is "NP" for a new post from another user
if response == "NP":
new_response = client_socket.recv(1024)
print new_response
else: #print original message being sent
print response
where post_checker is called in the main function as simply "post_checker(client_socket)" Basically, sometimes I get "NPray" printed to my console (when the client only expects to receive the username "ray") and other times it will print correctly.
Here is the server code correlated to this
for sublist in user_list:
client_socket.send("NP")
client_socket.send(sublist[1] + " ")
where user_list is a nested list and sublist[1] is the username I wish to print out on the client side.
Whats going on here?
The nature of your problem is that TCP is a streaming protocol. The bufsize in recv(bufsize) is a maximum size. The recv function will always return data when available, even if not all of the bytes have been received.
See the documentation for details.
This causes problems when you've only sent half the bytes, but you've already started processing the data. I suggest you take a look at the "recvall" concept from this site or you can also consider using UDP sockets (which would solve this problem but may create a host of others as UDP is not a guaranteed protocol).
You may also want to let the python packages handle some of the underlying framework for you. Consider using a SocketServer as documented here:
buffer = []
def recv(sock):
global buffer
message = b""
while True:
if not (b"\r\n" in b"".join(buffer)):
chunk = sock.recv(1024)
if not chunk:
break
buffer.append(chunk)
concat = b"".join(buffer)
if (b"\r\n" in concat):
message = concat[:concat.index(b"\r\n")]
concat = concat[concat.index(b"\r\n") + 2:]
buffer = [concat]
break
return message
def send(sock, data):
sock.send(data + b"\r\n")
I have tested this, and in my opinion, it works perfectly
My use case: I have two scripts that send data quickly, it ends up that one time or another, the buffers receive more than they should, and gather the data, with this script it leaves everything that receives more saved, and continues receiving until there is a new line between the data, and then, it gathers the data, divides in the new line, saves the rest and returns the data perfectly separated
(I translated this, so please excuse me if anything is wrong or misunderstood)

In a list, skip a host that I cannnot access

SOLVED:
I figured out the fix for this was adding env.abort_on_prompts = True to my fab file
This is a very specific question ... but I have a python definition that checks for the OS version of a specific host. It goes line by line through the list, attempts to connect to the host and outputs the OS information it finds. But that is just background ...
So my real question is if I can skip the hosts I cannot access. Many hosts it does fine with, but it will hit one where the screen prompts for "Login password for 'yourAdminUser':". I want to know if there is a way that I can get the script to realize when this is being output to the console, that it should terminate that connection attempt and then move on to the next line.
I would paste my code but it is only a few lines and I have nothing in it to expect this error of a password that I do not have.
Thanks
EDIT : I've pasted my definition below.
def get_os():
put(local_path="scripts/check_OS.ksh",remote_path="/tmp/check_OS.ksh")
sudo('chmod u+x /tmp/check_OS.ksh')
output = sudo("/tmp/check_OS.ksh")
print green("OS: {}".format(output))

Categories