Python MQTT to publish multiple message with same topic - python

I am trying to publish a multiple random data using mqtt to the broker. Below is the script for the publish part.
import paho.mqtt.client as mqtt
import json, schedule, time, random
client = mqtt.Client()
client.connect("<broker address", 1883, 60)
def pub_message():
tempreading = random.uniform(0, 100)
pHreading = random.uniform(1,14)
oxyreading = random.uniform(0, 100)
data_string1 = str(oxyreading)
data_string2 = str(pHreading)
data_string3 = str(tempreading)
msgs = [("randomdata", data_string1),("randomdata", data_string2),("randomdata", data_string3)]
client.publish(msgs)
schedule.every(1).minutes.do(pub_message)
while True:
schedule.run_pending()
time.sleep(1)
client.disconnect()
I ran the script and there is error like below:
Traceback (most recent call last):
File "mqttpub.py", line 27, in <module>
schedule.run_pending()
File "/usr/local/lib/python2.7/dist-packages/schedule/__init__.py", line 462, in run_pending
default_scheduler.run_pending()
File "/usr/local/lib/python2.7/dist-packages/schedule/__init__.py", line 75, in run_pending
self._run_job(job)
File "/usr/local/lib/python2.7/dist-packages/schedule/__init__.py", line 129, in _run_job
ret = job.run()
File "/usr/local/lib/python2.7/dist-packages/schedule/__init__.py", line 377, in run
ret = self.job_func()
File "mqttpub.py", line 22, in pub_message
client.publish(msgs)
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 980, in publish
rc = self._send_publish(local_mid, topic, local_payload, qos, retain, False, info)
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 1979, in _send_publish
utopic = topic.encode('utf-8')
AttributeError: 'list' object has no attribute 'encode'
I searched about the publish multiple message with mqtt but did not find any good reference. I also included my mqtt subscribe part for receiving the multiple messages. I did search about this part too but did not find any good reference.
import paho.mqtt.client as mqtt
from models import *
from sqlalchemy.orm import sessionmaker
import json
def on_connect(client, userdata, rc):
print("connected with result code" + str(rc))
client.subscribe("randomdata")
def on_message(client, userdata, msg):
print "Topic:", msg.topic + " " + "Message:" + " " + "Value1:" + str(msg.payload1) + " " + "Value2:" + str(msg.payload2) + " " + "Value3:" + str(msg.payload3)
engine = create_engine('postgresql://user:password#localhost/mydatabase')
Base.metadata.bind = engine
DBSession = sessionmaker(bind=engine)
session = DBSession()
# store message received into database
raw_data = _Data(Value1=msg.payload1, Value2=msg.payload2, Value3=msg.payload3, time=msg.timestamp)
session.add(raw_data)
session.commit()
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("<broker address>",1883, 60)
client.loop_forever()
Does anyone have any experience doing it? Thank you in advance.

What makes you think client.publish() will accept an array?
The doc's (https://pypi.python.org/pypi/paho-mqtt/1.1#publishing) don't mention anything about publishing multiple messages, you will have to call client.publish() once for every message you want to send.
You should also be calling client.loop() in your while true loop.
while True:
schedule.run_pending()
client.loop()
time.sleep(1)

Related

Chat Bot don't polling

