Deploy Flask on Apache using mod_wsgi - apache

I'm trying to deploy a Flask web app I built to be deployed on an Apache server. I'm using Raspbian (Jessie) OS on a Raspberry Pi 3. The app runs perfect on the flask built-in dev web server, but I have been unable to deploy it on the Apache sever.
This is what I did:
sudo apt-get update
sudo apt-get -y install python3 ipython3 python3-flask
sudo apt-get -y install apache2
sudo apt-get -y install libapache2-mod-wsgi-py3
The conf file is: /etc/apach2/sites-available/arduinoweb.conf:
<VirtualHost *>
ServerName 10.0.0.20
WSGIDaemonProcess arduinoweb user=pi group=pi threads=5
WSGIScriptAlias / /var/www/ArduinoWeb/arduinoweb.wsgi
<Directory /var/www/ArduinoWeb/ArduinoWeb>
WSGIProcessGroup arduinoweb
WSGIApplicationGroup %{GLOBAL}
WSGIScriptReloading On
Require all granted
</Directory>
Alias /static /var/www/ArduinoWeb/ArduinoWeb/static
<Directory /var/www/ArduinoWeb/ArduinoWeb/static/>
Require all granted
</Directory>
Alias /temp /var/www/ArduinoWeb/ArduinoWeb/temp
<Directory /var/www/ArduinoWeb/ArduinoWeb/temp/>
Require all granted
</Directory>
Alias /templates /var/www/ArduinoWeb/ArduinoWeb/templates
<Directory /var/www/ArduinoWeb/ArduinoWeb/templates/>
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
~
The WSGI script file in /var/www/Arduinoweb/arduinoweb.wsgi:
import sys
if sys.version_info[0]<3: # require python3
raise Exception("Python3 required! Current (wrong) version: '%s'" % sys.version_info)
sys.path.insert(0, '/var/www/Arduinoweb/Arduinoweb')
from app import app as application
The error log of Apache:
[Wed Sep 21 21:46:22.669633 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] mod_wsgi (pid=17681): Target WSGI script '/var/www/ArduinoWeb/arduinoweb.wsgi' cannot be loaded as Python module.
[Wed Sep 21 21:46:22.669971 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] mod_wsgi (pid=17681): Exception occurred processing WSGI script '/var/www/ArduinoWeb/arduinoweb.wsgi'.
[Wed Sep 21 21:46:22.670196 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] Traceback (most recent call last):
[Wed Sep 21 21:46:22.671185 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] File "/var/www/ArduinoWeb/arduinoweb.wsgi", line 8, in <module>
[Wed Sep 21 21:46:22.671238 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] from app import app as application
[Wed Sep 21 21:46:22.671406 2016] [wsgi:error] [pid 17681:tid 1972667440] [client 10.0.0.3:64819] ImportError: No module named 'app'
I don't understand why it cant find the app.
This is the python file /var/www/Arduinoweb/Arduinoweb/app.py :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask import request, redirect, url_for, render_template, jsonify
from socket import *
from time import time
from threading import Timer
from datetime import datetime
import fileinput
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:Qazwsx#localhost/arduinoweb'
app.debug = True
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<user %r>' % self.username
class Temp(db.Model):
__tablename__ = "Temp"
id = db.Column("id", db.Integer, primary_key=True)
Temp = db.Column("Temp", db.Integer)
Date = db.Column("Date", db.Date)
Time = db.Column("Time", db.Time)
DateTime = db.Column("DateTime", db.String)
def __init__(self, Temp, Date=None, Time=None, DateTime=None):
self.Temp = Temp
if Date is None:
Date = str(datetime.now()).split('.')[0]
self.Date = Date
if Time is None:
Time = str(datetime.now()).split('.')[0]
self.Time = Time
if DateTime is None:
DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
self.DateTime = DateTime
class EC(db.Model):
__tablename__ = "EC"
id = db.Column("id", db.Integer, primary_key=True)
EC = db.Column("EC", db.Float)
Date = db.Column("Date", db.Date)
Time = db.Column("Time", db.Time)
DateTime = db.Column("DateTime", db.String)
def __init__(self, EC, Date=None, Time=None, DateTime=None):
self.EC = EC
if Date is None:
Date = str(datetime.now()).split('.')[0]
self.Date = Date
if Time is None:
Time = str(datetime.now()).split('.')[0]
self.Time = Time
if DateTime is None:
DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
self.DateTime = DateTime
class PH(db.Model):
__tablename__ = "PH"
id = db.Column("id", db.Integer, primary_key=True)
PH = db.Column("PH", db.Float)
Date = db.Column("Date", db.Date)
Time = db.Column("Time", db.Time)
DateTime = db.Column("DateTime", db.String)
def __init__(self, PH, Date=None, Time=None, DateTime=None):
self.PH = PH
if Date is None:
Date = str(datetime.now()).split('.')[0]
self.Date = Date
if Time is None:
Time = str(datetime.now()).split('.')[0]
self.Time = Time
if DateTime is None:
DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
self.DateTime = DateTime
class Humidity(db.Model):
__tablename__ = "Humidity"
id = db.Column("id", db.Integer, primary_key=True)
Humidity = db.Column("Humidity", db.Integer)
Date = db.Column("Date", db.Date)
Time = db.Column("Time", db.Time)
DateTime = db.Column("DateTime", db.String)
def __init__(self, Humidity, Date=None, Time=None, DateTime=None):
self.Humidity = Humidity
if Date is None:
Date = str(datetime.now()).split('.')[0]
self.Date = Date
if Time is None:
Time = str(datetime.now()).split('.')[0]
self.Time = Time
if DateTime is None:
DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
self.DateTime = DateTime
class HumidityRoots(db.Model):
__tablename__ = "HumidityRoots"
id = db.Column("id", db.Integer, primary_key=True)
HumidityRoots = db.Column("HumidityRoots", db.Integer)
Date = db.Column("Date", db.Date)
Time = db.Column("Time", db.Time)
DateTime = db.Column("DateTime", db.String)
def __init__(self, HumidityRoots, Date=None, Time=None, DateTime=None):
self.HumidityRoots = HumidityRoots
if Date is None:
Date = str(datetime.now()).split('.')[0]
self.Date = Date
if Time is None:
Time = str(datetime.now()).split('.')[0]
self.Time = Time
if DateTime is None:
DateTime = repr(datetime.now().replace(second=0, microsecond=0)).split('datetime.datetime',1)[1]
self.DateTime = DateTime
#app.route('/Sensors')
def sensors_function():
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto("GETSENSORS".encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return rec_data
#app.route('/OutputsState')
def outputs_state_function():
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto("GETOUTPUTSSTATE".encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return rec_data
#app.route('/WebModeState')
def web_mode_state_function():
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto("GETWEBMODE".encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return rec_data
#app.route('/PLCState')
def plcstatefunction():
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto("GETPLCSTATE".encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return rec_data
#app.route('/IrrigateOnOff')
def irrigate_on_off_function():
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto("IRRIGATEOnOff".encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return rec_data
#app.route('/SprinklersOnOff')
def sprinklers_on_off_function():
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto("SprinklersOnOff".encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return rec_data
#app.route('/SetDateTime' , methods=['POST'])
def set_date_time_function():
completeAnswer = "%s:%s:%s:%s:%s:%s:%s:%s" % ("SETDATETIME", request.form.get('dOw'), request.form.get('SetDate'), request.form.get('SetMonth'), request.form.get('SetYear'), request.form.get('SetHour'), request.form.get('SetMinute'), request.form.get('SetSeconds'))
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto(completeAnswer.encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return "ok"
#app.route('/SetIrrigation' , methods=['POST'])
def set_irrigation_function():
completeAnswer = "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s" % ("SETIRRIGATION",request.form.get('SetIrrigationMode'), request.form.get('SetHumidityRangeMin'), request.form.get('SetHumidityRangeMax'), request.form.get('SetHour1'), request.form.get('SetHour1OnTime'), request.form.get('SetHour1OffTime'), request.form.get('SetHour2'), request.form.get('SetHour2OnTime'), request.form.get('SetHour2OffTime'), request.form.get('SetHour3'), request.form.get('SetHour3OnTime'), request.form.get('SetHour3OffTime'), request.form.get('SetHour4'), request.form.get('SetHour4OnTime'), request.form.get('SetHour4OffTime'))
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto(completeAnswer.encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return "ok"
#app.route('/SetEC' , methods=['POST'])
def set_EC_function():
completeAnswer = "%s:%s:%s:%s:%s" % ("SETEC", request.form.get('SetECRangeMin'), request.form.get('SetECRangeMax'), request.form.get('SetDoseEC'), request.form.get('SetECDelay'))
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto(completeAnswer.encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return "ok"
#app.route('/SetPH' , methods=['POST'])
def set_PH_function():
completeAnswer = "%s:%s:%s:%s:%s:%s" % ("SETPH", request.form.get('SetPHRangeMin'), request.form.get('SetPHRangeMax'), request.form.get('SetDosePHUp'), request.form.get('SetDosePHDown'), request.form.get('SetPHDelay'))
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto(completeAnswer.encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return "ok"
#app.route('/SetWaterTemp' , methods=['POST'])
def set_water_temp_function():
completeAnswer = "%s:%s:%s" % ("SETWATERTEMP", request.form.get('SetWaterTempRangeMin'), request.form.get('SetWaterTempRangeMax'))
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto(completeAnswer.encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return "ok"
#app.route('/SetSprinklers' , methods=['POST'])
def set_sprinklers_function():
completeAnswer = "%s:%s:%s:%s:%s" % ("SETSPRINKLERS", request.form.get('SetSprinklersBeginEndHoursBegin'), request.form.get('SetSprinklersBeginEndHoursEnd'), request.form.get('SetSprinklersOnTime'), request.form.get('SetSprinklersOffTime'))
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto(completeAnswer.encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return "ok"
#app.route('/SetAlerts' , methods=['POST'])
def set_alerts_function():
completeAnswer = "%s:%s:%s:%s:%s:%s" % ("SETALERTS", request.form.get('SetIrrigationThresholdAlert'), request.form.get('ECAlertOffset'), request.form.get('PHAlertOffset'), request.form.get('ResetCounterState'), request.form.get('AlertsState'))
address= ( '192.168.0.196', 5000) #define server IP and port
client_socket =socket(AF_INET, SOCK_DGRAM) #Set up the Socket
client_socket.settimeout(1) #Only wait 1 second for a response
client_socket.sendto(completeAnswer.encode(), address) #Send the data request
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
return "ok"
#app.route('/')
def index():
return render_template('index.html')
#app.route('/Charts')
def charts():
return render_template('charts.html')
#app.route('/livechart')
def live_chart():
return render_template('livechart.html')
#app.route('/TempQuery' , methods=['POST'])
def temp_query():
answerDate = request.form.get('date')
answerSensor = request.form.get('sensor')
datafile = 'temp/TempByDateDbFile.txt'
if answerSensor == 'Temp':
DbTemp = Temp.query.filter_by(Date = answerDate).all()
## create the file from db
file = open(datafile, 'w')
for item in DbTemp:
file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.Temp) + '},' + '\n')
file.close()
elif answerSensor == 'EC':
DbTemp = EC.query.filter_by(Date = answerDate).all()
## create the file from db
file = open(datafile, 'w')
for item in DbTemp:
file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.EC) + '},' + '\n')
file.close()
elif answerSensor == 'PH':
DbTemp = PH.query.filter_by(Date = answerDate).all()
## create the file from db
file = open(datafile, 'w')
for item in DbTemp:
file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.PH) + '},' + '\n')
file.close()
elif answerSensor == 'Humidity':
DbTemp = Humidity.query.filter_by(Date = answerDate).all()
## create the file from db
file = open(datafile, 'w')
for item in DbTemp:
file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.Humidity) + '},' + '\n')
file.close()
elif answerSensor == 'HumidityRoots':
DbTemp = HumidityRoots.query.filter_by(Date = answerDate).all()
## create the file from db
file = open(datafile, 'w')
for item in DbTemp:
file.write('{x: new Date' + str(item.DateTime) + ' , y: ' + str(item.HumidityRoots) + '},' + '\n')
file.close()
##replace "-" in ","
f = open(datafile,'r')
filedata = f.read()
f.close()
newdata = filedata.replace("-",", ")
f = open(datafile,'w')
f.write(newdata)
f.close()
return 'OK'
#app.route('/RenderTempChart' , methods=['POST' , 'GET'])
def render_temp_chart():
datafile = 'temp/TempByDateDbFile.txt'
with open(datafile, 'r') as myfile:
file = myfile.read()
return render_template('DbTemp.html', file = file)
#app.route('/Control' , methods=['POST' , 'GET'])
def control():
return render_template('control.html')
"""
def update_data(interval): # store in DB all sensors real time data
Timer(interval, update_data, [interval]).start()
SensorsAnswer = sensors_function().split()
addTemp = Temp(int(SensorsAnswer[2]))
addEC = EC(float(SensorsAnswer[0]))
addPH = PH(float(SensorsAnswer[1]))
addHumidity = Humidity(int(SensorsAnswer[3]))
addHumidityRoots = HumidityRoots(int(SensorsAnswer[5]))
db.session.add(addTemp)
db.session.add(addEC)
db.session.add(addPH)
db.session.add(addHumidity)
db.session.add(addHumidityRoots)
db.session.commit()
update_data(300) # Store data in DB every x seconds
"""
if __name__ == "__main__":
app.run()
It's not working even with a simple code like this (same error):
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello world!"
if __name__ == "__main__":
app.run()
I'm using python 3.4.2. I'm not using it in a virtual environment.
The folder structure:
app.py is at /var/www/Arduinoweb/Arduinoweb/app.py
arduinoweb.wsgi is at /var/www/Arduinoweb/arduinoweb.wsgi
I do enable the VirtualHost arduinoweb.conf and restart apach2 service.

For a start, this:
<Directory /var/www/ArduinoWeb/ArduinoWeb>
WSGIProcessGroup arduinoweb
WSGIApplicationGroup %{GLOBAL}
WSGIScriptReloading On
Require all granted
</Directory>
should be:
<Directory /var/www/ArduinoWeb>
WSGIProcessGroup arduinoweb
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
Technically this being wrong would cause two problems.
The first is that Apache shouldn't have even let you use that WSGI script as it wouldn't have permission to. Looks though like somewhere else in your Apache configuration is giving broad access to your file system when it shouldn't really.
I have also dropped the reloading option as that default to on anyway and isn't needed.
The second is that the WSGI script wouldn't be run in the context of the daemon process group. This would mean code would load in embedded mode instead and would run as Apache user. If the permissions on your files were such that only the pi user could read them, then it wouldn't be able to access the app module.
It is also generally wrong to have SeverName be an IP address. If it is working then it is only doing so because this is the first VirtualHost in the Apache configuration and so Apache is defaulting to using it when it can't properly do name base virtual host matching.
Anyway, see if that helps, otherwise provide output of running:
ls -las /var/www/ArduinoWeb /var/www/ArduinoWeb/ArduinoWeb
so can check what ownership/permissions of directories/files are.

thanks for the help .. eventually it was seems to be just a typing mistake in the wsgi script path: "/var/www/ArduinoWeb/ArduinoWeb" instead "/var/www/Arduinoweb/Arduinoweb" .
now its seems to work fine . thanks!!

Related

PyQt5 QTimer in not working after moving it to a thread

I am currently trying to separate my PyQT5-GUI from my serial communication to prevent a freezing GUI.
Therefore, I tried to implement threading. So when I am pressing a button "Open Port", a new thread starts which handles this incoming and outgoing data of the Port.
Now, this works fine, but I am having problems with a timer not fulfilling its function. Essentially, I want to close the port after a 'no valid' message has been received for x seconds.
I tried to create a minimum example:
Upon starting, the GUI and the thread are created. When pressing "Open", the port is opened and the timer in the thread should start. After 3000 milliseconds, the port should be closed by the timer overflow.
from PyQt5 import QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtSerialPort
import sys
class AECRobotControl(QMainWindow):
signal_open_port = pyqtSignal(str)
signal_close_port = pyqtSignal(int)
def __init__(self):
super().__init__()
# main-window setup
self.ui = Ui_RobotControls_Main()
self.ui.setupUi(self)
# Port
self.port_gcode_timer_sending = QTimer() # Timer for sending Gcode to prevent robot queue overflow
# END Port
# Threads
self.thread_port = QThread()
self.thread_port_worker = None
# END Threads
# END Variables
# Functions
# Init the ui with standard values
# self.init_ui()
# Init COM-worker
self.init_worker()
# Init signal callbacks
self.init_signals()
# show GUI
self.show()
# END Functions
def init_ui(self):
self.layout.addWidget(self.button_open)
self.layout.addWidget(self.button_close)
self.setLayout(self.layout)
def init_signals(self):
# Button Open Port
self.ui.pushButton_open_port.clicked.connect(self.button_open_comport)
# END Button Open Port
# Button Close Port
self.ui.pushButton_close_port.clicked.connect(self.button_close_comport)
# END Button Close Port
def init_worker(self):
self.thread_port_worker = RobotMessageThread()
self.thread_port_worker.moveToThread(self.thread_port)
self.thread_port.started.connect(self.thread_port_worker.start_thread)
self.thread_port.finished.connect(self.thread_port.deleteLater)
self.thread_port_worker.finished.connect(self.thread_port.quit)
self.thread_port_worker.finished.connect(self.thread_port_worker.deleteLater)
self.signal_open_port.connect(self.thread_port_worker.open_port_slot)
self.signal_close_port.connect(self.thread_port_worker.close_comport)
self.thread_port.start()
def button_open_comport(self):
self.signal_open_port.emit("COM4")
def button_close_comport(self):
if (self.thread_port.isRunning() == True):
self.signal_close_port.emit(0)
def parse_com_message(self, message):
try:
print(message)
except Exception as e:
print(e)
class RobotMessageThread(QObject):
finished = pyqtSignal()
progress = pyqtSignal(int)
com_message_parsed = pyqtSignal(QByteArray)
com_ascii_message_parsed = pyqtSignal(str)
def __init__(self):
super().__init__()
self.port_com_port = QtSerialPort.QSerialPort()
self.port_name = None
self.port_is_alive_timer = QTimer() # Interprets valid received messages as alive-sign from robot.
""" Functions to be called upon start of thread"""
def start_thread(self):
print("Thread started")
self.port_is_alive_timer.timeout.connect(lambda: self.close_comport(1))
""" Inits the port"""
def _init_port(self):
self.port_com_port.setPortName(self.port_name)
self.port_com_port.setBaudRate(QtSerialPort.QSerialPort.BaudRate.Baud115200)
self.port_com_port.setParity(QtSerialPort.QSerialPort.Parity.NoParity)
self.port_com_port.setDataBits(QtSerialPort.QSerialPort.DataBits.Data8)
self.port_com_port.setStopBits(QtSerialPort.QSerialPort.StopBits.OneStop)
#pyqtSlot(bytearray)
def message_slot(self, message: bytearray):
self._write_to_port(message)
#pyqtSlot(str)
def open_port_slot(self, com_name: str):
self.port_name = com_name
self._init_port()
self._open_comport()
#pyqtSlot()
def close_port_slot(self, message: bytearray):
self.close_comport(0)
""" Tries to open the selected comport"""
def _open_comport(self):
# Check whether port is already open
if self.port_com_port.open(QIODevice.ReadWrite) == True:
self.port_com_port.setDataTerminalReady(True)
print("COM Opened")
# Reset message-buffer
self.port_is_alive_timer.start(3000)
else:
print("opening failed")
""" Closes the selected comport"""
def close_comport(self, source):
if self.port_com_port.isOpen() == True:
# Close port and delete queue
self.port_com_port.clear()
self.port_com_port.close()
# Stop timers
self.port_is_alive_timer.stop()
print("Closed by " + str(source))
else:
print("Closing failed")
# GUI
class Ui_RobotControls_Main(object):
def setupUi(self, RobotControls_Main):
RobotControls_Main.setObjectName("RobotControls_Main")
RobotControls_Main.resize(1024, 900)
RobotControls_Main.setMinimumSize(QSize(1024, 900))
RobotControls_Main.setMaximumSize(QSize(1600, 1200))
self.centralwidget = QtWidgets.QWidget(RobotControls_Main)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_12 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_12.setObjectName("gridLayout_12")
self.QGroupBox_port_settings = QtWidgets.QGroupBox(self.centralwidget)
self.QGroupBox_port_settings.setObjectName("QGroupBox_port_settings")
self.gridLayout_15 = QtWidgets.QGridLayout(self.QGroupBox_port_settings)
self.gridLayout_15.setObjectName("gridLayout_15")
self.horizontalLayout_21 = QtWidgets.QHBoxLayout()
self.horizontalLayout_21.setObjectName("horizontalLayout_21")
self.pushButton_open_port = QtWidgets.QPushButton(self.QGroupBox_port_settings)
self.pushButton_open_port.setMaximumSize(QSize(100, 50))
self.pushButton_open_port.setObjectName("pushButton_open_port")
self.horizontalLayout_21.addWidget(self.pushButton_open_port)
self.gridLayout_15.addLayout(self.horizontalLayout_21, 0, 0, 1, 1)
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.pushButton_close_port = QtWidgets.QPushButton(self.QGroupBox_port_settings)
self.pushButton_close_port.setObjectName("pushButton_close_port")
self.horizontalLayout_4.addWidget(self.pushButton_close_port)
self.gridLayout_15.addLayout(self.horizontalLayout_4, 0, 1, 1, 1)
self.gridLayout_12.addWidget(self.QGroupBox_port_settings, 0, 0, 1, 1)
RobotControls_Main.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(RobotControls_Main)
self.statusbar.setObjectName("statusbar")
RobotControls_Main.setStatusBar(self.statusbar)
self.retranslateUi(RobotControls_Main)
QMetaObject.connectSlotsByName(RobotControls_Main)
def retranslateUi(self, RobotControls_Main):
_translate = QCoreApplication.translate
RobotControls_Main.setWindowTitle(_translate("RobotControls_Main", "RobotControls"))
self.QGroupBox_port_settings.setTitle(_translate("RobotControls_Main", "Port settings"))
self.pushButton_open_port.setText(_translate("RobotControls_Main", "Open Port"))
self.pushButton_close_port.setText(_translate("RobotControls_Main", "Close Port"))
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = AECRobotControl()
app.exec() # QT main-threadtimer.start(TIME)
I found a solution. In the above code, just one line needs to be added: after moving the worker to the separate thread, the QTimer also has to be moved to the same thread. So, after self.thread_port_worker.moveToThread(self.thread_port), the line self.thread_port_worker.port_is_alive_timer.moveToThread(self.thread_port) needs to be added

How to force terminate Qthread and ThreadPoolExecutioner Threads

Iam working on a script using PYQT5 GUI to do network script using paramiko and iam using pyQT Qthread as below in my main application class i created below function to run a script which reads csv file get IPs and hostnames and then call another QObject Class:
class MemoryUtilizWidget(QDialog):
def __init__(self):
super(MemoryUtilizWidget, self).__init__()
self.setStyleSheet("background-color: rgb(35, 35, 35);")
self.setWindowIcon(QtGui.QIcon('Logo.png'))
self.setWindowTitle('Memory Utilization Script Options')
layout = QGridLayout()
self.setLayout(layout)
def MemoryRunScript(self):
InventoryFile = self.InventoryCombo.currentText()
if InventoryFile:
Routers_List = []
Routers_Names = []
line_count = 0
with open(path + '\\Script Data\\Inventory Database\\' + InventoryFile) as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for row in csv_reader:
if line_count == 0:
pass
else:
Routers_Names.append(row[1])
Routers_List.append(row[2])
line_count+=1
Not_Accessible_Routers = open(path + "\\Script Data\\Routers Summary\\Not Accessible Routers.txt" , 'w+' , encoding='utf-8')
Login_Incorrect_Routers = open(path + "\\Script Data\\Routers Summary\\Login Routers Routers.txt" , 'w+' , encoding='utf-8')
TACACS_Down_Routers = open(path + "\\Script Data\\Routers Summary\\TACACS Down Routers.txt" , 'w+' , encoding='utf-8')
Wrong_Hostname_Routers = open(path + "\\Script Data\\Routers Summary\\Wrong Hostname Routers.txt" , 'w+' , encoding='utf-8')
Username = 'user'
Password = 'pass'
self.MemoryProgressBar.setMinimum(0)
self.MemoryProgressBar.setMaximum(len(Routers_List))
self.RunScriptButton.setEnabled(False)
self.InventoryCombo.setEnabled(False)
self.InventoryButton.setEnabled(False)
self.InventorytLineEdit.setEnabled(False)
self.MemoryThread = QtCore.QThread()
self.MemoryObject = MemoryThreading(Routers_List,Routers_Names,Not_Accessible_Routers,Login_Incorrect_Routers,TACACS_Down_Routers,Wrong_Hostname_Routers,Username,Password)
self.MemoryObject.moveToThread(self.MemoryThread)
self.MemoryObject.Finished.connect(self.MemoryFinished)
self.MemoryThread.started.connect(self.MemoryObject.MainThreading)
self.MemoryThread.start()
self.MemoryObject.Progressvalue.connect(self.ProgressValue)
the QObject class i used multithreading technique of ThreadPoolExecuter to run fast as the IPs are over 3000 IP which will take forever:
class MemoryThreading(QtCore.QObject):
Finished = QtCore.pyqtSignal()
Progressvalue = QtCore.pyqtSignal(int)
def __init__(self,Routers_List, Routers_Names, Login_Incorrect_Routers,TACACS_Down_Routers,Not_Accessible_Routers,Wrong_Hostname_Routers, Username, Password):
super().__init__()
self.Routers_List = Routers_List
self.Routers_Names = Routers_Names
self.Login_Incorrect_Routers = Login_Incorrect_Routers
self.TACACS_Down_Routers = TACACS_Down_Routers
self.Not_Accessible_Routers = Not_Accessible_Routers
self.Wrong_Hostname_Routers = Wrong_Hostname_Routers
self.Username = Username
self.Password = Password
def MainThreading(self):
i = 0
with concurrent.futures.ThreadPoolExecutor() as self.executor:
self.results = self.executor.map(RouterConnection, self.Routers_List,self.Routers_Names,itertools.repeat(self.Login_Incorrect_Routers),itertools.repeat(self.TACACS_Down_Routers),itertools.repeat(self.Not_Accessible_Routers),itertools.repeat(self.Wrong_Hostname_Routers), itertools.repeat(self.Username), itertools.repeat(self.Password))
for result in self.results:
i+=1
self.Progressvalue.emit(i)
try:
if result:
print(result)
except Exception as exc:
print(exc)
self.Progressvalue.emit(0)
self.Finished.emit()
my concern is how to force this Created threads during execution of the script to stop so that the user can run the script and also stop it if possible i searched and googled a lot but didn't find any solution to my case as iam using both QThread and ThreadpoolExecutor

Make USB device visible with different vendor and product ID

I'm looking for a way to make a USB device show up as if it has different vendor and product IDs. I'm trying to make a proprietary piece of software to work with a USB device that should be supported but gets rejected solely because of its ID.
The software is for Windows, but I can run it in a VM in Linux. So I'll be fine with either approach, whatever works:
Changing USB ID in Linux
Changing USB ID in Windows
Making Qemu (or perhaps some other equivalent) change USB ID in passthrough
There may be a simpler way to do this, but I was faced with a similar problem and was able to create a process in which I could change the device descriptor information for development purposes. The process is summarized in this diagram:
First configure a static IP address for you Raspberry Pi and configure your PC ethernet TCP/IPv4 settings so you are able to communicate with you Raspberry Pi over the LAN connection.
Download the Virtual Here Raspberry Pi server and the client software for your PC from the Virtual Here website. The trial version will work for this use case.
Move the Virtual Here server software to you Raspberry Pi. In order to run the USB server you need to change the privileges of the file with $ sudo chmod +x vhusbdarm then run with $ sudo ./vhusbdarm.
Run the client software on your local machine. You will see that the client detects the USB device on the USB device server at <Your Raspberry Pi IP address>:7575. Connecting to the device at this point will give no advantage and mimic a direct connection.
Run the python file bellow, which was modified from a solution I found here, but utilizes Scapy sniff to capture the incoming packets before forwarding the raw data. The original script in the linked solution should work fine as well. In the script you can see that I used port 12345.
#!/usr/bin/env python
from scapy.all import *
import socket
import threading
import select
from queue import Queue
main_queue = Queue()
terminateAll = False
class ClientThread(threading.Thread):
def __init__(self, clientSocket, targetHost, targetPort):
threading.Thread.__init__(self)
self.__clientSocket = clientSocket
self.__targetHost = targetHost
self.__targetPort = targetPort
def run(self):
print("Client Thread started")
self.__clientSocket.setblocking(0)
targetHostSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
targetHostSocket.connect((self.__targetHost, self.__targetPort))
targetHostSocket.setblocking(0)
clientData = b""
targetHostData = b""
terminate = False
while not terminate and not terminateAll:
inputs = [self.__clientSocket, targetHostSocket]
outputs = []
if len(clientData) > 0:
outputs.append(self.__clientSocket)
if len(targetHostData) > 0:
outputs.append(targetHostSocket)
try:
inputsReady, outputsReady, errorsReady = select.select(inputs, outputs, [], 1.0)
except Exception as e:
print(e)
break
for inp in inputsReady:
if inp == self.__clientSocket:
try:
data = self.__clientSocket.recv(4096)
#print(data)
#data = b""
#while not main_queue.empty():
# data += main_queue.get()
except Exception as e:
print(e)
if data != None:
if len(data) > 0:
targetHostData += data
#else:
# terminate = True
elif inp == targetHostSocket:
try:
data = b""
while not main_queue.empty():
data += main_queue.get()
except Exception as e:
print(e)
if data != None:
if len(data) > 0:
clientData += data
for out in outputsReady:
if out == self.__clientSocket and len(clientData) > 0:
#pck = Ether(clientData)
#pck.show()
bytesWritten = self.__clientSocket.send(clientData)
if bytesWritten > 0:
clientData = clientData[bytesWritten:]
elif out == targetHostSocket and len(targetHostData) > 0:
#pck = Ether(targetHostData)
#pck.show()
bytesWritten = targetHostSocket.send(targetHostData)
if bytesWritten > 0:
targetHostData = targetHostData[bytesWritten:]
self.__clientSocket.close()
targetHostSocket.close()
print ("ClientThread terminating")
def handle_sniff(pck):
if IP in pck:
if pck[IP].src == "192.168.1.48":
if Raw in pck:
payload = pck[Raw].load
if b'\x12\x01\x00\x01\x00\x00\x00\x08$\x07\x04\x00\x88#\x01\x02\x00\x01' in payload:
payload = payload.replace(b'\x00\x08$\x07\x04\x00\x88#\x01\x02\x00', b'\x00\x08$\x07\x04\x00\x88\x15\x01\x02\x00')
print(payload)
main_queue.put(payload)
if __name__ == '__main__':
localHost = "localhost"
localPort = 12345
targetHost = "192.168.1.12"
targetPort = 7575
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.bind((localHost, localPort))
serverSocket.listen(5)
print("Waiting for client...")
while True:
try:
clientSocket, address = serverSocket.accept()
except KeyboardInterrupt:
print("\nTerminating...")
terminateAll = True
break
print("starting client")
ClientThread(clientSocket, targetHost, targetPort).start()
sniff(iface="Ethernet", prn=lambda pck: handle_sniff(pck))
serverSocket.close()
Once the script is running, configure the Virtual Here client to listen for USB servers at localhost:12345. The handle_sniff function is where the USB device descriptor information is being changed. Once connected you should be able to double click on the USB device in the dropdown tree. You will see the USB data begin to be printed in the your python console.
In the above example I changed the device bcdDevice bytes of the USB Descriptor.
Another helpful script I used to identify the packet that contained the information I was targeting is below. I modified a script I found in this solution. It is modified to print the raw data along with the unpacked device descriptor information, which can then be searched for in the TCP raw data to identify which bytes to replace.
#!/usr/bin/env python
from __future__ import print_function
import argparse
import string
import struct
import sys
import win32api
import win32file
import pywintypes
BUFF=b""
def CTL_CODE(DeviceType, Function, Method, Access):
return (DeviceType << 16) | (Access << 14) | (Function << 2) | Method
def USB_CTL(id):
# CTL_CODE(FILE_DEVICE_USB, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
return CTL_CODE(0x22, id, 0, 0)
IOCTL_USB_GET_ROOT_HUB_NAME = USB_CTL(258) # HCD_GET_ROOT_HUB_NAME
IOCTL_USB_GET_NODE_INFORMATION = USB_CTL(258) # USB_GET_NODE_INFORMATION
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION = USB_CTL(259) # USB_GET_NODE_CONNECTION_INFORMATION
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME = USB_CTL(264) # USB_GET_NODE_CONNECTION_DRIVERKEY_NAME
IOCTL_USB_GET_NODE_CONNECTION_NAME = USB_CTL(261) # USB_GET_NODE_CONNECTION_NAME
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION = USB_CTL(260) # USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
USB_CONFIGURATION_DESCRIPTOR_TYPE = 2
USB_STRING_DESCRIPTOR_TYPE = 3
USB_INTERFACE_DESCRIPTOR_TYPE = 4
MAXIMUM_USB_STRING_LENGTH = 255
def open_dev(name):
try:
handle = win32file.CreateFile(name,
win32file.GENERIC_WRITE,
win32file.FILE_SHARE_WRITE,
None,
win32file.OPEN_EXISTING,
0,
None)
except pywintypes.error as e:
return None
return handle
def get_root_hub_name(handle):
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_ROOT_HUB_NAME,
None,
6,
None)
act_len, _ = struct.unpack('LH', buf)
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_ROOT_HUB_NAME,
None,
act_len,
None)
return buf[4:].decode('utf-16le')
def get_driverkey_name(handle, index):
key_name = bytes(chr(index) + '\0'*9, 'utf-8')
try:
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
key_name,
10,
None)
except pywintypes.error as e:
print(e.strerror, index)
sys.exit(1)
_, act_len, _ = struct.unpack('LLH', buf)
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
key_name,
act_len,
None)
return buf[8:].decode('utf-16le')
def get_ext_hub_name(handle, index):
hub_name = chr(index) + '\0'*9
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_NODE_CONNECTION_NAME,
hub_name,
10,
None)
_, act_len, _ = struct.unpack('LLH', buf)
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_NODE_CONNECTION_NAME,
hub_name,
act_len,
None)
return buf[8:].decode('utf-16le')
def get_str_desc(handle, conn_idx, str_idx):
req = struct.pack('LBBHHH',
conn_idx,
0,
0,
(USB_STRING_DESCRIPTOR_TYPE<<8) | str_idx,
win32api.GetSystemDefaultLangID(),
MAXIMUM_USB_STRING_LENGTH)
try:
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
req,
12+MAXIMUM_USB_STRING_LENGTH,
None)
except pywintypes.error as e:
return 'ERROR: no String Descriptor for index {}'.format(str_idx)
if len(buf) > 16:
return buf[14:].decode('utf-16le')
return ''
def exam_hub(name, verbose, level):
handle = open_dev(r'\\.\{}'.format(name))
if not handle:
print('Failed to open device {}'.format(name))
return
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_NODE_INFORMATION,
None,
76,
None)
print_hub_ports(handle, ord(buf[6]), verbose, level)
handle.close()
def print_str_or_hex(to_be_print):
if all(c in string.printable for c in to_be_print):
print('"{}"'.format(to_be_print))
return
print('Hex: ', end='')
for x in to_be_print:
print('{:02x} '.format(ord(x)), end='')
print('')
def print_hub_ports(handle, num_ports, verbose, level):
print(handle, num_ports, verbose, level)
for idx in range(1, num_ports+1):
info = bytes(chr(idx) + '\0'*34, 'utf-8')
try:
buf = win32file.DeviceIoControl(handle,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
info,
34 + 11*30,
None)
except pywintypes.error as e:
print(e)
print(e.winerror, e.funcname, e.strerror)
return
print(buf)
_, vid, pid, vers, manu, prod, seri, _, ishub, _, stat = struct.unpack('=12sHHHBBB3s?6sL', buf[:35])
if ishub:
if verbose:
print('{} [Port{}] {}'.format(' '*level, idx, 'USB Hub'))
exam_hub(get_ext_hub_name(handle, idx), verbose, level)
elif stat == 0 and verbose:
print('{} [Port{}] {}'.format(' '*level, idx, 'NoDeviceConnected'))
elif stat == 1:
if verbose or (manu != 0 or prod != 0 or seri != 0):
print('{} [Port{}] {}'.format(' '*level, idx, get_driverkey_name(handle, idx)))
print('{} Vendor ID: 0x{:04X}'.format(' '*level, vid))
print('{} Product ID: 0x{:04X}'.format(' '*level, pid))
print('{} Device BCD: 0x{:04X}'.format(' '*level, vers))
print(vers)
if manu != 0:
print('{} Manufacturer (0x{:x}) -> '.format(' '*level, manu), end='')
print_str_or_hex(get_str_desc(handle, idx, manu))
if prod != 0:
print('{} Product (0x{:x}) -> '.format(' '*level, prod), end='')
print_str_or_hex(get_str_desc(handle, idx, prod))
if seri != 0:
print('{} Serial No (0x{:x}) -> '.format(' '*level, seri), end='')
print_str_or_hex(get_str_desc(handle, idx, seri))
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', action='store_true',
help="Increase output verbosity.")
args = parser.parse_args()
for i in range(10):
name = r"\\.\HCD{}".format(i)
handle = open_dev(name)
if not handle:
continue
root = get_root_hub_name(handle)
print('{}RootHub: {}'.format('\n' if i != 0 else '', root))
dev_name = r'\\.\{}'.format(root)
dev_handle = open_dev(dev_name)
if not dev_handle:
print('Failed to open device {}'.format(dev_name))
continue
buf = win32file.DeviceIoControl(dev_handle,
IOCTL_USB_GET_NODE_INFORMATION,
None,
76,
None)
global BUFF
BUFF=buf
print_hub_ports(dev_handle, buf[6], args.verbose, 0)
dev_handle.close()
handle.close()
if __name__ == '__main__':
main()
P.S. This is also really helpful for filtering and modifying any of the USB data being transferred not just the device descriptor.

