receive SMS using python and python-smpp - python-3.x

I'm a newbie in SMPP but I need to simulate traffic over the SMPP protocol. I have found the tutorial how to send SMS using smpp lib from Python How to Send SMS using SMPP Protocol
I'm trying to write a receiver,but I am unable to get it to work. Please help.
My code is:
import smpplib
class ClientCl():
client=None
def receive_SMS(self):
client=smpplib.client.Client('localhost',1000)
try:
client.connect()
client.bind_receiver("sysID","login","password")
sms=client.get_message()
print(sms)
except :
print("boom! nothing works")
pass
sms_getter=ClientCl.receive_SMS

From what I can understand the smpplib you are using is the one available at github. Looking at your code and the client code, I can't find the function client.get_message. Perhaps you have an older version of the library? Or I have the wrong library. In any case, it is likely that the get_message function does not block and wait for the message to arrive.
Looking at the client code it seems that you have two options:
Poll the library until you get a valid message
Setup the library to listen to the SMPP port and call a function once a message arrives.
If you look at the README.md file it shows how you can setup the library to implement the second option (which is the better option).
...
client = smpplib.client.Client('example.com', SOMEPORTNUMBER)
# Print when obtain message_id
client.set_message_sent_handler(
lambda pdu: sys.stdout.write('sent {} {}\n'.format(pdu.sequence, pdu.message_id)))
client.set_message_received_handler(
lambda pdu: sys.stdout.write('delivered {}\n'.format(pdu.receipted_message_id)))
client.connect()
client.bind_transceiver(system_id='login', password='secret')
for part in parts:
pdu = client.send_message(
source_addr_ton=smpplib.consts.SMPP_TON_INTL,
#source_addr_npi=smpplib.consts.SMPP_NPI_ISDN,
# Make sure it is a byte string, not unicode:
source_addr='SENDERPHONENUM',
dest_addr_ton=smpplib.consts.SMPP_TON_INTL,
#dest_addr_npi=smpplib.consts.SMPP_NPI_ISDN,
# Make sure thease two params are byte strings, not unicode:
destination_addr='PHONENUMBER',
short_message=part,
data_coding=encoding_flag,
esm_class=msg_type_flag,
registered_delivery=True,
)
print(pdu.sequence)
client.listen()
...
When receiving a message or delivery receipt the function defined in client.set_message_received_handler() will be called. In the example, it is a lambda function. There is also an example on how to set up for listening in a thread.
If you prefer the simpler polling option you should use the poll function. For the simplest implementation all you need to do is:
while True:
client.Poll()
As before, the function set in client.set_message_received_handler() will be called once a message arrives.

Related

Appropriate way to run pytest unit tests for your API using threading.Thread and virtualports with socat

So I have written API for a device. The unit tests are going to run on CI automatically, therefore I will not test the connection with the device, purpose of these unit tests are to just test that my API generate appropriate requests and appropriately react to responses.
Before I had the following:
import serial
import threading
from src.device import Device # that is my API
class TestDevice:
#pytest.fixture(scope='class')
def device(self):
dev = Device()
dev.connect(port='/dev/ttyUSB0')
dev.connect() constantly sends command through serial port to establish handshake it will stay inside the function until response is received or timeout happens
So in order to simulate device, I have opened virtual serial port using socat:
socat -d -d pty,raw,echo=0 pty,raw,echo=0
My idea is to write into one virtual port and read from another. For that I would launch another threading and read from the message that has been sent, and upon thread receiving handshake request, I would sent a reply like this:
class TestDevice:
#pytest.fixture(scope='class')
def device(self):
reader_thread = threading.Thread(target=self.reader)
reader_thread.start()
dev = Device()
dev.connect('/dev/pts/3')
def reader(self):
EXPECTED_HANDSHAKE = b"hello"
HANDSHAKE_REPLY = b"hi"
timeout_handshake_ms = 1000
reader_port = serial.Serial(port='/dev/pts/4', baudrate=115200)
start_time_ns = time.time_ns()
timeout_time_ns = start_time_ns + (timeout_handshake_ms * 1e6)
while time.time_ns() < timeout_time_ns:
response = reader_port.read(1024)
# if dev.connect() sent an appropriate handshake request
# this port would receive it and then
if response == EXPECTED_HANDSHAKE:
reader_port.write(HANDSHAKE_REPLY)
And once the reply is received, dev.connect() will exit successfully and device will be considered successful. All of the code that I have posted works. As you can see, my approach is that I first start reading in a different thread, then I send a command, and in the reader thread I read the response and send appropriate response if applicable. The connection part was an easy one. However, I have 30 commands to test, all of them have different inputs, multiple arguments and etc. Reader's response also varies depending on the Request generated by API. Therefore, I will be needing to send same command with different arguments and I will need to reply to command in many different ways. What is the best way to organize my code, so I can test everything as possible as efficiently as possible. Do I need a thread for every command I am testing? Is there an efficient way to do all of this I have set out to?