I,m just study codding, and try make chat-bot. But it's don' work, please help me.
I'ts my code:
import time
import logging
from aiogram import Bot, Dispatcher, types, executor
logging.basicConfig(level=logging.INFO)
TOKEN = '6292675773:AAGBBeUms_4NILy6h26TH4rGLyml7h3bHWg'
MSG = 'Hello, are you coddind today?'
bot = Bot(token=TOKEN)
dp = Dispatcher(bot=bot)
#dp.message_handler(Commands=['start'])
async def start_handler(message: types.Message):
user_id = message.from_user.id
user_name = message.from_user.first_name
user_full_name = message.from_user.first_name
logging.info(f'{user_id} {user_full_name} {time.asctime()}')
await message.reply(f"Hello, {user_full_name}!")
for i in range(10):
time.sleep(2)
await bot.send_message(user_id, MSG.format(user_name))
if __name__ == '__main__':
executor.start_polling(dp)
and it's Error:
(venv) PS C:\Users\roman\PycharmProjects\pythonProject> python main.py
Traceback (most recent call last):
File "C:\Users\roman\PycharmProjects\pythonProject\main.py", line 14, in
#dp.message_handler(Commands = ['start'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\roman\PycharmProjects\pythonProject\venv\Lib\site-packages\aiogram\dispatcher\dispatcher.py", line 560, in decorator
self.register_message_handler(callback, *custom_filters,
File "C:\Users\roman\PycharmProjects\pythonProject\venv\Lib\site-packages\aiogram\dispatcher\dispatcher.py", line 479, in register_message_handler
filters_set = self.filters_factory.resolve(self.message_handlers,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\roman\PycharmProjects\pythonProject\venv\Lib\site-packages\aiogram\dispatcher\filters\factory.py", line 51, in resolve
filters_set = list(
^^^^^
File "C:\Users\roman\PycharmProjects\pythonProject\venv\Lib\site-packages\aiogram\dispatcher\filters\factory.py", line 77, in _resolve_registered
raise NameError("Invalid filter name(s): '" + "', ".join(full_config.keys()) + "'")
NameError: Invalid filter name(s): 'Commands'

A Question file transfer using socket in python

I'm currently creating an encrypted chat program. Text chat works well. However, I want to implement file transfer, but it doesn't work. My code is trying to work in a way that when one client tries to transfer a file, the server receives it and sends it to another client. When I type '/filetransfer' to transfer file.
Dick: hi
/filetransfer
Sending...
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Python\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "c:\Users\USER\Desktop\filetest\client.py", line 198, in sndChat
self.sndFile()
File "c:\Users\USER\Desktop\filetest\client.py", line 233, in sndFile
clientSocket.send(l)
This error occurred. I think the client cannot send the file data.
Also, I would like to apply Diffie-Hellman and AES used for text encryption to file transfer. I spent a lot of time here, but it doesn't work. I desperately need help...
Client.py
def rcvChat(self):
print("\nWelcome to Chatee!")
while True:
try:
message = clientSocket.recv(4096).decode(encodeType)
if self.thred_done:
message=self.aes.decrypt(message)
print(message)
if message == 'filetransfer start':
filereceive_thread = threading.Thread(target=self.rcvChat)
filereceive_thread.join()
#write_thread = threading.Thread(target=self.sndChat)
#write_thread.join()
#self.rcvFile()
break
def sndChat(self):
while True:
message = input('')
if message == '/filetransfer':
message = self.aes.encrypt(message)
clientSocket.send(message)
writefile_thread = threading.Thread(target=self.sndChat)
writefile_thread.start()
self.sndFile()
break
message = self.aes.encrypt(message)
clientSocket.send(message)
def sndFile(self):
print("---File Transfer---")
print("Type a file name...")
filename = 'C:\\Users\\USER\\Desktop\\filetest\\test.txt'
#clientSocket.send(filename.encode(encodeType))
#data_transferred = 0
if not exists(filename):
print("The file doesn't exsit.")
f = open(filename,'rb')
print ('Sending...')
l = f.read(8096)
while (l):
print ('Sending...')
#data_transferred += clientSocket.send(l)
clientSocket.send(l)
l = f.read(8096)
f.close()
print ('Done Sending')
#clientSocket.shutdown(socket.SHUT_WR)
print (clientSocket.recv(8096))
#clientSocket.close
def rcvFile(self):
#filename = clientSocket.recv(1024).decode(encodeType)
#filename = self.aes.decrypt(filename)
filename = 'received.txt'
f = open(filename,'wb')
while True:
print ('Receiving...')
l = clientSocket.recv(8096)
if not l:
print("Fail file transfer")
#sys.exit()
while (l):
print ('Receiving...')
f.write(l)
l = clientSocket.recv(8096)
f.close()
print ('Done Receiving')
Server.py
def handle_client(self,client,client_addr):
client_pvt_key=self.client_keys[client]
client_name=self.clients[client]
print(f"[{client_addr[0]}]-{client_addr[1]} - [{client_name}] - Connected")
print(f"Active Connections - {threading.active_count()-1}")
self.broadcast(f'{client_name} has joined the chat!\n\n')
aes=AESCipher(client_pvt_key)
while True:
try:
msg = aes.decrypt(client.recv(self.header)) #복호화 안하고 바로 브로드캐스트 해도 될듯
if msg == '/filetransfer':
#보낸 사람 제외하고 보내기
self.broadcast('filetransfer start')
thread = threading.Thread(target=self.sndFile, args=(client, ))
thread.start()
thread.join()
elif msg==self.quit_msg:
break
print(f"[{client_addr[0]}]-{client_addr[1]} - [{client_name}]")
msg=f'{client_name}: {msg}'
self.broadcast(msg)
except:
break
client.close()
print(f"[{client_addr[0]}]-{client_addr[1]} - [{client_name}] - quit_msged")
del self.clients[client]
del self.client_keys[client]
self.broadcast(f'{client_name} has left the chat\n')
print(f"Active Connections - {threading.active_count()-2}")
def broadcast(self,msg):
for client in self.clients:
aes=AESCipher(self.client_keys[client])
crypted_msg=aes.encrypt(msg)
client.send(crypted_msg)
def sndFile(self, client):
print("---File Transfer---")
#print("Type a file name...")
client_pvt_key=self.client_keys[client]
aes=AESCipher(client_pvt_key)
#filename = client.recv(1024).decode(self.encodetype)
#self.broadcast('fuck',filename)
while True:
try:
l = client.recv(8096)
print('Rceiving...')
#del self.clients[client]
for client in self.clients:
client.send(l)
#client.send(filename.encode(self.encodetype))
#l = client.recv(8096)
if not l:
print("Fail file transfer")
except:
print('file fail')
break

MQTT: Python script should subscribe to subtopics

we're working on a project where some sensors send data to a mqtt broker and we wrote a python script which takes this data and stores it in a csv file.
now when we're adding more sensors our topics vary like this:
topic/sensor1
topic/sensor2
and so on. Now we want to get the subtopics automated in this script to not hardcode it when a sensor is added or removed.
Have you any suggestions, how we can subscribe in a loop to all subtopics?
We have the following so far:
import paho.mqtt.client as mqtt
import logging
from datetime import datetime
def on_subscribe(mosq, obj, mid, granted_qos):
print("Subscribed: " + str(mid))
def on_log(client, userdata, level, buf):
print(buf)
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("envdata/#")
def on_message(client, userdata, msg):
f = open("log.csv", "a")
msg_decoded = str(msg.payload, 'utf-8')
msg_decoded = msg_decoded.replace("\n","")
msg_decoded = msg_decoded + "\ttime:" + datetime.now().strftime("%d/%m/%Y %H:%M:%S") + "\n"
f.write(msg_decoded)
f.close()
print(msg.topic+" "+msg_decoded)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.on_log = on_log
client.on_subscribe = on_subscribe
client.username_pw_set(user, password=password)
client.connect(url, 1883, 60)
client.loop_forever()
We figured it out. So as we subscribe to each subtopic with client.subscribe("topic/#") we can access all topcs in on_message callback with msg.topic.
And now we can store this topic in a string which represents the .csv file.
So our on_message callback now looks like the following:
def on_message(client, userdata, msg):
filename = msg.topic
filename = filename.replace("/","-")
f = open(filename + ".csv", "a")
msg_decoded = str(msg.payload, 'utf-8')
msg_decoded = msg_decoded.replace("\n","")
msg_decoded = msg_decoded + "\ttime:" + datetime.now().strftime("%d/%m/%Y %H:%M:%S") + "\n"
f.write(msg_decoded)
f.close()
print(msg.topic+" "+msg_decoded)
This works fine for what we wanted to reach with this script. Now when new messages are recognised by the script it opens or creates a file like topic-subtopic.csv and fills it with the expected data.

on_connect() takes exactly 3 arguments (4 given)

(ERROR MODULE) python mqtt_Listen_Sensor_Data.py
Previously I had a problem with localhost but now im getting another error. I'm trying to store my MQTT data in SQLITE database on raspberry. What am I doing wrong to get the error below?
CODE:
import paho.mqtt.client as mqtt
from store_Sensor_Data_to_DB import sensor_Data_Handler
# MQTT Settings
MQTT_Broker = "localhost"
MQTT_Port = 1883
Keep_Alive_Interval = 45
MQTT_Topic = "kuca/primanje/kanta01/r"
#Subscribe to all Sensors at Base Topic
def on_connect(mosq, obj, rc):
self.subscribe(MQTT_Topic,0)
#Save Data into DB Table
def on_message(mosq, obj, msg):
self.subscribe(MQTT_Topic, 0)
# This is the Master Call for saving MQTT Data into DB
# For details of "sensor_Data_Handler" function please refer "sensor_data_to_db.py"
print "MQTT Data Received..."
print "MQTT Topic: " + msg.topic
print "Data: " + msg.payload
sensor_Data_Handler(msg.topic, msg.payload)
def on_subscribe(mosq, obj, mid, granted_qos):
pass
mqttc = mqtt.Client()
# Assign event callbacks
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_subscribe = on_subscribe
# Connect
mqttc.connect(MQTT_Broker, int(MQTT_Port), int(Keep_Alive_Interval))
# Continue the network loop
mqttc.loop_forever()
ERROR:
pi#Pi:~/Desktop/SQLITE $ python mqtt_Listen_Sensor_Data.py
Traceback (most recent call last):
File "mqtt_Listen_Sensor_Data.py", line 46, in <module>
mqttc.loop_forever()
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 1481, in loop_forever
rc = self.loop(timeout, max_packets)
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 1003, in loop
rc = self.loop_read(max_packets)
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 1284, in loop_read
rc = self._packet_read()
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 1849, in _packet_read
rc = self._packet_handle()
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 2311, in _packet_handle
return self._handle_connack()
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 2372, in _handle_connack
self.on_connect(self, self._userdata, flags_dict, result)
TypeError: on_connect() takes exactly 3 arguments (4 given)
I am really sorry for having troubled you so much.
Your problem resides here: you define a function, and address the self without actually passing it:
#Subscribe to all Sensors at Base Topic
def on_connect(mosq, obj, rc):
self.subscribe(MQTT_Topic,0)
Then you create an object, and assign your function as an attribute of that object:
mqttc = mqtt.Client()
# Assign event callbacks
mqttc.on_message = on_message
mqttc.on_connect = on_connect
Your on_connect function isn't an instance method.
When you call an instance method, the self variable is passed as first argument.
So when you call mgttc.on_connect(x, y, z) what actually executed is mgttc.on_connect(self, x, y, z).
Your on_connect() callback must have this signature (from paho python doc) :
def on_connect(client, userdata, flags, rc):
If you want to use it in another class you can use this signature :
def on_connect(self, client, userdata, flags, rc):
Furthermore, variable self is undefined in the on_connect() and on_message() callbacks, for example :
self.subscribe(MQTT_Topic,0)
must be
mqttc.subscribte(MQTT_Topic, 0)
Hope this will help you

how to use threading with a 'neverending' process

I'm attempting to add an irc client to a django web application I'm working on. I'd like the server side code for the irc communication to use python and connect through the sockets library. I'll then use gevent-socketio to send and receive data from the irc channel to the client side in the browser. So far I have a very basic gevent-socketio server and client that can be used for realtime broadcasting amongst multiple clients, however, when I start to connect clients to IRC they connect to the IRC server successfully using a nick passed from the client, but then it appears that this is ongoing keepalive/listening process is blocking be from sending any messages from the client.
Python IRC code
import socket
class pycli:
def __init__(self,user):
self.nick = user
self.chan = "#testchannel"
self.owner = "Bluebot"
self.sock = socket.socket()
print "irc conn"
def send_msg(self,message):
self.sock.send("PRIVMSG " + self.chan + " : " + message + "\r\n")
## misc setup
def keep_alive(self):
self.sock.connect(("irc.freenode.net",6667))
self.sock.send("USER " + self.nick + " 0 * :" + self.owner + "\r\n")
self.sock.send("NICK " + self.nick + "\r\n")
while 1:
## keep checking for data
data = self.sock.recv(512)
datalen = len(data.split(" "))
sender = ""
msg_type = ""
msg_rcpt = ""
message = ""
###----------------------------------------------
## reply to keep alive pings
if data[0:4] == "PING":
self.sock.send(data.replace("PING", "PONG"))
if data[0]!=':':
continue
if data.split(" ")[1] == "001":
self.sock.send("MODE " + self.nick + " +B\r\n")
self.sock.send("JOIN " + self.chan + "\r\n")
###-----------------------------------------------
##split and assign data parts
## parse out the actual sender
send_data = data.split(" ")[0]
send_data = send_data[1:]
sender = send_data.split('!')[0]
## mode
msg_type = data.split(" ")[1]
## if it exists get the recipient (room or private)
if datalen > 2:
msg_rcpt = data.split(" ")[2]
## get the actual message body
if datalen > 3:
message = (" ".join(data.split(" ")[3:])).lower()[1:]
print data
I know this functionality is super basic, but I can expand on it once I get it working through the client.
The relevant parts of my server code basically looks like:
def on_login(self, nick):
if self.nick:
self._broadcast('exit', self.nick)
self.nick = nick
self._broadcast('enter', nick)
self.emit('users',
[ ns.nick
for ns in self._registry.values()
if ns.nick is not None ])
t = threading.Thread(target=self.make_start_irc(nick),daemon=True)
t.start()
def on_chat(self, message):
if self.nick:
self._broadcast('chat', dict(u=self.nick, m=message))
self._irc_nicks[self.nick].send_msg("this is a test")
else:
self.emit('chat', dict(u='SYSTEM', m='You must first login'))
def make_start_irc(self,nick):
if nick not in self._irc_nicks.values():
self._irc_nicks[nick] = pycli.pycli(nick)
print self._irc_nicks
self._irc_nicks[nick].keep_alive()
def _broadcast(self, event, message):
for s in self._registry.values():
s.emit(event, message)
def chat(environ, start_response):
if environ['PATH_INFO'].startswith('/socket.io'):
return socketio_manage(environ, { '/chat': ChatNamespace })
else:
return serve_file(environ, start_response)
def serve_file(environ, start_response):
path = os.path.normpath(
os.path.join(public, environ['PATH_INFO'].lstrip('/')))
assert path.startswith(public), path
if os.path.exists(path):
start_response('200 OK', [('Content-Type', 'text/html')])
with open(path) as fp:
while True:
chunk = fp.read(4096)
if not chunk: break
yield chunk
else:
start_response('404 NOT FOUND', [])
yield 'File not found'
if __name__ == "__main__":
from gevent import monkey
monkey.patch_all()
sio_server = SocketIOServer(
('', 8080), chat,
policy_server=False)
t2 = threading.Thread(target=sio_server.serve_forever())
t2.start()
When I eventually give up and use ctrl-C, I see the following stacktrace which leads me to believe something about the way I'm threading is blocking.
Traceback (most recent call last):
File "socketio_test.py", line 92, in <module>
t2 = threading.Thread(target=sio_server.serve_forever())
File "/Users/andrewscott/Desktop/wham/pycli/wham/lib/python2.7/site-packages/gevent/baseserver.py", line 284, in serve_forever
self._stop_event.wait()
File "/Users/andrewscott/Desktop/wham/pycli/wham/lib/python2.7/site-packages/gevent/event.py", line 77, in wait
result = self.hub.switch()
File "/Users/andrewscott/Desktop/wham/pycli/wham/lib/python2.7/site-packages/gevent/hub.py", line 338, in switch
return greenlet.switch(self)
KeyboardInterrupt
If anyone has any idea how I can change the irc process to be non-blocking, or any general suggestions they'd be greatly appreciated.
You should remove the call:
t2 = threading.Thread(target=sio_server.serve_forever())
And properly pass the method:
t2 = threading.Thread(target=sio_server.serve_forever)

Categories

Resources