Disable or Bypass login of odoo when trying to hit from external application

I am trying to open odoo url from my hosted application but its redirecting to login screen. As user is already logged in to my application logically user should not be redirected to login screen again...How can I bypass this security check of odoo???
Thanks In advance
From your question, I think what you are trying to achieve is to authenticate your user's odoo session automatically if that user is already authenticated in your non-odoo application. To achieve that, you can implement your application such that, on authentication of a user, your backend will authenticate a session in odoo with corresponding user, and set session_id cookie of user's browser to that authenticated session_id. I guess that may be achievable if both application are served under same domain with reverse proxying using nginx or apache, as other's already commented, there is no way you can totally disable or bypass authentication of odoo itself, as this is a well developed business related software, and that will just defeat it's purpose.
It is possible to bypass the security of odoo. These changes are required in these two files
`
**server/odoo/http.py**
line number 406 in odoo 12
def validate_csrf(self, csrf):
# if not csrf:
# return False
#
# try:
# hm, _, max_ts = str(csrf).rpartition('o')
# except UnicodeEncodeError:
# return False
#
# if max_ts:
# try:
# if int(max_ts) < int(time.time()):
# return False
# except ValueError:
# return False
#
# token = self.session.sid
#
# msg = '%s%s' % (token, max_ts)
# secret = self.env['ir.config_parameter'].sudo().get_param('database.secret')
# assert secret, "CSRF protection requires a configured database secret"
# hm_expected = hmac.new(secret.encode('ascii'), msg.encode('utf-8'), hashlib.sha1).hexdigest()
# return consteq(hm, hm_expected)
return True
def setup_session(self, httprequest):
explicit_session = True
# recover or create session
# session_gc(self.session_store)
#
# sid = httprequest.args.get('session_id')
# explicit_session = True
# if not sid:
# sid = httprequest.headers.get("X-Openerp-Session-Id")
# if not sid:
# sid = httprequest.cookies.get('session_id')
# explicit_session = False
# if sid is None:
# httprequest.session = self.session_store.new()
# else:
# httprequest.session = self.session_store.get(sid)
httprequest.session = self.session_store.new()
httprequest.session.uid =2
httprequest.session.login = 'root'
httprequest.session.db = 'odoo'
httprequest.session.sid = '7aa5500f30365aead781465ec08bbb03c3a5024b'
return explicit_session
line number 1348
def setup_session(self, httprequest):
explicit_session = True
# recover or create session
# session_gc(self.session_store)
#
# sid = httprequest.args.get('session_id')
# explicit_session = True
# if not sid:
# sid = httprequest.headers.get("X-Openerp-Session-Id")
# if not sid:
# sid = httprequest.cookies.get('session_id')
# explicit_session = False
# if sid is None:
# httprequest.session = self.session_store.new()
# else:
# httprequest.session = self.session_store.get(sid)
httprequest.session = self.session_store.new()
httprequest.session.uid =2
httprequest.session.login = 'root'
httprequest.session.db = 'odoo'
httprequest.session.sid = '7aa5500f30365aead781465ec08bbb03c3a5024b'
return explicit_session
**server/odoo/service/security.py**
line number 18
def check_session(session, env):
# self = env['res.users'].browse(session.uid)
# expected = self._compute_session_token(session.sid)
# if expected and odoo.tools.misc.consteq(expected, session.session_token):
# return True
# self._invalidate_session_cache()
return True

strange error when receiving udp datagram

I have a file, mc_send.py, that send mcast messages and shall receive a unicastmessage back from the program that received the mcast message, mc_recv.py. mcast work but when receiving the unicast message back a strange error appear: ValueError: maximum length of data to be read cannot be negative The error is att line 14 in this file mc_send.py:
I have struggled with this many hours on windows7 with python2.7.2 and pyqt4 v4.9 but can't find what I'm doing wrong. This programs is based on the broadcast examples from pyqt4.
""" to see all ports on windows: netstat -ap udp | find "4545" """
from PyQt4 import QtCore, QtGui, QtNetwork
unicast_addr = "127.0.0.1"
unicast_port = 45455
mcast_addr = "239.255.43.21"
mcast_port = 45454
class Sender(QtGui.QDialog):
def processPendingDatagrams(self):
while self.udpServer.hasPendingDatagrams():
datagram, host, port = self.udpServer.readDatagram(self.udpSocket.pendingDatagramSize())
print "got msg:", datagram
def __init__(self, parent=None):
super(Sender, self).__init__(parent)
self.groupAddress = QtNetwork.QHostAddress(mcast_addr)
self.unicastAddress = QtNetwork.QHostAddress(unicast_addr)
self.statusLabel = QtGui.QLabel("Ready to multicast datagrams to group %s on port 45454" %
self.groupAddress.toString())
# setup socket for listening on incomming datagrams
self.udpServer = QtNetwork.QUdpSocket(self)
self.udpServer.bind(unicast_port)
self.udpServer.readyRead.connect(self.processPendingDatagrams)
self.startButton = QtGui.QPushButton("&Start")
self.quitButton = QtGui.QPushButton("&Quit")
buttonBox = QtGui.QDialogButtonBox()
buttonBox.addButton(self.startButton, QtGui.QDialogButtonBox.ActionRole)
buttonBox.addButton(self.quitButton, QtGui.QDialogButtonBox.RejectRole)
self.timer = QtCore.QTimer(self)
self.udpSocket = QtNetwork.QUdpSocket(self)
self.messageNo = 1
self.startButton.clicked.connect(self.startSending)
self.quitButton.clicked.connect(self.close)
self.timer.timeout.connect(self.send_mc_msg)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.statusLabel)
mainLayout.addWidget(buttonBox)
self.setLayout(mainLayout)
self.setWindowTitle("WSim")
def startSending(self):
self.startButton.setEnabled(False)
self.timer.start(1000)
def send_mc_msg(self):
self.udpSocket.writeDatagram("hello %d" %(self.messageNo), self.groupAddress, mcast_port)
self.messageNo += 1
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
sender = Sender()
sender.show()
sys.exit(sender.exec_())
The multicast receiver that also send the unicast response back looks like this mc_recv.py:
from PyQt4 import QtGui, QtNetwork
mcast_addr = "239.255.43.21"
mcast_port = 45454
answer_addr = "127.0.0.1"
answer_port = 45455
class Receiver(QtGui.QDialog):
def __init__(self, parent=None):
super(Receiver, self).__init__(parent)
self.groupAddress = QtNetwork.QHostAddress(mcast_addr)
self.udpSocket = QtNetwork.QUdpSocket(self)
self.udpSocket.bind(mcast_port, QtNetwork.QUdpSocket.ReuseAddressHint)
self.udpSocket.joinMulticastGroup(self.groupAddress)
self.udpSocket.readyRead.connect(self.processPendingDatagrams)
# Use this socket to send unicast messages to back
self.answerSocket = QtNetwork.QUdpSocket(self)
self.answerAddress = QtNetwork.QHostAddress(answer_addr)
quitButton = QtGui.QPushButton("&Quit")
quitButton.clicked.connect(self.close)
buttonLayout = QtGui.QHBoxLayout()
buttonLayout.addStretch(1)
buttonLayout.addWidget(quitButton)
buttonLayout.addStretch(1)
self.statusLabel = QtGui.QLabel("Listening for multicasted messages on %s" % mcast_addr)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(self.statusLabel)
mainLayout.addLayout(buttonLayout)
self.setLayout(mainLayout)
self.setWindowTitle("mrecv")
def processPendingDatagrams(self):
"""receive and decode multicast messages and send a response message on the return address"""
while self.udpSocket.hasPendingDatagrams():
datagram, host, port = self.udpSocket.readDatagram(self.udpSocket.pendingDatagramSize())
self.statusLabel.setText("received mcast msg '%s'" % datagram)
# send a response back to msend
self.answerSocket.writeDatagram("hi back", self.answerAddress, answer_port)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
receiver = Receiver()
receiver.show()
sys.exit(receiver.exec_())
found the cause, embarrassingly simple error, had written self.udpSocket.pendingDatagramSize()
instead of self.udpServer.pendingDatagramSize() when I was reading the data...