I have created my own MSMQ wrapper class like this:
public class MsgQueue
{
private MessageQueue messageQueue;
public delegate void ReadMessageDelegate(string message);
public event ReadMessageDelegate NewMessageAvailable;
public MsgQueue(string queueName)
{
var queuePath = #".\Private$\" + queueName;
if (!MessageQueue.Exists(queuePath)) MessageQueue.Create(queuePath);
messageQueue = new MessageQueue(queuePath);
messageQueue.Label = queueName;
messageQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string)});
messageQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(MsgReceivedHandler);
messageQueue.BeginReceive();
}
private void MsgReceivedHandler(object sender, ReceiveCompletedEventArgs e)
{
try
{
MessageQueue mq = (MessageQueue)sender;
var message = mq.EndReceive(e.AsyncResult);
NewMessageAvailable(message.Body.ToString());
mq.BeginReceive();
}
catch (MessageQueueException)
{
// Handle sources of MessageQueueException.
}
return;
}
public void SendMessage(string message)
{
messageQueue.Send(message);
}
}
I tested it on two separate WinForms applications.
First app sends a text message when button is clicked:
private void btn_Click(object sender, EventArgs e)
{
var queue = new MsgQueue.MsgQueue("GBMqueue");
queue.SendMessage("some message text");
}
Second app is listening for any incoming messages and then tries to process it:
// declaration
private MsgQueue queue;
// preparation of the queue
private void Form1_Load(object sender, EventArgs e)
{
queue = new MsgQueue.MsgQueue("GBMqueue");
queue.NewMessageAvailable += Queue_NewMessageAvailable;
}
// Handler for the incoming messages
private void Queue_NewMessageAvailable(string message)
{
// Hits here very rarely!!!
}
The problem is that I can send the message from App1 several times, but the Queue_NewMessageAvailable handler catches only one random message, not the first one - just one of those which were sent.
No exception is thrown, it just does not catch the incoming messages.
What am I doing wrong here?
I think the first App should not listen for new messages. It's possible that it takes away the messages for the second App. It should only send messages.
When you split the functionality it should work.
Related
I'm trying to make Azure IOT Hub behave (more or less) like an MQTT broker.
I want to publish a message on devices/{deviceid}/messages/events/ and then receive it on devices/{deviceid}/messages/devicebound/#.
The library I'm using is M2MQTT and so far, I can connect to the IOT hub and publish a message to the events topic. Using DeviceExplorer I can see the message arriving on the hub.
For some reason the message is not relayed to the devicebound topic and the MqttClient_MqttMsgPublishReceived is never triggered. The event does get triggered when using DeviceExplorer and sending a message from there.
So... I think I'm missing something either in code or in the configuration of the IOT Hub.
Does anybody know what I'm doing wrong?
This is my code:
using Microsoft.Azure.Devices.Common.Security;
using Newtonsoft.Json;
using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Windows.Forms;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace DemoM2MqttAzure
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private const string IOTHubURI = "TESTIOTHUB.azure-devices.net";
private const string IOTDeviceID = "IOTDevice";
private string IOTDeviceUsername = string.Format("{0}/{1}/?api-version=2018-06-30", IOTHubURI, IOTDeviceID);
private const string IOTDevicePrimaryKey = "xxx";
private string IOTSubscribeDeviceTopic = string.Format("devices/{0}/messages/devicebound/#", IOTDeviceID);
private string IOTPublishDeviceTopic = string.Format("devices/{0}/messages/events/", IOTDeviceID);
//M2MQTT client.
MqttClient mqttClient;
private void buttonStartMQTT_Click(object sender, EventArgs e)
{
mqttClient = new MqttClient(IOTHubURI, 8883, true, MqttSslProtocols.TLSv1_0, UserCertificateSelectionCallback, null);
mqttClient.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
mqttClient.MqttMsgPublishReceived += MqttClient_MqttMsgPublishReceived;
mqttClient.MqttMsgPublished += MqttClient_MqttMsgPublished;
mqttClient.MqttMsgSubscribed += MqttClient_MqttMsgSubscribed;
string IOTDevicePassword = CreateSharedAccessSignature();
mqttClient.Connect(IOTDeviceID, IOTDeviceUsername, IOTDevicePassword);
if(mqttClient.IsConnected)
{
MessageBox.Show("Connected!");
}
else
{
MessageBox.Show("Connection failed.");
}
}
private void MqttClient_MqttMsgSubscribed(object sender, MqttMsgSubscribedEventArgs e)
{
byte[] qosLevels = e.GrantedQoSLevels;
ushort msgId = e.MessageId;
MessageBox.Show("Event subscribed");
}
private string CreateSharedAccessSignature()
{
string target = string.Format("{0}/devices/{1}", IOTHubURI, IOTDeviceID);
return new SharedAccessSignatureBuilder
{
Key = IOTDevicePrimaryKey,
Target = target,
KeyName = null,
TimeToLive = TimeSpan.FromDays(360)
}.ToSignature();
}
private void buttonSubscribe_Click(object sender, EventArgs e)
{
if(mqttClient.IsConnected)
{
mqttClient.Subscribe(new string[] { IOTSubscribeDeviceTopic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
}
else
{
MessageBox.Show("Not connected.");
}
}
private void buttonPublish_Click(object sender, EventArgs e)
{
if (mqttClient.IsConnected)
{
var telemetryDataPoint = new
{
deviceId = IOTDeviceID,
value = 123.456,
text = "abc"
};
var json = JsonConvert.SerializeObject(telemetryDataPoint);
ushort result = mqttClient.Publish(IOTPublishDeviceTopic, Encoding.UTF8.GetBytes(json), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, true);
}
else
{
MessageBox.Show("Not connected.");
}
}
private void MqttClient_MqttMsgPublished(object sender, MqttMsgPublishedEventArgs e)
{
if (e.IsPublished)
{
MessageBox.Show("Event message published.");
}
else
{
MessageBox.Show("Message was not published...");
}
}
private void MqttClient_MqttMsgPublishReceived(object sender, uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishEventArgs e)
{
MessageBox.Show("Event message publish received.");
}
private bool UserCertificateSelectionCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if(mqttClient.IsConnected)
{
mqttClient.Disconnect();
}
}
}
}
So what you really want to do is this:
Device A --> sends message --> IoT Hub receives it --> sends the message on to Device B --> Device B receives it
You can build this fairly easily, however, not only with IoT Hub.
I would propose using a simple Azure Function in the middle:
Device A sends messages to IoT Hub.
The Azure Function receives all D2C (device-2-cloud) message from the IoT Hub
The Function uses the Service SDK of the IoT Hub to send C2D (cloud-2-device) messages to Device B through the IoT Hub
Device B listens for messages on ../devicebound and will receive the message there.
I think MqttClient.MqttMsgPublishReceived will probably be triggerred when one client receive the message you published. Have MqttClient_MqttMsgSubscribed ever been triggered? Would you like to have a try?
Refer to: MQTT Publish, Subscribe & Unsubscribe - MQTT Essentials: Part 4
I'm trying to fetch emails as soon as they arrive in my inbox using MailSystem.NET library. Everything works fine IMAP client gets connected but my NewMessageReceived event is never fired.
Please Help
Below is the code:
public static Imap4Client _imap = new Imap4Client();
public string SenderEmailAddress = System.Configuration.ConfigurationManager.AppSettings["EmailAddress"];
public string SenderEmailPassword = System.Configuration.ConfigurationManager.AppSettings["EmailPassword"];
public static Mailbox inbox = new Mailbox();
protected void Application_Start()
{
var worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(StartIdleProcess);
if (worker.IsBusy)
worker.CancelAsync();
worker.RunWorkerAsync();
}
private void StartIdleProcess(object sender, DoWorkEventArgs e)
{
try
{
if (_imap != null && _imap.IsConnected)
{
_imap.StopIdle();
_imap.Disconnect();
}
_imap = new Imap4Client();
_imap.NewMessageReceived += new NewMessageReceivedEventHandler(NewMessageReceived);
_imap.ConnectSsl("imap.gmail.com", 993);
_imap.Login(SenderEmailAddress, SenderEmailPassword);
inbox = _imap.SelectMailbox("inbox");
int[] ids = inbox.Search("UNSEEN");
inbox.Subscribe();
_imap.StartIdle();
}
catch (Exception ex)
{
}
}
public static void NewMessageReceived(object source, NewMessageReceivedEventArgs e)
{
int offset = e.MessageCount - 2;
Message message = inbox.Fetch.MessageObject(offset);
Debug.WriteLine("message subject: " + message.Subject);
// Do something with the source...
_imap.StopIdle();
}
I can't tell you the exact reason but it seems that interacting with the imapclient from the NewMessageReceived event just doesn't work.
In NewMessageReceived call _imap.StopIdle() then continue in your main execution flow and restart idle. Then use a boolean to drop out of the loop entirely.
private bool _stop = false;
private void StartIdle(object sender, DoWorkEventArgs e)
{
//Setup client
_imap = new Imap4Client();
_imap.NewMessageReceived += new NewMessageReceivedEventHandler(NewMessageReceived);
StartRepeatExecution();
}
public void StartRepeatExecution()
{
_imap.StartIdle();
if(_stop) return;
//Handle your new messages here! dummy code
var mailBox = _imap.SelectMailBox("inbox");
var messages = mailBox.SearchParse("").Last();
StartRepeatExecution();
}
public static void NewMessageReceived(object source, NewMessageReceivedEventArgs e)
{
//StopIdle will return to where _imap.StartIdle() was called.
_imap.StopIdle();
}
public void StopRepeatExecution()
{
_stop = true;
}
I tried to send Apple push notification with PushSharp library like that:
public class Push
{
private readonly PushBroker _push;
private static Push _instance;
public static Push Instance
{
get { return _instance ?? (_instance = new Push()); }
}
public Push()
{
_push = new PushBroker();
_push.OnNotificationSent += new NotificationSentDelegate(_push_OnNotificationSent);
_push.OnNotificationFailed += new NotificationFailedDelegate(_push_OnNotificationFailed);
_push.OnServiceException += new ServiceExceptionDelegate(_push_OnServiceException);
_push.OnChannelCreated += new ChannelCreatedDelegate(_push_OnChannelCreated);
_push.OnChannelDestroyed += new ChannelDestroyedDelegate(_push_OnChannelDestroyed);
_push.OnChannelException += new ChannelExceptionDelegate(_push_OnChannelException);
_push.OnNotificationRequeue += new NotificationRequeueDelegate(_push_OnNotificationRequeue);
_push.RegisterAppleService(new ApplePushChannelSettings(false, File.ReadAllBytes(#"C:\PathToCertificate\Name.p12"), "***"), "myAppId", new PushServiceSettings()
{
Channels = 1,
AutoScaleChannels = false
});
}
void _push_OnNotificationRequeue(object sender, NotificationRequeueEventArgs e)
{
Debug.Print("requeue");
}
void _push_OnChannelException(object sender, IPushChannel pushChannel, Exception error)
{
Debug.Print("channel exception");
}
void _push_OnChannelDestroyed(object sender)
{
Debug.Print("channel destroyed");
}
void _push_OnChannelCreated(object sender, IPushChannel pushChannel)
{
Debug.Print("channel created");
}
void _push_OnServiceException(object sender, System.Exception error)
{
Debug.Print("service exception");
}
void _push_OnNotificationFailed(object sender, INotification notification, System.Exception error)
{
Debug.Print("failed");
}
void _push_OnNotificationSent(object sender, INotification notification)
{
Debug.Print("sent");
}
public void Send(Notification notification)
{
_push.QueueNotification(notification);
_push.StopAllServices("biz.sintek.Rotapost", true);
}
public void SendAppleNotification(string deviceToken, string text)
{
Send(new AppleNotification()
.ForDeviceToken(deviceToken)
.WithAlert(text)
.WithSound("default"));
}
}
I'm calling SendAppleNotification method. It returns in no time but no exceptions throwed, no events called, no notifications sent and no notifications received.
I am using developer push certificate converted to .p12 format.
Double checked provisioning profile.
QueueNotification method of PushBroker class is generic. It using generic type parameter to identify which service to use for notification send.
Solution is to pass new AppleNotification()... directly to the QueueNotification
I am trying to send information from my windows phone to the computer. I read some where that the usb cable is treated like a Ethernet cable. I created a server and a client(Phone is client) to try to send information. The program sends a message every time it presses enter.
Client Side
public sealed partial class MainPage : Page
{
private bool Connected;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// TODO: Prepare page for display here.
// TODO: If your application contains multiple pages, ensure that you are
// handling the hardware Back button by registering for the
// Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
}
private DatagramSocket dataGramSocket = new DatagramSocket();
private DataWriter socketWriter;
private bool messageSent;
private static string port = "138";
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
dataGramSocket.MessageReceived += dataGramSocket_MessageReceived;
StartListener();
}
void dataGramSocket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
}
private async void StartListener()
{
string IpHostname = "127.0.0.1";
var IpAdresses = NetworkInformation.GetHostNames();
for (int i = 0; i < IpAdresses.Count; i++)
{
if (IpAdresses[i].IPInformation != null)
{
if (IpAdresses[i].IPInformation.NetworkAdapter.IanaInterfaceType == 6 && IpAdresses[i].DisplayName != null)
{
IpHostname = IpAdresses[i].DisplayName;
break;
}
else if (IpAdresses[i].IPInformation.NetworkAdapter.IanaInterfaceType == 71 && IpAdresses[i].DisplayName != null)
{
IpHostname = IpAdresses[i].DisplayName;
break;
}
}
}
HostName host = new HostName(IpHostname);
//EndpointPair endpoint = new EndpointPair(localHostName,)
await dataGramSocket.BindServiceNameAsync(port);
await dataGramSocket.ConnectAsync(host, port);
socketWriter = new DataWriter(dataGramSocket.OutputStream);
Connected = true;
}
private async void SendPacket()
{
await socketWriter.StoreAsync();
messageSent = true;
}
private void TextBox1_KeyDown(object sender, KeyRoutedEventArgs e)
{
if(e.Key == Windows.System.VirtualKey.Enter)
{
SendMessage(textBox1.Text);
}
}
private void SendMessage(string message)
{
socketWriter.WriteString(message);
SendPacket();
textBox1.Text = "";
}
}
}
Server Side
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static int port = 138;
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Task.Factory.StartNew(() =>
{
var dataStream = new MemoryStream(1024);
var udpClient = new UdpClient(port);
while (true)
{
if (udpClient.Available > 0)
{
udpClient.BeginReceive(ar =>
{
var clientEndPoint = new IPEndPoint(IPAddress.Any, port);
var bytesReceived = udpClient.EndReceive(ar, ref clientEndPoint);
dataStream.Write(bytesReceived, 0, bytesReceived.Length);
if (bytesReceived.Length > 0)
{
UpdateUI(Encoding.UTF8.GetString(bytesReceived));
UpdateUI(Encoding.ASCII.GetString(bytesReceived));
}
}, null);
}
Thread.Sleep(1);
}
}, _cancellationTokenSource.Token);
}
private void UpdateUI(string message)
{
this.Invoke(new MethodInvoker(delegate
{
this.textBox1.Text += message + Environment.NewLine;
}));
}
private void button1_Click_1(object sender, EventArgs e)
{
byte[] message = Encoding.UTF8.GetBytes(textBox2.Text);
using (var udpClient = new UdpClient())
{
udpClient.Send(message, message.Length, new IPEndPoint(IPAddress.Loopback, port));
}
textBox2.Clear();
}
}
}
The information isn't connecting somewhere in the middle. On both sides nothing breaks. When I test the form by sending information to the loopback it works. I don't know why the information is not reaching the other side. Can you please tell me if I am doing this write and it is suppose to be done this way or can you tell me if this is not possible so I can stop working on it.
I saw a similar question and I answered there, Communicate to PC over USB.
It requires editing the registry, the server code running on the device and I am not sure if the code will run outside of a development environment (I only need this to speed up my workflow and debugging - so its not an issue).
Not possible.
TCP/IP over USB worked OK in Windows Phone 7. In Windows Phone 8 however they removed the functionality.
Seek for other alternatives.
You could use TCP/IP over WiFi, or use BT, or write data to "Documents" and read with MTP COM API, or write data to isolated storage and read it using isetool.exe (this one only works for dev.unlocked devices).
I'm currently working on a project and one of the featured devices is a Windows Tablet. To "connect" it to other devices (like some Raspberry Pi) in the project environment UDP is used to send messages. The Windows Tablet is intended to be some controlling device with soem touch functionality. Therefore I'm writing an App (and the intention of the App is not to put it into the Windows Store). The UDP part in this work is quite painful because I had to do much research since I started with no experience in App programming. More painful than the programming is, that I practically finished the work only to start over again because the App didn't receive UDP anymore.
Here's my code (I removed elements not relevant to the actual problem). I apologize for the bad coding....
App.xaml.cs:
sealed partial class App : Application
{
NetworkInterface ni = new NetworkInterface();
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
ni.MessageReceived += OnMessageReceived;
ni.Connect(new HostName("127.0.0.1"), "5556");
}
private void OnMessageReceived(object sender, MessageReceivedEventArgs e)
{
Debug.WriteLine("Processing");
Debug.WriteLine(e.Message.Data);
}
public static new App Current
{
get { return Application.Current as App; }
}
private DatagramSocket _socket;
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Update_Timer();
}
DispatcherTimer timer = new DispatcherTimer();
private void Update_Timer()
{
timer.Start();
timer.Interval = new TimeSpan(0,0,0,0,500);
timer.Tick += alive;
}
private void alive(object sender, object e)
{
if (start == 0) {
Debug.WriteLine("App-Startup");
ni.SendMessage("Startup...");
start++;
}
else
{
Debug.WriteLine("App-Alive");
ni.SendMessage("alive");
start++;
}
}
}
This part of code is to send and receive Messages in the backgrond in the whole App.
And a NetworkInterface class:
class NetworkInterface
{
private DatagramSocket _socket;
public bool IsConnected { get; set; }
public NetworkInterface()
{
IsConnected = false;
_socket = new DatagramSocket();
_socket.MessageReceived += OnSocketMessageReceived;
}
public async void Connect(HostName remoteHostName, string remoteServiceNameOrPort)
{
if (IsConnected != true)
{
await _socket.BindServiceNameAsync("5321");
await _socket.ConnectAsync(remoteHostName, remoteServiceNameOrPort);
}
IsConnected = true;
}
public void alive(object sender, object e)
{
Debug.WriteLine("alive");
}
public event EventHandler<MessageReceivedEventArgs> MessageReceived;
private void OnSocketMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
var reader = args.GetDataReader();
var count = reader.UnconsumedBufferLength;
var data = reader.ReadString(count);
Debug.WriteLine(args);
if (MessageReceived != null)
{
var ea = new MessageReceivedEventArgs();
ea.Message = new Message() { Data = data };
ea.RemoteHostName = args.RemoteAddress;
ea.RemotePort = args.RemotePort;
MessageReceived(this, ea);
}
}
DataWriter _writer = null;
public async void SendMessage(string message)
{
if (_writer == null)
{
var stream = _socket.OutputStream;
_writer = new DataWriter(stream);
}
_writer.WriteString(message);
await _writer.StoreAsync();
}
}
The main problems are:
If I dont send something before receiving, I won't be able top get an message.
If I send before I have random Faults at this line:
var reader = args.GetDataReader();
If nothing fails, I'm not able to receive messages from a local Python script (which works) but I can send messages from a local program which the App receives.
Does anyone know how I can fix these problems?
Thanks in advance!