I am trying to make a CoAP NON server using CoAPSharp binary in Visual Studio 2015. My target device is Raspberry Pi with Windows IoT core.
"Remotesender" part has the error. I don't know how to solve it
/// <summary>
/// Called when a request is received
/// </summary>
/// <param name="coapReq">The CoAPRequest object</param>
void OnCoAPRequestReceived(CoAPRequest coapReq)
{
//This sample only works on NON requests of type GET
//This sample simualtes a temperature sensor at the path "sensors/temp"
string reqURIPath = (coapReq.GetPath() != null) ? coapReq.GetPath ().ToLower() : "";
/**
* Draft 18 of the specification, section 5.2.3 states, that if against a NON message,
* a response is required, then it must be sent as a NON message
*/
if (coapReq.MessageType.Value != CoAPMessageType.NON)
{
//only NON combination supported..we do not understand this send a RST back
CoAPResponse msgTypeNotSupported = new CoAPResponse (CoAPMessageType.RST, /*Message type*/
CoAPMessageCode.NOT_IMPLEMENTED, /*Not implemented*/
coapReq.ID.Value /*copy message Id*/);
msgTypeNotSupported.Token = coapReq.Token; //Always match the request/response token
msgTypeNotSupported.RemoteSender = coapReq.RemoteSender;
//send response to client
this._coapServer.Send(msgTypeNotSupported);
}
else if (coapReq.Code.Value != CoAPMessageCode.GET)
{
//only GET method supported..we do not understand this send a RST back
CoAPResponse unsupportedCType = new CoAPResponse (CoAPMessageType.RST, /*Message type*/
CoAPMessageCode.METHOD_NOT_ALLOWED, /*Method not allowed*/
coapReq.ID.Value /*copy message Id*/);
unsupportedCType.Token = coapReq.Token; //Always match the request/response token
unsupportedCType.RemoteSender = coapReq.RemoteSender;
//send response to client
this._coapServer.Send(unsupportedCType);
}
else if (reqURIPath != "sensors/temp")
{
//classic 404 not found..we do not understand this send a RST back
CoAPResponse unsupportedPath = new CoAPResponse (CoAPMessageType.RST, /*Message type*/
CoAPMessageCode.NOT_FOUND, /*Not found*/
coapReq.ID.Value /*copy message Id*/);
unsupportedPath.Token = coapReq.Token; //Always match the request/response token
unsupportedPath.RemoteSender = coapReq.RemoteSender;
//send response to client
this._coapServer.Send(unsupportedPath);
}
else
{
//All is well...send the measured temperature back
//Again, this is a NON message...we will send this message as a JSON
//string
Hashtable valuesForJSON = new Hashtable();
valuesForJSON.Add("temp", this.GetRoomTemperature());
string tempAsJSON = JSONResult.ToJSON(valuesForJSON);
//Now prepare the object
CoAPResponse measuredTemp = new CoAPResponse(CoAPMessageType.NON, /*Message type*/
CoAPMessageCode.CONTENT, /*Carries content*/
coapReq.ID.Value/*copy message Id*/);
measuredTemp.Token = coapReq.Token; //Always match the request/response token
//Add the payload
measuredTemp.Payload = new CoAPPayload(tempAsJSON);
//Indicate the content-type of the payload
measuredTemp.AddOption(CoAPHeaderOption.CONTENT_FORMAT,
AbstractByteUtils.GetBytes(CoAPContentFormatOption.APPLICATION_JSON));
//Add remote sender address details
measuredTemp.RemoteSender = coapReq.RemoteSender;
//send response to client
this._coapServer.Send(measuredTemp);
}
}
Error:
error: CS1061 C# does not contain a definition for and no extension method accepting a first argument of type could be found (are you missing a using directive or an assembly reference?)
Simply following the tutorial on CoAPSharp official website.
If you want to run the CoAPSharp library on Raspberry Pi with Windows 10 IoT core, you need to download the experimental release for Windows 10 IoT core. The URL is http://www.coapsharp.com/releases/ . See the last download link.
Also, you may want yo get the source and recompile to get the latest binary to reference in your main project.
Additional information added on 3-Nov-16:
OK, I understood what the problem is. Here is a full and large answer :-)
The CoAPSharp experimental library has a small bug (although unrelated to your problem). I am one of the CoAPSharp developers and work for the company which built the library. The updated library with the fix should be available in a day or two. The issue was with synchronous receive.
The sample you are trying to run, is for NETMF and not for Windows 10 IoT Core and that is why you are getting the errors. There are no samples for the Raspberry Pi experimental release. To help you with the problem, I'm giving below step-by-step solution:
First, download the latest CoAPSharp experimental library to get the fix for synchronous receive bug.
Next, create a solution in which, create one UWA project and add the CoAPSharp library to the solution. Reference the library in the UWA project.
5.1 Create a small server code for Raspberry Pi in this project, as shown below:
/// <summary>
/// We will start a server locally and then connect to it
/// </summary>
private void TestLocalCoAPServer()
{
/*_coapServer variable is a class level variable*/
_coapServer = new CoAPServerChannel();
_coapServer.CoAPRequestReceived += OnCoAPRequestReceived;
_coapServer.Initialize(null, 5683);
}
/// <summary>
/// Gets called everytime a CoAP request is received
/// </summary>
/// <param name="coapReq">The CoAP Request object instance</param>
private async void OnCoAPRequestReceived(CoAPRequest coapReq)
{
//send ACK back
Debug.WriteLine("Received Request::" + coapReq.ToString());
CoAPResponse coapResp = new CoAPResponse(CoAPMessageType.ACK, CoAPMessageCode.CONTENT, coapReq);
coapResp.AddPayload("GOT IT!");
await _coapServer.Send(coapResp);
}
5.2 Next, ensure that port 5683 is not blocked on Raspberry Pi. If yes, then use the powershell to unblock it.
5.3 Next, create a new solution on your desktop(I used Windows 10 and Visual Studio 2015 Community edition) and add another copy of CoAPSharp Raspberry Pi experimental library.
5.3 Now create another UWA project on your desktop . Also, refer the CoAPSharp project in this new project.
5.4 Now write a client in this project that will send/receive CoAP messages from the server hosted on the Raspberry Pi:
private async void TestCoAPAsyncClient()
{
/*_coapAsyncClient is declared at class level*/
this._coapAsyncClient = new CoAPClientChannel();
/*minwinpc was the name of the device running Windows IoT core on Raspberry Pi*/
this._coapAsyncClient.Initialize("minwinpc", 5683);
this._coapAsyncClient.CoAPError += delegate (Exception e, AbstractCoAPMessage associatedMsg) {
Debug.WriteLine("Exception e=" + e.Message);
Debug.WriteLine("Associated Message=" + ((associatedMsg != null) ? associatedMsg.ToString() : "NULL"));
};
this._coapAsyncClient.CoAPRequestReceived += delegate (CoAPRequest coapReq) {
Debug.WriteLine("REQUEST RECEIVED !!!!!!!!!!!!!!" + coapReq.ToString());
};
this._coapAsyncClient.CoAPResponseReceived += delegate (CoAPResponse coapResp) {
Debug.WriteLine("RESPONSE RECEIVED <<<<<<<<<<<<<" + coapResp.ToString());
};
CoAPRequest req = new CoAPRequest(CoAPMessageType.CON, CoAPMessageCode.GET, 100);
//req.SetURL("coap://capi.coapworks.com:5683/v1/time/pcl?mid=CPWK-TESTM");
req.SetURL("coap://localhost:5683/someurl");
await this._coapAsyncClient.Send(req);
}
You can call the method TestCoAPAsyncClient() in a button click or when the page is loaded.
The setup I used was, one desktop with Windows 10 and Visual Studio Community Edition 2015. This was connected to Raspberry Pi running Windows 10 IoT core (OS: 10.0.10240.16384). Both my desktop and the Raspberry Pi were connected to ethernet.
CoAPSharp team added a sample at the link http://www.coapsharp.com/coap-server-windows-10-iot-core-raspberry-pi/ to elaborate this further.
Related
I wrote a console app on .NET, to read without consuming the messages from an IBM MQ queue.
Worked perfect.
Now, I need to migrate that app into .NET Core. Can't figure out why it is extremely slow.
How it works:
target framework .NET Core 3.1
IBMMQDotNetClient NuGet package installed
created a helper class, static, with a static constructor where I initialise MQEnvironment properties like so:
MQEnvironment.CertificateLabel = "ibmwebsphere"; // this is the friendlyname on mmc certificate
MQEnvironment.SSLKeyRepository = "*SYSTEM";
added a method called Init where I initialise connection to MQManager like so:
Hashtable properties = new Hashtable();
properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
properties.Add(MQC.HOST_NAME_PROPERTY, hostName); // I read the hostName from a config file
properties.Add(MQC.PORT_PROPERTY, port); // I read the port from a config file
properties.Add(MQC.CHANNEL_PROPERTY, channelName); // I read the channel from a config file
properties.Add(MQC.SSL_CIPHER_SPEC_PROPERTY, cipherSpec); // I read the cipher spec from a config file, it's something like TLS_RSA_WITH_AES_256_CBC_SHA256
Then, I'm going to create a connection to the queue manager using the connection, and read messages one by one until coming to end of the queue.
var queueManager = new MQQueueManager(qm, properties); // I read the qm from a config file
var queue = queueManager.AccessQueue(queueName, MQC.MQOO_BROWSE + MQC.MQOO_FAIL_IF_QUIESCING); // I read the queueName from a config file
var mqGMO = new MQGetMessageOptions();
mqGMO.Options = MQC.MQGMO_FAIL_IF_QUIESCING + MQC.MQGMO_NO_WAIT + MQC.MQGMO_BROWSE_NEXT; mqGMO.MatchOptions = MQC.MQMO_NONE;
try {
while (true) {
MQMessage queueMessage = new MQMessage();
queue.Get(queueMessage, mqGMO); // code gets apparently stuck on this line,
// overprocessing, for many minutes until it gets to the next line,
// even though I mentioned "NO_WAIT" in the options.
// Note this only happens for .NET Core, but not in .NET framework.
var message = queueMessage.ReadString(queueMessage.MessageLength);
string fileName = message.Substring(0,3); // some processing here to extract some info from each message
}
}
catch(MQException ex)
{
if(err.ReasonCode.CompareTo(MQC.MQRC_NO_MSG_AVAILABLE) == 0)
{
// harmless exception to indicate there are no messages on the queue
}
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
Of course it would be preferable to use a listener, not sure how to do that yet, it would be part of optimising, but for now - why is working so slow on line:
queue.Get(queueMessage, mqGMO); // but, again, as mentioned, only with the amqmdnetstd.dll (.NET Core), because if I use amqmdnet.dll (.NET framework), it works super fast, and it's supposed to be the other way around.
I do need to use .NET Standard/Core because I will run this in Linux, currently testing in Windows.
Don't use the MQEnvironment class as it is not threaded safe. Also, don't mix and match between MQEnvironment class and using MQ HashTable. Put your SSL/TLS information as a property in the MQ HashTable.
i.e.
properties.Add(MQC.SSL_PEER_NAME_PROPERTY, "ibmwebsphere");
properties.Add(MQC.SSL_CERT_STORE_PROPERTY, "*SYSTEM");
There isn't enough of your code to test to see why it might be failing.
I wrote and posted a blog item called: IBM MQ For .NET Core Primer. In the blog post, I included a fully functioning C# MQ example (MQTest62L.cs) that was built and run using .NET Core v3.1 and everything worked perfectly (see very bottom of post). Hence, I would suggest you follow my instructions, download, compile and run MQTest62L.cs to see if the issue is your code or MQ Client library.
Note: I was using Windows 10 Pro, IBM MQ v9.2.0.0 and .NET Core v3.1.415.
I'm attempting to get the characteristics of a custom BLE service. I have a NETStandard class library, making use of NETCore build 17134 for Bluetooth communication. This library is then used in a WPF application (.NET Framework 4.7.1.) I'm able to connect to my BLE peripheral, as well as read the generic service that includes Hardware Revision, etc. However, when it then goes to get the characteristics of my custom service, the status reads AccessDenied and the array of characteristics is empty. Any help would be greatly appreciated.
The same code works when it's purely UWP. However, I have no way to set Bluetooth permissions in the desktop app as I can in UWP. I've attempted running as administrator and performing the workaround using an AppID/registry entry. It didn't seem to work, but perhaps I simply did something wrong.
Is this a known issue? I've read there's been some regression since the original Creator's Update (15xxx) but the threads all seem about a year old.
protected async override Task<IList<ICharacteristic>> GetCharacteristicsNativeAsync()
{
var accessRequestResponse = await _nativeService.RequestAccessAsync();
// Returns Allowed
if (accessRequestResponse != Windows.Devices.Enumeration.DeviceAccessStatus.Allowed)
{
throw new Exception("Access to service " + _nativeService.Uuid.ToString() + " was disallowed w/ response: " + accessRequestResponse);
}
var allCharacteristics = await _nativeService.GetCharacteristicsAsync(Windows.Devices.Bluetooth.BluetoothCacheMode.Uncached);
// Status: AccessDenied
var status = allCharacteristics.Status;
// No error
var err = allCharacteristics.ProtocolError;
var nativeChars = allCharacteristics.Characteristics;
var charList = new List<ICharacteristic>();
foreach (var nativeChar in nativeChars)
{
var characteristic = new Characteristic(nativeChar, this);
charList.Add(characteristic);
}
return charList;
}
Any help would be greatly appreciated!
I am developing a simple app that need to send and receive some data from azure.
First of all, I have worked with a simulated device(and console app). I have configured my azure portal to work with the this data and everything works well.
At the same time, I checked my sensor with unit-tests and it works fine too.
Now, I want to send some data from my sensors to azure(with Universal App). I tried to work with this link:
https://blogs.windows.com/buildingapps/2016/03/03/connect-your-windows-app-to-azure-iot-hub-with-visual-studio/#BgxLrRq1bXolCitM.97
I choose the device that I worked with in the simulated device and got an error of "unknown host" for the client connect.
Do I need to register my raspberry pi as a device before? How I can send a simple string from known universal app (i.e: https://developer.microsoft.com/en-us/windows/iot/samples/helloblinky ) to azure?
I am working with Windows 10 IOT, c#
Thanks!
Update:
I tried to do all what you suggested without success.
Relavant code:
public static async Task SendDeviceToCloudMessageAsync()
{
CreateClient();
var currentTemperature = 20 /*getCurrentTemperature()*/;
var currentHumidity = 20/*getCurrentHumidity()*/;
var telemetryDataPoint = new
{
deviceId = DeviceId,
plantID = 7,
temperature = currentTemperature,
humidity = currentHumidity,
userId = 1
};
var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
var message = new Message(Encoding.ASCII.GetBytes(messageString));
message.Properties.Add("temperatureAlert", (currentTemperature > 30) ? "true" : "false");
Debug.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString);
await deviceClient.SendEventAsync(message);
}
I don't know how to validate the "sharedAccessKey" on connectionString var
Error(on await deviceClient.SendEventAsync(message) line):
Exception thrown: 'System.Exception' in System.Private.CoreLib.ni.dll
No such host is known. (Exception from HRESULT: 0x80072AF9)
You will need to do two things here.
First up, connect your device. Details here - https://developer.microsoft.com/en-us/windows/iot/docs/ConnectDeviceToCloud
Second, connect your app. - https://developer.microsoft.com/en-us/windows/iot/docs/ConnectAppToCloud
If you run into issues when doing the above two, then, you will be able to ask more specific questions.
So I have spent the whole night looking like a zombie in the morning trying to figure out how the OS handles an NFC tap for an NDEFLaunchApp Record and I have known the following.
I'm pretty sure that there is a workaround which lets you launch a system app / third party app (if you know the product Id / GUID) from your app. As there are apps in the Windows Phone Store which I have somehow figured out what I've been trying to.
I have come up with the following code:
NdefLaunchAppRecord appLaunchRecord = new NdefLaunchAppRecord();
appLaunchRecord.AddPlatformAppId("WindowsPhone", "{App GUID}");
appLaunchRecord.Arguments = "_default";
// Creating a new NdefMessage from the above record.
var message = new NdefMessage { appLaunchRecord };
// Getting the record from the message that we just created
foreach (NdefLaunchAppRecord record in message)
{
var specializedType = record.CheckSpecializedType(false);
if (specializedType == typeof(NdefLaunchAppRecord))
{
var x = String.Join(" ", record.Payload);
// Getting the payload by GetString gets a formatted Uri with args
string result = System.Text.Encoding.UTF8.GetString(record.Payload, 0, record.Payload.Length);
// result = "\0\fWindowsPhone&{5B04B775-356B-4AA0-AAF8-6491FFEA5630}\0\b_default";
// result = "(null)(form feed)WindowsPhone&{App GUID}(null)(backspace)_default
// So this will be sent to the OS and I believe the OS will then launch the specified app by an unknown protocol
// like xxx://result
// and the app will be launched?
// So is it then possible to somehow call the following:
await Windows.System.Launcher.LaunchUriAsync(new Uri("OUR MAGIC RESULT?", UriKind.RelativeOrAbsolute));
If anyone has / can figure out a way for this, it would be a REAL Service to the WP Community as developers are restricted by Microsoft to open certain settings / apps which are actually needed by those apps. For instance (speech settings, audio settings, about settings, alarms, region settings, date+time);
APPS that possibly have a workaround:
Music Hub Tile (Launches the old Music+Videos Hub)
http://www.windowsphone.com/en-gb/store/app/music-hub-tile/3faa2f9e-6b8d-440a-bb60-5dd76a5baec1
Tile for Bing Vision
http://www.windowsphone.com/en-gb/store/app/tile-for-bing-vision/05894022-e18c-40a4-a6cc-992383aa7ee8
There are reserved uri schemes for bing and zune.
See: http://msdn.microsoft.com/en-us/library/windows/apps/jj207065(v=vs.105).aspx
Those two apps propably use these and have found some undocumented use of the scheme.
If there is an uri scheme that launches any app by guid from within your app, it is hidden well.
Currently you can only launch apps that registered for an uri scheme or file association.
First linux service listening process is started using the following command:
obexpushd –B[00:15:83:3D:0A:57]:9 –d –o /home/myfolder
On windows the following code is used to perform the obex transfer:
InTheHand.Net.BluetoothAddress address = peerDevice.DeviceAddress;
System.Uri uri = new Uri("obex://" + address.ToString() + "/" + srcfile.Name);
request = new ObexWebRequest(uri);
startcopy = DateTime.Now;
request.ReadFile(file); // this performs the file read from the hard drive
try
{
response = (ObexWebResponse)request.GetResponse(); // here file should be pushed to the listening service
}
catch (System.InvalidOperationException ex)
{
if (response != null) {
response.Close();
}
return;
}
Devices see each other and their obex services are visible as well.
Transfer seems to be successful, but no data is actually transferred.
The code works between windows and windows without a problem.
Obexpushd process ouput shows:
obexpushd 0.10.2 Copyright (C) 2006-2010 Hendrik Sattler
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
Listening on bluetooth/[00:15:83:3D:0A:57]:9
OBEX_EV_ACCEPTHINT, OBEX_CMD_CONNECT
0: Connection from "bluetooth/[00:09:DD:50:94:0B]:9"
0: OBEX_EV_REQHINT, OBEX_CMD_CONNECT
0: OBEX_EV_REQ, OBEX_CMD_CONNECT
0: Sending response code 0
0: OBEX_EV_REQDONE, OBEX_CMD_CONNECT
0: OBEX_EV_REQHINT, OBEX_CMD_PUT
0.1: OBEX_EV_REQCHECK, OBEX_CMD_PUT
0.1: OBEX_EV_REQDONE, OBEX_CMD_PUT
0.1: OBEX_EV_REQHINT, OBEX_CMD_DISCONNECT
0.1: Sending response code 100
0.1: OBEX_EV_REQ, OBEX_CMD_DISCONNECT
0.1: OBEX_EV_REQDONE, OBEX_CMD_DISCONNECT
I have also tried to disable Authentication in C# code but that did not help.
Does any one have idea how to nail this problem down or where to even start looking?
Ok so it seems that no one is much interested in this topic. :) Fortunately I have found the solution myself.
However, it involved a lot of analysis (of both obex transfer protocol and 32feet library) and a bit of luck.
The difference between Linux obexpushd implementation lies in its interpretation of OBEX transfer packets.
I found the OBEX specification on page: OBEX specification.
After debugging the internals of the 23feet obex transfer I found where the code sends the OBEX PUT command used to send file to the receiver. Obex specification gives the following example for PUT inititialization packet:
PUT Command | length of packet | Name header | Length of Name header | name of object | Length header | Length of object | Object Body chunk header | Length of Body header | bytes of body
The 32feet library sends the first packet without the Body Header which causes error in obexpushd Linux command.
Not shure if it is error in 32feet library, obexpushd or if the OBEX specification is not precise enough, but adding the Body header to the first packet solved the problem. From my experiments it turns out that at least 2 first bytes of the objectt must be sent in the first packet. Moreover, adding the header does not crash anything else and Windows<->Windows transfer still works very well.