I'm using pika to send message to rabbitmq.
I need to send additional properties so I'm using pika.BasicProperties, but when I see this message in Wireshark there are no properties added.
My code:
import pika, uuid
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='test_60', durable=True, arguments={'x-message-ttl' : 21600000})
routingKey = "test_server"
message = '{"test_int":268,"Timestamp":1610022012203}'
correlation_id = str(uuid.uuid4())
reply_to = "test_60"
message_type = "SendRequest"
channel.basic_publish(exchange='',routing_key=routingKey,
body=message,properties=pika.BasicProperties(
headers={"testId": "60"},
delivery_mode=2,
correlation_id = correlation_id,
reply_to = reply_to,
type = message_type))
print('message sent')
print(correlation_id)
In Wireshark this message looks like this, so there are no properties and I have no idea what is wrong with this example.
prop = pika.BasicProperties(
content_type='application/json',
content_encoding='utf-8',
headers={'key': 'value'},
delivery_mode = 1,
)
channel.basic_publish(
exchange='',
routing_key=qname,
properties=prop,
body='{message: hello}'
)
UI:
Wireshark:
Related
I have created a module for a Bacnet scan and it will respond with a list of devices and its address as a result. But I'm having trouble implementing a direct method handler in python. When i first tried implementing it myself i got this error. Which could mean I didn't successfully register the direct method callback. I have some references but it was from C# and azure docs is not helping me figure out the right method to register the callback. for IoTHubModuleClient there's a on_method_request_received and a receive_method_request. appreciate any help!
def iothub_client_scan_run():
try:
iot_client = iothub_client_init()
bacnet_scan_listener_thread = threading.Thread(target=device_method_listener, args=(iot_client,))
bacnet_scan_listener_thread.daemon = True
bacnet_scan_listener_thread.start()
while True:
time.sleep(1000)
def device_method_listener(iot_client):
while True:
# Receive the direct method request
method_request = iot_client.receive_method_request()
print (
"\nMethod callback called with:\nmethodName = {method_name}\npayload = {payload}".format(
method_name=method_request.name,
payload=method_request.payload
)
)
if method_request.name == "runBacnetScan":
response = bacnet_scan_device(method_request)
else:
response_payload = {"Response": "Direct method {} not defined".format(method_request.name)}
response_status = 404
# Send a method response indicating the method request was resolved
print('Sending method response')
iot_client.send_method_response(response)
print('Message sent!')
Edit:
Here is my route config
I was able to resolve my issue or at least find the root cause and it was my network configuration under the createOptions. It seems like there's an issue when I'm trying to do NetworkMode: host and connects to the IotModuleClient.connect_from_edge_environment via connect with connection string. I'm still trying to tweak the connection configuration but at least i know its not on the code.
async def method_request_handler(module_client):
while True:
method_request = await module_client.receive_method_request()
print (
"\nMethod callback called with:\nmethodName = {method_name}\npayload = {payload}".format(
method_name=method_request.name,
payload=method_request.payload
)
)
if method_request.name == "method1":
payload = {"result": True, "data": "some data"} # set response payload
status = 200 # set return status code
print("executed method1")
elif method_request.name == "method2":
payload = {"result": True, "data": 1234} # set response payload
status = 200 # set return status code
print("executed method2")
else:
payload = {"result": False, "data": "unknown method"} # set response payload
status = 400 # set return status code
print("executed unknown method: " + method_request.name)
# Send the response
method_response = MethodResponse.create_from_method_request(method_request, status, payload)
await module_client.send_method_response(method_response)
print('Message sent!')
def stdin_listener():
while True:
try:
selection = input("Press Q to quit\n")
if selection == "Q" or selection == "q":
print("Quitting...")
break
except:
time.sleep(10)
# Schedule task for C2D Listener
listeners = asyncio.gather(input1_listener(module_client), twin_patch_listener(module_client), method_request_handler(module_client))
I can't load JSON-type message with dictionary inside when client receives it from server
Dictionary contains: message, sender address, time of sending
When i dump dictionary to JSON and send it to client, client tries to load this dict, so he can't use data from dictionary from server and print it to user
Also, when client sending message he can write "/r" to receive data from server, that means client can receive big data at one time.
This is only parts of code with sending and receiving data from server and in client
SERVER
def serialize_data(self, sending_time, message, address,):
message_dict = {
'sending_time': sending_time,
'message': message,
'sender_address': address
}
serialized_dict = dumps(message_dict)
return serialized_dict
def send_messages(self, data_dict, address):
if enable_log:
message = f'{self.get_time()}, {data_dict["message"]}, {address}'
self.save_log(message, 'a')
message = self.serialize_data(self.get_time(), data_dict['message'], address)
for client in self.connections_list:
message = dumps(message)
client.sendall(bytes(message, encoding='utf-8'))
CLIENT
def receive_data(self,):
while True:
try:
data = self.sock.recv(2048).decode('utf-8')
print(data)
data_dict = loads(data)
for d in data_dict:
d = loads(d)
d = f"{d['sending_time']} {d['sender_address']} - {d['message']}"
print(d)
except timeout:
break
I getting this in client when i trying to receive data from server:
"{\"sending_time\": \"2019-05-17 | 21:16:32 \", \"message\": \"connected!\", \"sender_address\": \"127.0.0.1\"}""{\"sending_time\": \"2019-05-17 | 21:16:33 \", \"message\": \"abcd\", \"sender_address\": \"127.0.0.1\"}"
That is because you are calling json.dumps() twice.
def serialize_data(self, sending_time, message, address,):
message_dict = {
'sending_time': sending_time,
'message': message,
'sender_address': address
}
serialized_dict = dumps(message_dict) # -------------> first time
return serialized_dict
def send_messages(self, data_dict, address):
if enable_log:
message = f'{self.get_time()}, {data_dict["message"]}, {address}'
self.save_log(message, 'a')
message = self.serialize_data(self.get_time(), data_dict['message'], address)
for client in self.connections_list:
message = dumps(message) # ------------------> Second time
client.sendall(bytes(message, encoding='utf-8'))
Removing either one of them should fix it.
I have created a Cloud Compute Engine instance on Debian, and have successfully created a PUSH subscription to a topic with
from google.cloud import pubsub_v1
project_id = "censored"
topic_name = "censored"
subscription_name = "censored"
endpoint = "https://censored.appspot.com/pubsub/push?token=censored"
def create_push_subscription(project_id,
topic_name,
subscription_name,
endpoint):
"""Create a new push subscription on the given topic."""
# [START pubsub_create_push_subscription]
subscriber = pubsub_v1.SubscriberClient()
topic_path = subscriber.topic_path(project_id, topic_name)
subscription_path = subscriber.subscription_path(
project_id, subscription_name)
push_config = pubsub_v1.types.PushConfig(
push_endpoint=endpoint)
subscription = subscriber.create_subscription(
subscription_path, topic_path, push_config)
print('Push subscription created: {}'.format(subscription))
print('Endpoint for subscription is: {}'.format(endpoint))
# [END pubsub_create_push_subscription]
create_push_subscription(project_id, topic_name, subscription_name, endpoint)
but I'm not sure how exactly incoming messages arrive. I have found this sample code to parse messages, but I'm not sure how to get it to monitor in the background and 'activate' whenever incoming messages arrive.
import argparse
import base64
import json
import sys
import time
from google.cloud import pubsub_v1
def summarize(message):
# [START parse_message]
data = message.data.decode('utf-8')
attributes = message.attributes
name = attributes['name']
time_created = attributes['timeCreated']
bucket_id = attributes['bucketId']
object_id = attributes['objectId']
generation = attributes['objectGeneration']
description = (
'\tName: {name}\n'
'\tTime Created: {time_created}\n'
'\tBucket ID: {bucket_id}\n'
'\tObject ID: {object_id}\n'
'\tGeneration: {generation}\n'
).format(
name=name,
time_created=time_created,
bucket_id=bucket_id,
object_id=object_id,
generation=generation
)
if 'overwroteGeneration' in attributes:
description += '\tOverwrote generation: %s\n' % (
attributes['overwroteGeneration'])
if 'overwrittenByGeneration' in attributes:
description += '\tOverwritten by generation: %s\n' % (
attributes['overwrittenByGeneration'])
payload_format = attributes['payloadFormat']
if payload_format == 'JSON_API_V1':
object_metadata = json.loads(data)
name = object_metadata['name']
time_created = object_metadata['timeCreated']
size = object_metadata['size']
content_type = object_metadata['contentType']
metageneration = object_metadata['metageneration']
description += (
'\tName: {name}\n'
'\tTime Created: {time_created}\n'
'\tContent type: {content_type}\n'
'\tSize: {object_size}\n'
'\tMetageneration: {metageneration}\n'
).format(
name=name,
time_created=time_created,
content_type=content_type,
object_size=size,
metageneration=metageneration
)
return description
print('Note for developer: If BucketId and ObjectId listed, utf encoding.')
print('If not, JSON_V1 encoding. Adjust accordingly.')
# [END parse_message]
while(True):
print("signpost 1")
summarize(message)
print("signpost 2")
time.sleep(10)
print("signpost 3")
For example, this code will return
NameError: name 'message' is not defined
which is expected...
Could someone please help me set it up properly?
I know it's different in PULL because then the message will be defined during the pull, but I'd like to keep it as PUSH, if possible.
You need to create a long-running process which is either able to continuously poll for new messages (pull subscription) or have a reachable endpoint to receive new messages (push subscription).
See the example here: https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/pubsub/cloud-client/subscriber.py, as well as the differences between push and pull here: https://cloud.google.com/pubsub/docs/subscriber
I would like to get all the messages from a chat that have been sent today.
import sys,datetime
from telethon import TelegramClient
api_id = 1234567
api_hash = "0986asdgshjfag"
client = TelegramClient('session_name', api_id, api_hash)
client.start()
dialogs = client.get_dialogs()
chat = client.get_input_entity('username')
filter = InputMessagesFilterEmpty()
result = client(SearchRequest(
peer=chat, # On which chat/conversation
q='', # What to search for
filter=filter, # Filter to use (maybe filter for media)
min_date=datetime.date.today(), # Minimum date
max_date=None, # Maximum date
offset_id=0, # ID of the message to use as offset
add_offset=0, # Additional offset
limit=5, # How many results
max_id=0, # Maximum message ID
min_id=0, # Minimum message ID
from_id=None, # Who must have sent the message (peer)
hash=0 # Special number to return nothing on no-change
))
for message in client.iter_messages(chat,filter=result):
print(message.message)
The filter doesn't work at all, I can see more than 5 messages (the whole chat) and it doesn't care about the time.
Why?
You can use 'message.date'.
If you want to get the message from today you need to check the sent day. and this would be like :
if datetime.datetime.now().strftime('%Y-%m-%d') == message.date.strftime('%Y-%m-%d')
Help: Relatively new to telethon and was having issue with delete_messages()function. It "seems" to do nothing for me...
Initially I am getting the message id from send_message, from the return object's id value. It returns values like 1, 2, etc. Not sure this is the message id though.
I send it to delete_messages as delete_messages(channel, [id])
I get the channel (It's a private channel) from:
def resolve_channel_id(self, name):
try:
if name in self.__channel_ids:
return self.__channel_ids[name]
channel_id = self.client(ResolveUsernameRequest(name))
self.__channel_ids[name] = channel_id
return channel_id
# except UserNameNotOccupiedError as err:
except Exception as err:
# try for private channel
chatinvite = self.client(CheckChatInviteRequest(name))
channel_id = chatinvite.chat.id
access_hash_channel = chatinvite.chat.access_hash
channel_id = InputChannel(channel_id, access_hash_channel)
self.__channel_ids[name] = channel_id
return channel_id
I hope this example is useful for friends :
by this code, if a message with a Hello text is sent to a group with ID -1001300989487, that text will be deleted.
import logging
from telethon import TelegramClient, events
logging.basicConfig(level=logging.INFO)
api_id = XXXXXX
api_hash = 'XXXXXXXXXXXXXXXXXXXXXXX'
phone_number = '+989XXXXXXXX'
################################################
client = TelegramClient('session_name',
api_id,
api_hash,
)
#client.on(events.NewMessage(chats=(-1001300989487)))
async def my_event_handler(event):
if 'hello' in event.raw_text:
await event.delete()
client.start()
client.run_until_disconnected()
print('finish')
Works by updating to latest telethon: 1.0.3, and following documentation... https://telethon.readthedocs.io/en/latest/extra/basic/asyncio-magic.html