I am attempting to assemble a small proof of concept system on IBM's Bluemix/Internet of Things. Currently this comprises of a Raspberry Pi feeding events up to the cloudbased app, which currently stores those events away, and periodically attempts to send down a command, using the following code block:
def sendCmd(command, payload, device="raspberrypi" ):
deviceId = #Fixed value
global cmdCount
client.publishCommand("raspberrypi", deviceId, str(command), "json", payload)
print "Sending '%s' cmd, payload '%s' to device %s" % (command, payload, deviceId)
cmdCount = cmdCount + 1
As far as the documentation is concerned this appears to be the correct syntax, as described by the documentation :
client.connect()
commandData={'rebootDelay' : 50}
client.publishCommand(myDeviceType, myDeviceId, "reboot", "json", myData)
No exceptions are thrown in this block of code, however the device is not receiving any commands; and the cloud foundry log is not throwing any errors. Is there a subtle point about the syntax I am missing?
This issue boiled down to having instantiated the wrong class on the Raspberry Pi. I had an instance of ibmiotf.application which registered a function to the variable self.client.commandCallback. However nothing appeared to be triggering the callback.
Once I instantiated the device with the ibmiotf.device import rather than ibmiotf.application, the command callback started to be called. This required a couple of the minor changes, to support slightly different function calls, but they were fairly self explanatory when trying to run the code.
The Device Class controls Events being published from the unit, and determines how to handle commands from upstream. Whereas the Application Class handles the receipt of Events and emission of Commands.
Related
We are facing an MismatchingMessageCorrelationException for the receive task in some cases (less than 5%)
The call back to notify receive task is done by :
protected void respondToCallWorker(
#NonNull final String correlationId,
final CallWorkerResultKeys result,
#Nullable final Map<String, Object> variables
) {
try {
runtimeService.createMessageCorrelation("callWorkerConsumer")
.processInstanceId(correlationId)
.setVariables(variables)
.setVariable("callStatus", result.toString())
.correlateWithResult();
} catch(Exception e) {
e.printStackTrace();
}
}
When i check the logs : i found that the query executed is this one :
select distinct RES.* from ACT_RU_EXECUTION RES
inner join ACT_RE_PROCDEF P on RES.PROC_DEF_ID_ = P.ID_
WHERE RES.PROC_INST_ID_ = 'b2362197-3bea-11eb-a150-9e4bf0efd6d0' and RES.SUSPENSION_STATE_ = '1'
and exists (select ID_ from ACT_RU_EVENT_SUBSCR EVT
where EVT.EXECUTION_ID_ = RES.ID_ and EVT.EVENT_TYPE_ = 'message'
and EVT.EVENT_NAME_ = 'callWorkerConsumer' )
Some times, When i look for the instance of the process in the database i found it waiting in the receive task
SELECT DISTINCT * FROM ACT_RU_EXECUTION RES
WHERE id_ = 'b2362197-3bea-11eb-a150-9e4bf0efd6d0'
However, when i check the subscription event, it's not yet created in the database
select ID_ from ACT_RU_EVENT_SUBSCR EVT
where EVT.EXECUTION_ID_ = 'b2362197-3bea-11eb-a150-9e4bf0efd6d0'
and EVT.EVENT_TYPE_ = 'message'
and EVT.EVENT_NAME_ = 'callWorkerConsumer'
I think that the solution is to save the "receive task" before getting the response for respondToCallWorker, but sadly i can't figure it out.
I tried "asynch before" callWorker and "Message consumer" but it did not work,
I also tried camunda.bpm.database.jdbc-batch-processing=false and got the same results,
I tried also parallel branches but i get OptimisticLocak exception and MismatchingMessageCorrelationException
Maybe i am doing it wrong
Thanks for your help
This is an interesting problem. As you already found out, the error happens, when you try to correlate the result from the "worker" before the main process ended its transaction, thus there is no message subscription registered at the time you correlate.
This problem in process orchestration is described and analyzed in this blog post, which is definitely worth reading.
Taken from that post, here is a design that should solve the issue:
You make message send and receive parallel and put an async before the send task.
By doing so, the async continuation job for the send event and the message subscription are written in the same transaction, so when the async message send executes, you already have the subscription waiting.
Although this should work and solve the issue on BPMN model level, it might be worth to consider options that do not require remodeling the process.
First, instead of calling the worker directly from your delegate, you could (assuming you are on spring boot) publish a "CallWorkerCommand" (simple pojo) and use a TransactionalEventLister on a spring bean to execute the actual call. By doing so, you first will finish the BPMN process by subscribing to the message and afterwards, spring will execute your worker call.
Second: you could use a retry mechanism like resilience4j around your correlate message call, so in the rare cases where the result comes to quickly, you fail and retry a second later.
Another solution I could think of, since you seem to be using an "external worker" pattern here, is to use an external-task-service task directly, so the send/receive synchronization gets solved by the Camunda external worker API.
So many options to choose from. I would possibly prefer the external task, followed by the transactionalEventListener, but that is a matter of personal preference.
I am using a ServiceBusTrigger to execute code when receiving a message. I would like to use the Singleton attribute to limit which messages can be executed in parallel. This attribute allows specifying a scope bound to properties on the incoming message, such that messages with different values can be executed in parallel but ones with the same value must be done serially.
This works when using top level properties on the incoming message object like CorrelationId.
Example
[Singleton("{CorrelationId}", SingletonScope.Function, Mode = SingletonMode.Function)]
public async Task HandleMessage(
[ServiceBusTrigger("my-topic-name", "my-subscription-name"), ServiceBusAccount("my-account-name")]
Message message,
CancellationToken cancellationToken
)
{
await Task.Yield();
}
What I am struggling to figure out is how to achieve the same behavior with user properties on the message. These are stored in the UserProperties dictionary on the Message object. I'm not seeing a way to refer to these with the binding statement in the Singleton attribute, but it seems like this would be a very common use case when combining Singleton with ServiceBusTrigger
The Service Bus Bindings exposes Message Metadata in binding expressions. So, userProperties.<key> should do the trick.
I have a problem, I've created multicasting with gui and my program need sys.stdin but I have text - string in my gui.
sockets_list = [sys.stdin, server]
read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
This code does not work
def message(self, event):
mess = self.write.get()
self.sockets_list = [mess, self.server]
self.read_sockets, write_socket, error_socket = select.select(self.sockets_list,[],[])
print self.sockets_list
self.write.delete(0, Tkinter.END)
if mess != '':
self.mess1.configure(state = NORMAL)
self.all_users.append('Adam')
for socks in self.read_sockets:
if socks == self.server:
message = socks.recv(2048)
self.mess1.insert(Tkinter.END, '%s> %s \n' %(self.nick, message)) #wyswietla wprowadzony tekst
self.mess1.see(Tkinter.END)
else:
message = mess
self.server.send(message)
print self.nick
print message
self.mess1.see(Tkinter.END)
self.mess1.configure(state = DISABLED)
I want to create a messenger on a multicast basis I send a message from one client - I go to the server and send it to the rest of the clients. The problem is that I can not use the message entered in the gui and it works in the terminal
All code
web_pr_less2_client.py - client
dup.py - serv
https://github.com/Antoni-Hp/Web_programing/tree/master/Python_web_programing_less2
The problem here as stated by the author of the question is that "the code doesn't work". While the author is trying to find a solution for a particular error that results in a particular exception throw, fixing it alone won't solve the problem of the code not working. It also appears that the author is only beginning to learn how to code GUI applications.
I have little knowledge with Tkinter, but I'll try to help regardless by explaining what problems I see here.
The message method as presented in the question is being called in response to a "submit message" event. However, this method also tries to read the messages that may arrive from the server at any given time. This means that the user will not see any new messages from the server until they themselves send a message. This "read from server" piece of code should be moved out from this method and handled separately.
Now, as I stated before I'm not familiar with Tkinter so I can't claim that I know what's the best approach here, but normally with GUI apps listening to the background events needs to be done by either awaiting for an arrival of a "ready" event through a callback function or by polling for the events on which we await in the background. How this is achieved depends on the used technology (timers, threads, OS API functions with callbacks).
In your case:
1.1. Extract the read operations to a separate method.
1.2. Use a Tkinter timer to call this method periodically.
1.3. select() on the socket with a short timeout (try 0.01)
1.4. If socket is ready for reading, read it and append it to the chat window.
This is a primitive solution as the 0.01 timeout will stall your application and in a production-grade software should not be done in the main thread, but it's a good starting point.
The exception throw on message submit is caused by trying to use the mess variable you obtain from the text input widget as if it was an I/O handle, while in actuality it's a str. I/O handles are files, file descriptors, sockets, pipes. str is a data type and it cannot be passed to select(). However, you can just send it through the socket without much care, ie.
def message(self, event):
message = self.write.get()
self.write.delete(0, Tkinter.END)
self.server.send(message)
self.mess1.configure(state=NORMAL)
self.mess1.insert(Tkinter.END, '%s> %s \n' %(self.nick, message))
self.mess1.see(Tkinter.END)
self.mess1.configure(state=DISABLED)
Also, aside from the problem at hand, my general recommendations are:
Your code doesn't follow PEP8 styling recommendations. While this doesn't affect your software functionally, you may reconsider following those rules. They are officially recommended by the authors of the Python language and it will be very likely that most of the Python code you find online will follow them. Running a flake8 check over your code shows 351 violations.
I also recommend to focus on a more precise naming of your symbols.
def message should be def on_message_send_requested (I used the on prefix as this method can only be used as a callback due to the presence of the event argument),
self.server should be self.connection_socket,
mess should be message,
self.write should be self.text_input
i used after() function and it works.
#ZalewaPL thank you for help :)
solution:
def read_from_server(self):
read_sockets, write_socket, error_socket =
select.select([self.connection_socket],[],[], 0.1)
for socks in read_sockets:
if socks == self.connection_socket:
message = socks.recv(2048)
message = message.split(";;")
self.mess1.configure(state = NORMAL)
self.mess1.insert(Tkinter.END, '%s> %s \n' %(message[0], message[1]))
self.mess1.see(Tkinter.END)
self.mess1.configure(state = DISABLED)
self.main.after(1, self.read_from_server)
def on_message_send_requested(self, event):
message = self.text_input.get() # pobiera tekst z okienka write
self.text_input.delete(0, Tkinter.END)
if message != '':
self.mess1.configure(state = NORMAL)
send_message = "%s;;%s" %(self.nick, message)
self.connection_socket.send(send_message)
self.mess1.insert(Tkinter.END, '%s> %s \n' %(self.nick, message))
self.mess1.see(Tkinter.END) #pokazuje zawsze najnowszy wpis
self.mess1.configure(state = DISABLED)
I'm currently developing a simple application for querying/retrieving data on a PACS. I use DCMTK for this purpose, and a DCM4CHEE PACS as test server.
My goal is to implement simple C-FIND queries, and a C-MOVE retrieving system (coupled with a custom SCP to actually download the data).
To do so, I've created a CustomSCU class, that inherits the DCMTK DcmSCU class.
I first implemented a C-ECHO message, that worked great.
Then, I tried to implement C-FIND requesting, but I got the error "DIMSE No valid Presentation Context ID" (more on that in the next paragraph) from my application, but no other log from DCM4CHEE. I've then used the command tool findscu (from dcmtk) to see if there was some configuration issue but the tool just worked fine. So in order to implement my C-FIND request, I've read the source of findscu (here) and adapted it in my code (meaning that i'm not using DcmSCU::sendCFindRequest but the class DcmFindSU).
But now, i'm facing the same problem with C-MOVE request. My code is pretty straight-forward :
//transfer syntaxes
OFList<OFString> ts;
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
//sop class
OFString pc = UID_MOVEPatientRootQueryRetrieveInformationModel;
addPresentationContext(pc, ts);
DcmDataset query;
query.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "PATIENT");
query.putAndInsertOFStringArray(DCM_PatientID, <ThePatientId>);
OFCondition condition = sendMOVERequest(findPresentationContextID(pc, ""), getAETitle(), &query, nullptr);
return condition.good();
I've also tried using UID_MOVEStudyRootQueryRetrieveInformationModel instead of UID_MOVEPatientRootQueryRetrieveInformationModel, with the same result : my application shows the error
DIMSE No valid Presentation Context ID
As I understand, a presentation context is concatenation of one or more transfer syntax and one SOP class. I read that the problem could come from the PACS that won't accept my presentation contexts. To be sure, I used the movescu tool (from DCMTK). It worked, and I saw this in the logs from de server DCM4CHEE :
received AAssociatedRQ
pc-1 : as=<numbers>/Patient Root Q/R InfoModel = FIND
ts=<numbers>/Explicit VR Little Endian
ts=<numbers>/Explicit VR Big Endian
ts=<numbers>/Implicit VR Little Endian
That means that the movescu tool does a find before attempting an actual move ?
Therefore, I changed my application context creation with :
OFList<OFString> ts;
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
OFString pc1 = UID_FINDPatientRootQueryRetrieveInformationModel;
OFString pc = UID_MOVEPatientRootQueryRetrieveInformationModel;
addPresentationContext(pc1, ts);
addPresentationContext(pc, ts);
(also tried study root)
But this didn't do the trick.
The problem seems to lie on the client side, as findPresentationContextID(pc, ""); alwasy return 0, no matter what.
I don't feel like it's possible to adapt the code of the movescu tool, as it appears to be very complex and not adequat for simple retrieve operations.
I don't know what to try. I hope someone can help me understand what's going on. That's the last part of my application, as the storage SCP already works.
Regards
It looks like you are not negotiating the association with the PACS.
After adding the presentation contexts and before sending any command, the SCU must connect to the PACS and negotiate the PresentationContexts with DcmSCU::initNetwork and then DcmSCU::negotiateAssociation.
Using wireshark i can see a request-id goes on when i run this program (How to get the value of OID in Python using PySnmp), can i get the request-id number using python program similarly, when i run this program i basically give community:public and version v2c, but in get-response i get request-id, this is what is need to fetch. Please help me out how to do it. Here is the image of snmp response in wireshark.
Well, request-id is something very private to the SNMP mechanics. But you still can get it if you want.
With pysnmp, you can use the built-in hooks to have it calling back your function and passing it the internal data belonging to SNMP engine processing the request.
...
# put this in your script's initialization section
context = {}
def request_observer(snmpEngine, execpoint, variables, context):
pdu = variables['pdu']
request_id = pdu['request-id']
# this is just a way to pass fetched data from the callback out
context['request-id'] = request_id
snmpEngine.observer.registerObserver(
request_observer,
'rfc3412.receiveMessage:request',
cbCtx=context
)
...
Now, once you get SNMP message the normal way, request-id for its PDU should be stored in context['request-id']. You can get practically everything about underlying SNMP data structures that way.