How to debug a python websocket script that uses `.run_forever()` method (infinite event loop)

I'm coding a script that connects to the Binance websocket and uses the .run_forever() method to constantly get live data from the site. I want to be able to debug my code and watch the values of variables as the change but I'm not sure how to do this as the script basically hangs on the line with the .run_forever() method, because it is an infinite event loop. This is by design as I want to continuously get live data (it receives a message approximately every second), but I can't think of a way a good way to debug it.
I'm using VSCode and here are some snippets of my code to help understand my issue. The message function for the websocket is just a bunch of technical analysis and trade logic, but it is also the function that contains all the changing variables that I want to watch.
socket = f"wss://stream.binance.com:9443/ws/{Symbol}#kline_{interval}"
def on_open(ws):
print("open connection")
def on_message(ws, message):
global trade_list
global in_position
json_message = json.loads(message)
candle = json_message['k'] # Accesses candle data
...[trade logic code here]...
def on_close(ws):
print("Websocket connection close")
# ------------------------- Define a websocket object ------------------------ #
ws = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message, on_close=on_close)
ws.run_forever()
If more code is required to answer the question, then I can edit this question to include it (I'm thinking if you would like to have an idea of what variables I want to look at, I just thought it would be easier and simpler to show these parts).
Also, I know using global isn't great, once I've finished (or am close to finishing) the script, I want to go and tidy it up, I'll deal with it then.
I'm a little late to the party but the statement
websocket.enableTrace(True)
worked for me. Place it just before you define your websocket object and it will print all traffic in and out of the websocket including any exceptions that you might get as you process the messages.

Python SocketHandler with plain text

I've set up a SocketHandler but noticed it creates a binary output. I checked the docs and saw that it calls the "makePickle" function to create a binary output from the message record. I use dictConfig() to configure logging.
What I'd like to have is a plain text log message sent out to a TCP server without any pickling. I have two ideas in mind:
Create a custom handler derived from SocketHandler and override makePickle to return the plain text message with the given formatter
Create a custom handler derived from StreamHandler and pass IP and port and initialize stream to be a TCP stream
I can't decide which one is the better solution. Can you guys help me out? Also, if there's any other, easier and more straightforward way to achieve this I'm open to it.
Thanks
If anyone has the same problem, I decided to create a custom handler based on Socket handler. Like so:
class PlainTextTcpHandler(handlers.SocketHandler):
""" Sends plain text log message over TCP channel """
def makePickle(self, record):
message = self.formatter.format(record) + "\r\n"
return message.encode()
And you can use this handler as any other default one.

Getting Data from PolarH10 via BLE

I have been trying to get data from my PolarH10 with my raspberry-pi. I have been successfully getting data through the commandline with bluez, but have been unable to reproduce that in python. I am using pygatt(gatttool bindings) and python3.
I have been closely following the examples provided on bitbucket and was able to detect my device and filter out it's MAC address by filtering it by name. I however was unable to get either of the "reading data asyncronously" examples to work.
#This doesnt work...
req = gattlib.GATTRequester(mymac)
response = gattlib.GATTResponse()
req.read_by_handle_async(0x15, response) # what does the 0x15 mean?
while not response.received():
time.sleep(0.1)
steps = response.received()[0]
...
#This doesn't work either
class NotifyYourName(gattlib.GATTResponse):
def on_response(self, data):
print("your data is: {}".format(data))
response = NotifyYourName()
req = gattlib.GATTRequester(mymac)
req.read_by_handle_async(0x15, response)
while True:
# here, do other interesting things
time.sleep(1)
I don't know and cannot extract from the "documentation(s)" how to subscribe to/read notifications from a characteristic(heart rate) of my sensor(PolarH10). The error I am getting is when calling GATTRequester.connect(True) is
RuntimeError: Channel or attrib not ready.
Please tell me how correctly connect to a BLE device via Python on Debian and how to programatically identify offered services and their characteristics and how to get their notifications asyncronously in python using gattlib(pygatt) or any other library. Thanks!
The answer is: Just use bleak.
I have a device that presents the same behavior. In my case, the problem was that it does not have a channel of type public, I should use random instead (like in gatttool -b BE:BA:CA:FE:BA:BE -I -t random).
Just calling the connect() method with the parameter channel_type to random could fix it:
requester.connect(True, channel_type="random")
PD: Sorry for the late response (maybe it will be helpful to others).

Can MessageChannel overflow

I am working on an AS3 project in FDT6. I am using the lastest FLEX 4.6 and AIR 3.7.
I have a worker.swf file that is embedded into the main application to do threading work with.
I am using the MessageChannel class to pass information between the two.
In my main class I have defined
private var mainToWorker:MessageChannel;
private var workerToMain:MessageChannel;
mainToWorker = Worker.current.createMessageChannel(worker);
workerToMain = worker.createMessageChannel(Worker.current);
on the mainToWorker I only ever send messages. In these messages I send a byte array of information. The information is an object that contains a 'command' property and a 'props' property. Basically acting like a function call. The command is a function name and the props is an object that contains data for that function.
mainToWorkerMutex.lock();
mainToWorker.send(ByteArrayUtils.ObjectToByteArray({command:"DoSomething", props:{propA:1,propB:7}}));
mainToWorkerMutex.unlock();
The same occurs for the workerToMain var except I only send byte data that contains the 'message' and 'props' parameters.
workerToMainMutex.lock();
workerToMain.send(ByteArrayUtils.ObjectToByteArray({command:"complete", props:{return:"result"}}));
workerToMainMutex.unlock();
As a sanity check I make sure that the message channels are getting what they should.
It is working fine when I build it in FDT, however when it is built using an ANT script through flash builder I am sometimes getting the 'command' events coming back through in the workerToMain channel.
I am sending quite a lot of data through the message channel. Is it possible that I am overloading it and causing a buffer overflow into the other message channel somehow? How could that only be happening in FB?
I have checked my code many times and I am sure there is nothing in my own code that is sending that message back.
I had similar issue. When sending many bytearrays using channels sometimes things i received was not things i've actually sended. I had 4 channels (message channel to worker, message channel to main, data channel to worker, data channel to main).
I've noticed that data channel to main was affecting message channel to worker. When i turned off data channel to main - message channel to worker stared working just fine :D...
They have a big issue there with sending byte arrays it seems.
But what helped me was using shareable (at first it was not shareable) bytearray for communication via channels, but only for communication, as soon as i am receiving such bytearray i'm copying it to another byte array and parsing a copy.
This removed the problem (made quite hard stress tests there)...
Cheers
P.S. I'm also using static functions (like your ByteArrayUtils) to create bytearray's used for communication, but it seems fine, even made tests using non static functions.
So, it looks like I have found the issue. Looks like it's the ByteArray that is doing it.
ByteArray.toString() is basically sometimes mangles your data meaning you can't really trust it.
http://www.actionscript.org/forums/showthread.php3?t=155067
If you read the comment by "Jim Freer" he mentions how strings sometimes do this.
My solution was to switch to using a JSON encoded string instead of ByteArray data in the message channel. The reason I was using bytearray data to begin with is because I wanted to preserve class definition information, which JSON doesn't do.

Resources