I am trying my very first MQTT example.
And I am using Processing.
I have downloaded and installed the library using the Proccessing library tool.
In the Processing File> Examples>Contributed Libraries> MQTT is the example PublishSubscribe
I open it and run it. I get the squar box and click to make it take focus. When i type on the keyboard the visual display at shifer.io shows I am publishing messages.
See the visual display here: https://shiftr.io/try#processing
However the messageReceived ?callback? never seams to execute as I get no subscribed messages in the console.
I am not sure what to try next.
I am running Processing 3.3.7
Code Example:
import mqtt.*;
MQTTClient client;
void setup() {
client = new MQTTClient(this);
client.connect("mqtt://try:try#broker.shiftr.io", "processing");
client.subscribe("/example");
// client.unsubscribe("/example");
size(200, 200);
frameRate(30);
}
void draw() {}
void keyPressed() {
client.publish("/hello", "world");
}
void messageReceived(String topic, byte[] payload) {
println("new message: " + topic + " - " + new String(payload));
}
Related
Greetings of the day.
Please help on the below requirement:
Requirement:
We want to delete message from MQ only after it is processed successfully.
Use event based message detection technique and avoid loop
So, to achieve above:
I have created message listener and consumer class below:
{
sessionIn = connectionIn.CreateSession(false, AcknowledgeMode.ClientAcknowledge);
// Create message listener and assign it to consumer
messageListener = new MessageListener(OnMessageCallback);
consumerAsync.MessageListener = messageListener;
Console.WriteLine("Message Listener set. Starting the connection now.");
// Start the connection to receive messages.
connectionWMQ.Start();
}
Reading the message from the call back event and push the message into other system:
OnMessageCallback(Message) {
if (xmsMessage is IBytesMessage)
{
IBytesMessage bytesMessage = (IBytesMessage)xmsMessage;
byte[] arrayMessage = new byte[bytesMessage.BodyLength];
bytesMessage.ReadBytes(arrayMessage);
string message = System.Text.Encoding.Default.GetString(arrayMessage);
}
}
Once the message processed, external system will fire the below over ride method:
Response method override:
protected override Task OnResponse(ReponseMessage message)
{
//Read the message and get the message id and correlation id.
//Delete the message from the queue.
//I am trying to do like this, but Its not working:
messageConsumerDelete = sessionDelete.CreateConsumer(destinationDelete, query);
if (messageConsumerDelete != null)
{
IMessage m = messageConsumerDelete.Receive(1000);
LogWrite("Receive Message=" + m);
m.Acknowledge();
}
}
Please suggest a best solution for this requirement.
I am trying to find a solution for this since weeks, but no breakthrough.
Thanks,
Balaji
I'm facing the error message 'There is no current subscription with tag 'T_1'. Due to this error, my connections are terminated which decreases the performance of my system.
First of, the environment I'm running:
Client app (Created in c#)
Server app (Created with spring boot version 2.6.0)
RabbitMQ (3.9.11) as message broker. Using STOMP plugin.
These 3 services works great in general. I'm not having any issues with these besides the error message described above (There is no current subscription with tag 'T_1'). Please also note that the tag can be any subscription ID, not neccesairy T_1, but also e.g T_100
When does the error occur:
I've noticed that the error usually occurs during a particular state of my program. In this state, the C# client app should subscribe to a topic named 'xxx.pong'. Empty messages are frequently sent to this topic by other client applications. Once retrieved a pong message, the C# client app should unsubscribe to this topic.
How I replicated the issue:
I created a test case similar to the description above. I've added the code as an attachment. The error occurs around 1 out of 10 test runs and it's the consumer (which subscribes and unsubscribes) that retrieves the error message. The publisher (which frequently sends pong messages) does not retrieve errors.
Logs when the error occurs:
Spring boot log:
2022-01-06 14:04:12.165 ERROR 25116 --- [ent-scheduler-7] o.s.m.s.s.StompBrokerRelayMessageHandler : Received ERROR {message=[Subscription not found], content-type=[text/plain], version=[1.0,1.1,1.2], content-length=[48]} session=0009197b-1281-0fdb-08fe-3f5de331fdb9, user=XXX) text/plain payload=There is no current subscription with tag 'T_1'.
RabbitMQ log (Note that the RabbitMQ serves timezone is 1 hour behind my local PC zone):
2022-01-06 13:04:06.450156+00:00 [info] <0.9710.0> Supervisor {<0.9710.0>,rabbit_connection_helper_sup}: child heartbeat_sender started (<0.9728.0>): {rabbit_heartbeat,start_heartbeat_sender,[#Port<0.1398>,10,#Fun<rabbit_stomp_reader.1.31184097>,{heartbeat_sender,unknown}]}
2022-01-06 13:04:06.450237+00:00 [info] <0.9710.0> Supervisor {<0.9710.0>,rabbit_connection_helper_sup}: child heartbeat_receiver started (<0.9729.0>): {rabbit_heartbeat,start_heartbeat_receiver,[#Port<0.1398>,55,#Fun<rabbit_stomp_reader.2.31184097>,{heartbeat_receiver,unknown}]}
2022-01-06 13:04:11.359597+00:00 [info] <0.9733.0> Supervisor {<0.9733.0>,rabbit_amqqueue_sup}: child rabbit_amqqueue started (<0.9734.0>): {rabbit_prequeue,start_link,[{amqqueue,{resource,<<"/">>,queue,<<"stomp-subscription-gItDy9sxnW3_TUCGLOs8PQ">>},false,true,none,[],none,[],[],[],undefined,undefined,[],[],live,0,[],<<"/">>,#{user => <<"guest">>},rabbit_classic_queue,#{}},declare,<0.9732.0>]}
2022-01-06 13:04:11.403234+00:00 [dbug] <0.9734.0> Deleting auto-delete queue 'stomp-subscription-gItDy9sxnW3_TUCGLOs8PQ' in vhost '/' because its last consumer with tag 'T_1' was cancelled
2022-01-06 13:04:11.412333+00:00 [info] <0.9687.0> closing STOMP connection <0.9687.0> (172.17.0.1:57136 -> 172.17.0.2:61613)
2022-01-06 13:04:11.412428+00:00 [dbug] <0.9741.0> Closing all channels from connection '172.17.0.1:57136 -> 172.17.0.2:61613' because it has been closed
This is the test which sometimes invokes the error:
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MyProject.Rabbitmq
{
[TestClass]
public class RabbitMqTests
{
private int _pongCounter;
private int _pingCounter;
private bool shouldStop = false;
[TestMethod]
public void TestTags()
{
var internalWs = new InternalWebsocket("Consumer");
internalWs.Open();
Thread.Sleep(10000);
List<StompSubscription> subscriptions = new List<StompSubscription>();
var task = new Task(() => SpamPong(), TaskCreationOptions.LongRunning);
task.Start();
Thread.Sleep(10000);
var sub = internalWs.Subscribe(
"xxx.pong",
OnPongMessage, true);
while (_pongCounter == 0)
{
Thread.Sleep(1);
}
internalWs.Unsubscribe(sub);
Thread.Sleep(10000);
}
private void SpamPong()
{
var internalWs = new InternalWebsocket("producer");
internalWs.Open();
Thread.Sleep(10000);
while (!shouldStop)
{
try
{
internalWs.Send(new object(), "xxx.pong");
}
catch (Exception e)
{
Logger.Log.Info("Has failed to send message");
}
Thread.Sleep(30);
}
}
public virtual void OnPongMessage(object sender, InternalMessageEventArgs args)
{
Interlocked.Increment(ref _pongCounter);
}
public virtual void OnPingMessage(object sender, InternalMessageEventArgs args)
{
Interlocked.Increment(ref _pingCounter);
}
}
We have a chat application which is using Smack, XMPP, ejabberd. I'm wondering if it's possible to achieve something like below:
A chat is open between 2 users.
User1 is typing some message.
User2 is able to see the message typed by User1 as he types it.
I have done a bit of research but couldn't find anything related.
Please let me know how to achieve this use case.
Thanks in advance!
That is not possible. You can send the text as user types but each piece will go as independent message. If you want that one you might want to have your own way to do so. XMPP have no way to do so!
With Smack it is easy, whenever the user changes the text you send a typing stanza to the other person using the ChatStateExtension:
private void sendTypingStatus(final String toJid) {
//you must have a valid xmpp connection of course
if (null == mConnection)
return;
try {
Message message = new Message(JidCreate.from(toJid));
message.addExtension(new ChatStateExtension(ChatState.composing));
message.setType(Message.Type.chat);
mConnection.sendStanza(message);
} catch (InterruptedException | SmackException.NotConnectedException | XmppStringprepException ex) {
Log.w(TAG, "sendTypingStatus error", ex);
}
}
The other person should be prepared to receive the stanza and use it correctly. The best option is to use ChatStatesStanzaListener for that:
public class ChatStatesStanzaListener implements StanzaListener {
private static final String TAG = ChatStatesStanzaListener.class.getSimpleName();
#Override
public void processStanza(Stanza packet) {
Message message = (Message) packet;
if (message.hasExtension(ChatStateExtension.NAMESPACE)) {
ChatStateExtension chatStateExtension = (ChatStateExtension) message.getExtension(ChatStateExtension.NAMESPACE);
ChatState chatState = chatStateExtension.getChatState();
String fromJid = message.getFrom().asBareJid().toString();
if (message.getType().equals(Message.Type.chat)) {
Log.v(TAG, "got chat state " + fromJid + " " + message.getType() + " " + chatState);
//you got youe information here, call a callback or broadcast an event, whatever
} else if (message.getType().equals(Message.Type.groupchat)) {
//out of your question
}
}
}
}
Don't forget to add the stanza listener to your xmpp connection once it's established:
1. Set the stanza filter:
// set up a stanzalistener and filter chatstates messages only
StanzaFilter chatStatesStanzaFilter = stanza -> {
// filter for chatstates message only
return stanza.hasExtension(ChatStateExtension.NAMESPACE);
};
Use it once you initialize the xmpp connection:
mConnection.addAsyncStanzaListener(new ChatStatesStanzaListener(), chatStatesStanzaFilter);
I hope it helps :)
I created an Edge browser extension which uses Native Messaging to a native app running via a Desktop Bridge technology. I used the SecureInput as a sample, which contains the Edge extension, UWP host and a Win32 Desktop Bridge app.
I need the Win32 Desktop Bridge app to connect to a web service using HTTP and WebSocket, so I added an internetClientServer and a privateNetworkClientServer capabilities to the package manifest, beside the already existed runFullTrust one.
The Win32 Desktop Bridge app activates just fine, and it is able to connect to the web server using HTTP. But as soon as it tries to open a WebSocket connection, the BackgroundTaskInstance on the UWP host receives a cancellation request with a BackgroundTaskCancellationReason.SystemPolicy as a reason, and the Desktop Bridge application closes. Unfortunately, the documentation for the BackgroundTaskCancellationReason.SystemPolicy does not explain much about true reasons of the cancellation request.
I tried to use two WebSocket classes: the System.Net.WebSockets.ClientWebSocket and the Windows.Networking.Sockets.MessageWebSocket, with the same result. No fancy code, just regular
var socket = new MessageWebSocket();
...
await socket.ConnectAsync(new Uri("wss://127.0.0.1:9001/myservice"));
The same WebSocket service endpoint is available from other WS clients, so I guess there is no server/firewall/antivirus issue here.
I also played with the CheckNetIsolation tool, adding loopback exemption for the Edge browser and for the package, with no effect. The HTTP works fine without the loopback exemption.
What may be a true reason of the task cancellation, and what can be a possible way to prevent it?
Ok, I resolved the issue. Thanks to this comment by Tom Shane I stumbled upon, I realized that the BackgroundTaskCancellationReason.SystemPolicy tells that the background task is closed by the system to release some system resources, and that in my case it happened because I didn't obtain a deferral in my async event handler. When the event handler yielded without a deferral, the system decided it can shut the task down. Below is a digested version of the code:
static class Program
{
static AppServiceConnection connection = null;
[STAThread]
static void Main(string[] args)
{
Thread appServiceThread = new Thread(new ThreadStart(ThreadProc));
appServiceThread.Start();
Application.Run();
}
static async void ThreadProc()
{
try {
connection = new AppServiceConnection();
connection.AppServiceName = "...";
connection.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
connection.RequestReceived += OnRequestReceived;
connection.ServiceClosed += OnServiceClosed;
var status = await connection.OpenAsync();
....
}
catch (Exception e) { ... }
}
private static async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
var defer = args.GetDeferral(); // <== that was missing, rookie mistake!
try {
var msg = ParseMessage(args.Request.Message);
if (msg.type.Equals("ws")) {
// this method was truly async
// and every time it yielded the issue was revealed
await HandleWsMessage(request, msg);
}
else if (msg.type.Equals("http")) {
// but this method was actually synchronous despite being marked as "async"
// and it never yielded, masking the issue for HTTP client
await HandleHttpMessage(request, msg);
}
}
catch (Exception e) { ... }
finally {
defer.Complete();
}
}
}
I am trying to develop a web-socket server app for my UWP Windows 10 App.
This is my code:
class Server
{
public async void Start()
{
MessageWebSocket webSock = new MessageWebSocket();
//In this case we will be sending/receiving a string so we need to set the MessageType to Utf8.
webSock.Control.MessageType = SocketMessageType.Utf8;
//Add the MessageReceived event handler.
webSock.MessageReceived += WebSock_MessageReceived;
//Add the Closed event handler.
webSock.Closed += WebSock_Closed;
Uri serverUri = new Uri("ws://127.0.0.1/motion");
try
{
//Connect to the server.
await webSock.ConnectAsync(serverUri);
//Send a message to the server.
await WebSock_SendMessage(webSock, "Hello, world!");
}
catch (Exception ex)
{
//Add code here to handle any exceptions
}
}
//The MessageReceived event handler.
private void WebSock_MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
{
DataReader messageReader = args.GetDataReader();
messageReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
string messageString = messageReader.ReadString(messageReader.UnconsumedBufferLength);
//Add code here to do something with the string that is received.
}
//The Closed event handler
private void WebSock_Closed(IWebSocket sender, WebSocketClosedEventArgs args)
{
//Add code here to do something when the connection is closed locally or by the server
}
//Send a message to the server.
private async Task WebSock_SendMessage(MessageWebSocket webSock, string message)
{
DataWriter messageWriter = new DataWriter(webSock.OutputStream);
messageWriter.WriteString(message);
await messageWriter.StoreAsync();
}
}
It errors here:
await webSock.ConnectAsync(serverUri);
with this error:
Not found (404). (Exception from HRESULT: 0x80190194)
I don't have any personal experience with it, but you might want to give IotWeb HTTP Server a try. It seems to be a portable embedded HTTP and web socket server that also supports UWP and can be run inside Windows Store and Windows 10 IoT Core applications.
Judging from its repository, it's rather new and not exactly mature, nor does it have a lot of documentations or samples available. There's a NuGet package available, though.
Unfortunately I didn't manage to find any other alternative yet.
The code
await webSock.ConnectAsync(serverUri);
Is try to connect to existing server at ws://127.0.0.1/motion, Not to deploy a server on this address.
You can look for ways to build a c# WebSocket server at the follwing links:
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server
http://www.codeproject.com/Articles/57060/Web-Socket-Server