I've been trying to make a direct method call using the AMQP protocol. But can't make it work. I believe calling direct method is possible over AMQP if I'm not wrong. It works with MQTT though. Any clues would be much appreciated.
Here's the code:
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Shared;
using Newtonsoft.Json;
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace VirtualIoTDevice
{
internal class Program
{
private const string DeviceConnectionString = "device-connection-string";
private const string DEVICE_ID = "device01";
private static DeviceClient _device;
private static async Task Main(string[] args)
{
Console.WriteLine("Initializing virtual IoT device..");
using (_device = DeviceClient.CreateFromConnectionString(DeviceConnectionString, DEVICE_ID))
{
await _device.OpenAsync();
await _device.SetMethodHandlerAsync("showMessage", ShowMessage, null);
Console.ReadKey();
}
}
private static Task<MethodResponse> ShowMessage(MethodRequest methodRequest, object userContext)
{
Console.WriteLine("***Direct message received***");
Console.WriteLine(methodRequest.DataAsJson);
var responsePayload = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(new { response = "Message shown!" }));
return Task.FromResult(new MethodResponse(responsePayload, 200));
}
}
}
And here's the command to invoke the direct method:
az iot hub invoke-device-method -n "iothub-name" -d "device01" --method-name "showMessage"
Ok, I know what your issue is: In the latest version of the SDK there was some change in regards to blocking threads. I don't know if this was an intended change or a regression.
However, in your case the Console.ReadKey() is somehow blocking AMQP from connecting in the first place. MQTT is not affected by this - which could indicate it might be a regression.
So, if you change Console.ReadKey() to for example await Task.Delay(-1) it works again in my test.
Related
I have a project creating a websocket client side (Subscriber) to a MQTT publisher. I am quite new to C# and MQTT protocol. I follow some youtube video to make finish my very first lines connecting to this MQTT publisher to get all the train going in and out Helsinki station.
broker: "rata.digitraffic.fi"
Port: 80
Topic: trains-by-station/HKI (HKI abbr for Helsinki)
I use M2Mqtt library in dotnet to build the subscriber, somehow the client_MqttMsgPublishReceived function is never triggered. the client.IsConnected always returned false value!
You can find info of this mqtt protocol in the url below.
https://www.digitraffic.fi/rautatieliikenne/#websocket-mqtt
It gives me example in JavaScripts and it seems to run fine with the example of each MQTT. But when I tried to do it with my PC, it doesn't give me any thing, but
Hello World!!!
False
and the cmd window on hold.
SOOOO FRUSTRATING right now. it would be much appreciate if anyone can help me out.
BTW, I am using win10, I tried with dotnet 4/5/6 and m2mqtt 4.3.0.
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using System;
namespace m2qttSubscriber
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!!!!");
MqttClient client = new MqttClient("rata.digitraffic.fi",
80,
false,
MqttSslProtocols.None,
null,
null);
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
string clientID = "myclientid_" + RandomDigits(4);
client.Connect(clientID);
Console.WriteLine(client.IsConnected);
client.Subscribe(new string[] { "trains-by-station/HKI" },
new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE}) ;
}
static void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
Console.WriteLine("SOme thing is received");
string payload = Encoding.Default.GetString(e.Message);
Console.WriteLine("Recevied {0} from", payload);
}
static public string RandomDigits(int length)
{
var random = new Random();
string s = string.Empty;
for (int i = 0; i < length; i++)
s = String.Concat(s, random.Next(10).ToString());
return s;
}
}
}
As per the comments the library used (uPLibrary.Networking.M2Mqtt) does not support MQTT over Websockets (which is what rata.digitraffic.fi:80 offers).
If you are able to use standard MQTT (over TCP/IP) then rata-mqtt.digitraffic.fi:1883 works (OP succeeded with MqttClient client = new MqttClient("rata-mqtt.digitraffic.fi", 1883, false, MqttSslProtocols.None, null, null);) and this is generally preferable to using WebSockets (there are some situations where you have to use WebSockets; e.g. code running in a browser or to bypass some filters/proxies).
Alternatively there are other libraries that do offer support for MQTT over Websockets.
I'm trying to make a simple console app client (starter.exe) on c# .NET Framework 4.6 to make a WireGuard protocol based connection using Wireguard source code.
What is done:
Downloaded wireguard source code from here: git://git.zx2c4.com/wireguard-windows
Successfuly built Tunnel.dll in ..\embeddable-dll-service\amd64\tunnel.dll via build.bat
Created a project in Visual Studio 2015.using the c# code from ..\embeddable-dll-service\csharp
Starting from here some strange thing are happenning:
if launching starter.exe \service <path to *.conf> I receive the
error
Service run error: The service process could not connect to the
service controller.
if launching starter.exe without parameters everything works fine until I remove the if{} block:
Unhandled Exception: System.ComponentModel.Win32Exception: The service
did not respond to the start or control request in a timely fashion
at WireGuardTunnel.Service.Add(String configFile) in
D:\Depository\BitBucket\WireGuard_Tunnel_Repository\WireGuardTunnel_proj\Launcher\Service.cs:line
69 at WireGuardTunnel.Program.Main(String[] args) in
D:\Depository\BitBucket\WireGuard_Tunnel_Repository\WireGuardTunnel_proj\Launcher\Program.cs:line
83
That means even if the code in if{} block is not executed it influencese somehow the application behaviour.
Next, as I want to make my app work with parameters I solved the
issue by removing return afer Service.Run and passing args[1] to Service.Add(args[1]). It works OK, but I have an extra log line (the first one due to Service.Run perpetual error described above) in the log:
Service run error: The service process could not connect to the
service controller. 235660: [TUN] [chicago4] Watching network
interfaces 245661: [TUN] [chicago4] Resolving DNS names
245661: [TUN] [chicago4] Creating Wintun interface 225660: [TUN]
[chicago4] Starting WireGuard/0.3.1 (Windows 6.1.7601; amd64)
So finally the questions:
Why Service.Run(confFile) does not work
Why Service.Run(confFile) influences the Service.Add(confFile)
Why if{} block is executed when I launch starte.exe with no parameters
The original Program.cs without modification:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices;
namespace Tunnel
{
class Program
{
[DllImport("kernel32.dll")]
private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);
private delegate bool SetConsoleCtrlEventHandler(UInt32 signal);
public static void Main(string[] args)
{
string baseDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
string configFile = Path.Combine(baseDirectory, "demobox.conf");
string logFile = Path.Combine(baseDirectory, "log.bin");
if (args.Length == 2 && args[0] == "/service")
{
configFile = args[1];
Service.Run(configFile);
return;
}
try { File.Delete(logFile); } catch { }
Ringlogger log = new Ringlogger(logFile, "GUI");
var logPrintingThread = new Thread(() =>
{
var cursor = Ringlogger.CursorAll;
while (Thread.CurrentThread.IsAlive)
{
var lines = log.FollowFromCursor(ref cursor);
foreach (var line in lines)
Console.WriteLine(line);
Thread.Sleep(300);
}
});
logPrintingThread.Start();
SetConsoleCtrlHandler(delegate
{
Service.Remove(configFile);
Environment.Exit(0);
return true;
}, true);
try
{
Service.Add(configFile);
logPrintingThread.Join();
}
finally
{
Service.Remove(configFile);
}
}
}
}
Bit late to the party but I was having the exact same issue as above and discovered that in order to get everything working correctly you have to have Tunnel.Service.Run("path to config") defined on application initialization either in your main loop or your constructor then you can run Tunnel.Service.Add("path to config", true) which will create the service and start the VPN connection. It's also good practice to destroy the service on close using Tunnel.Service.Remove("path to config", true) as the service will continue to run and you will still be connected to your VPN until it is stopped manually.
Hi Team I have the following code in C#, i am writting a backend-application using C# to read DeviceToCloudMEssage in Azure portal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Common;
using Microsoft.Azure.Devices.Shared;
using Microsoft.Azure.Devices;
namespace BackEndApplication
{
class Program
{
private static ServiceClient _serviceClient;
private readonly static string s_connectionString = "HostName=UniversityIOTHub.azure-devices.net;DeviceId=UniversityDeviceIOT;SharedAccessKey=******=";
private static async Task InvokeMethod()
{
var methodInvocation = new CloudToDeviceMethod("SetTelemetryInterval") { ResponseTimeout = TimeSpan.FromSeconds(30) };
methodInvocation.SetPayloadJson("10");
var response = await _serviceClient.InvokeDeviceMethodAsync("UniversityDeviceIOT", methodInvocation);
Console.WriteLine("Response status:{0}, payload", response.Status);
Console.WriteLine(response.GetPayloadAsJson());
}
static void Main(string[] args)
{
Console.WriteLine("IOT Hub Test-- BackEndApplication.\n");
_serviceClient = ServiceClient.CreateFromConnectionString(s_connectionString);
InvokeMethod().GetAwaiter().GetResult();
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
}
}
I am getting an authorizedException from the assemblies, one being Microsoft.Azure.Device.Common. The exception hits on InvokeMethod().GetAwaiter().GetResult(). Im also using DeviceExplore to test this exception, payload method i am also getting the same result. Please help me thanks.
What you are doing in your program is not reading DeviceToCloudMessages but invoking a direkt method.
For that you are using the wrong connectionString. The ServiceClient does not connect to your device but to IoT-Hub. So instead of using the IoT-Hub-Device connection string you have to use the IoT-Hub connection string which looks like this:
HostName=<yourIotHub>.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=<yourSharedAccessKey>=
Then you should be able to call _serviceClient.InvokeDeviceMethodAsync. This will make the IoT-Hub trigger the direct method on the device and pass on the response to the calling program.
I am new in c#
I am trying to send command to USB port(usbport=========fx3(Cypress chip), to light on LED than with in the custom board))
I tried to scanport but it was failed because my computer(win10) recognized the usb as camera(fx3 is chip that image processing)
so i found this code in sysnet.pe.kr
using System;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
ListDevices().GetAwaiter().GetResult();
}
private static async Task ListDevices()
{
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
foreach (var item in devices)
{
Console.WriteLine($"{item.Id}: {item.Name}");
devices.
}
}
}
}
it works!!! so I found port
but i don't have idea how to send command to the port!!!
please help me ㅠㅠ
First you must read your camera documentation (from producer website or .. , it may have programing sdk)
Otherwise you can use LibUsbDotNet
I was working on a security monitor application and the best approach i found was Skype.
when a possible intrusion occurs the application calls a specified Skype ID which is probably my android phone i am done with all the image processing stuff. But i am stuck with this Skype API i wrote this piece of code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SKYPE4COMLib;
namespace SkypeCall
{
class Program
{
static void Main(string[] args)
{
Skype skype;
skype = new Skype("Skype4COM.Skype", "Skype_");
Call call = skype.PlaceCall(SkypeID);
call.StartVideoSend();
}
}
}
This initiates a voice call but in the call.StartVideoSend(); shows an error
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in SkypeCall.exe
Additional information: CALL: Action failed
i even tried this but i guess that's old API and couldn't get anything out of it.
And not even by sending commands .
if somebody would help me out i'll be grateful.
I think you need to wait until the call is connected.
easiest way would be to test the call.Status
class Program
{
static void Main(string[] args)
{
Skype skype;
skype = new SKYPE4COMLib.Skype();
string SkypeID = args[1];
Call call = skype.PlaceCall(SkypeID);
do
{
System.Threading.Thread.Sleep(1);
} while (call.Status != TCallStatus.clsInProgress);
call.StartVideoSend();
}
}
You could also add an event, however I think this will fire on every call so unless you are only using it for this project it might be too much.
class Program
{
static string SkypeID = "";
static void Main(string[] args)
{
Skype skype;
skype = new SKYPE4COMLib.Skype();
skype.CallStatus += new _ISkypeEvents_CallStatusEventHandler(skype_CallStatus);
Call call = skype.PlaceCall(SkypeID);
Console.ReadKey();
}
static void skype_CallStatus(Call pCall, TCallStatus Status)
{
if (Status == TCallStatus.clsInProgress && pCall.PartnerHandle == SkypeID) { pCall.StartVideoSend(); }
}
}