How come the Device Display Name in IoT Central isn't updating when more than 1 device is being updated? - azure-iot-hub

I have the following code that is based upon the IoT Central C# Samples on GitHub (IoT Central CSharp Examples]1
In a AzureIoTDeviceService class I have the following method:
public async Task UpdateDeviceAsync(Device device, CancellationToken cancellationToken)
{
// If the Http Device Client doesnt exist then create it
if (HttpDeviceClient == null)
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", DeviceParameters.IoTAPIToken);
HttpDeviceClient = new HttpBasedDeviceService(DeviceParameters.IoTApplicationAPIEndpoint, httpClient);
}
// Set the device ID
device.Id = DeviceParameters.DeviceId;
device.InstanceOf = "dtmi:iotDevicesAnywhere:MfrAIUTModelIAA5Level_3o3;1";
ServiceLogger.LogInformation($"The following Device Information is being updated.\nProperty: Update Device - {device.DisplayName}.");
// Update the Device
var result = await HttpDeviceClient.UpdateDeviceAsync(device, cancellationToken);
ServiceLogger.LogInformation($"The return device info is Device Name - {result.DisplayName}.");
string json = JsonConvert.SerializeObject(result, Formatting.Indented);
ServiceLogger.LogDebug($"The following Device Information was updated.\nProperty: Update Device - {json} is complete.");
}
In a HttpBasedDeviceService class I have the following method:
public async Task<Device> UpdateDeviceAsync(Device body, CancellationToken cancellationToken)
{
Guard.Against.Null(body, nameof(body));
var urlBuilder_ = new StringBuilder();
urlBuilder_.Append(_baseUrl != null ? _baseUrl.TrimEnd('/') : "").Append("/devices/{device_id}");
urlBuilder_.Replace("{device_id}", System.Uri.EscapeDataString(ConvertToString(body.Id, System.Globalization.CultureInfo.InvariantCulture)));
urlBuilder_.Append("?api-version=2022-07-31");
var client_ = _httpClient;
try
{
using (var request_ = new HttpRequestMessage())
{
var content_ = new StringContent(JsonConvert.SerializeObject(body, _settings.Value));
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
request_.Content = content_;
request_.Method = new System.Net.Http.HttpMethod("PATCH");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
HttpResponseMessage? response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
try
{
var headers_ = Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
{
headers_[item_.Key] = item_.Value;
}
}
var status_ = ((int)response_.StatusCode).ToString();
if (status_ == "200")
{
var objectResponse_ = await ReadObjectResponseAsync<Device>(response_, headers_).ConfigureAwait(false);
return objectResponse_.Object;
}
else
if (status_ != "200" && status_ != "204")
{
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null);
}
return default(Device);
}
finally
{
if (response_ != null)
{
response_.Dispose();
}
}
}
}
finally
{
}
}
From my Razor Page I call the AzureIoTDeviceService.UpdateDevice() method after I register the devices and update some of the device Properties:
// Set Properties
foreach (var device in AzureDeviceServices)
{
PageLogger.LogInformation(device?.ToString());
// Get the device properties from the collection
var currentDeviceProperties = DevicePropertiesCollection.DevicePropertiesEnum.ElementAt(deviceCount);
// Update Properties
await UpdateDeviceProperties(currentDeviceProperties, device, cancellationToken);
// Update device information
await UpdateDevice(device, currentDeviceProperties, cancellationToken);
// Now Send Telemetry
await SendTelemetries(device, numberOfDaysOfTelemetry, currentDeviceProperties, cancellationToken);
deviceCount++;
}
}
Now here are the scenarios:
When I just register one device everything works fine - the Device Display Name is updated appropriately.
When I register 2 devices, everything runs fine (setting the device properties and telemetry) except the first device Display Name is not updated - only the second device's Display Name is updated. If I try to register 3 devices, only the 3rd device's Display Name is updated.
Here is some of the Log Outputs:
Information: Updating Device Info for device name of test-device1-i90 and device sn of dsn1i90
Information: The following Device Information is being updated.
Property: Update Device - test-device1-i90.
Information: The return device info is Device Name - test-device1-i90.
Information: Report the telemetry values sent. Current Battery Status - 100.
Information: Report the telemetry values sent. Current Tank Level - 100.
Information: Report the telemetry values sent. Current SSRIS - -140.
Information: Report the telemetry values sent. Current Level Read DateTime - 9/1/2022 12:22:20 PM.
Information: Updating properties for device test-device2-i90.
Updating Device Info for device name of test-device2-i90 and device sn of dsn2i90
Information: The following Device Information is being updated.
Property: Update Device - test-device2-i90.
Information: The return device info is Device Name - test-device2-i90.
Information: Report the telemetry values sent. Current Battery Status - 100.
Information: Report the telemetry values sent. Current Tank Level - 100.
Information: Report the telemetry values sent. Current SSRIS - -140.
Information: Report the telemetry values sent. Current Level Read DateTime - 9/1/2022 12:22:21 PM.
As you can see the "return device info Device Name" is what it should be. What could this be?

Related

cant send message to specific user. connection.on not being reached

I cant seem to reach the client from the hub. All I have is a .on on the client side and I am just trying to reach a break point but its never being reached. I have others on the client side I can reach without issue. I am not receiving any errors and not seeing any script issues in the dev tools console. All I want to do is fire off an action to a specific user. I have tried using both .Client and .User with the same result
On my client I have
connection.on("SendRequest", function (requestmessage) {
var whatever = requestmessage;
});
then in the hub
public async Task RequestPrivateChat(string UserListJS)
{
var ConnectionID = "";
MyUser user = new MyUser();
string message = "This is my message";
dynamic UserList = JsonConvert.DeserializeObject(UserListJS);
foreach (string item in UserList)
{
//I get the user okay then use the user.id below
user = _db.Users.Where(x => x.UserName == item).FirstOrDefault();
//I get the connection ID okay
ConnectionID = _connections.GetConnections(item).First();
//Both of these are reached but the client is never reached out to. Both Connection ID and user.Id are populated correctly
await Clients.Client(ConnectionID).SendAsync("SendRequest", message);
await Clients.User(user.Id.ToString()).SendAsync("SendRequest", message);
}
}
This for sending messages to all clients works fine
Hub
await Clients.All.SendAsync("ReceiveMessage", name, message);
Client
connection.on("ReceiveMessage", function (user, message) {
var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
var encodedMsg = user + " says " + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});
UPDATE
I have tried moving this outside of visual studio into IIS just in case this was and IDE issue with same result. I also tried the following
await Clients.User("username").SendAsync("SendChatRequest", message);
and it still didn't work but oddly enough I realized when I first go to the hub
connection.on("SendRequest", function (requestmessage)
is being hit without ever being called. I have confirmed there are only 2 references to send request, one in the hub and one on the client. I am sure there is something I am missing.
Since your await this.Clients.All.SendAsync("SendRequest", message); works, you not passing correctly the connectionId to target the user.
What I suggest is:
Get the connection Id from the context like:
await Clients.Client(this.Context.ConnectionId).SendAsync("SendRequest", message);
Get the connection Id from the caller:
await Clients.Caller(this.Context.ConnectionId).SendAsync("SendRequest", message);
Add the client to specific group and call the method for the group (assuming you added the connection in to a group):
await Clients.Group("GroupName").SendAsync("SendRequest", message);

SEC_ERROR_REVOKED_CERTIFICATE error while accesing the url in browser

Hi i am getting below error while trying to access the website which is hosted in IIS 8 for which the SSL certificate had got expired and i installed the new SSL certificate provided by GoDaddy, it was all working fine for 2 days and now it shows the below error. Let me know if anyone can figure out what is the issue
using Microsoft.CognitiveServices.Speech;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace SPT
{
class Program
{
public static async Task RecognizeSpeechAsync()
{
// Creates an instance of a speech config with specified subscription key and service region.
// Replace with your own subscription key // and service region (e.g., "westus").
var config = SpeechConfig.FromSubscription(" 7cf359266c964dc789960abe063cc65b", "westus");
// Creates a speech recognizer.
using (var recognizer = new SpeechRecognizer(config))
{
Console.WriteLine("Say something...");
// Starts speech recognition, and returns after a single utterance is recognized. The end of a
// single utterance is determined by listening for silence at the end or until a maximum of 15
// seconds of audio is processed. The task returns the recognition text as result.
// Note: Since RecognizeOnceAsync() returns only a single utterance, it is suitable only for single
// shot recognition like command or query.
// For long-running multi-utterance recognition, use StartContinuousRecognitionAsync() instead.
var result = await recognizer.RecognizeOnceAsync();
// Checks result.
if (result.Reason == ResultReason.RecognizedSpeech)
{
Console.WriteLine($"We recognized: {result.Text}");
}
else if (result.Reason == ResultReason.NoMatch)
{
Console.WriteLine($"NOMATCH: Speech could not be recognized.");
}
else if (result.Reason == ResultReason.Canceled)
{
var cancellation = CancellationDetails.FromResult(result);
Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");
if (cancellation.Reason == CancellationReason.Error)
{
Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
Console.WriteLine($"CANCELED: ErrorDetails={cancellation.ErrorDetails}");
Console.WriteLine($"CANCELED: Did you update the subscription info?");
}
}
}
}
public static async Task SynthesisToSpeakerAsync()
{
// Creates an instance of a speech config with specified subscription key and service region.
// Replace with your own subscription key and service region (e.g., "westus").
// The default language is "en-us".
var config = SpeechConfig.FromSubscription("7cf359266c964dc789960abe063cc65b", "westus");
// Creates a speech synthesizer using speaker as audio output.
using (var synthesizer = new SpeechSynthesizer(config))
{
// Receive a text from console input and synthesize it to speaker.
Console.WriteLine("Type some text that you want to speak...");
Console.Write("> ");
string text = Console.ReadLine();
using (var result = await synthesizer.SpeakTextAsync(text))
{
if (result.Reason == ResultReason.SynthesizingAudioCompleted)
{
Console.WriteLine($"Speech synthesized to speaker for text [{text}]");
}
else if (result.Reason == ResultReason.Canceled)
{
var cancellation = SpeechSynthesisCancellationDetails.FromResult(result);
Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");
if (cancellation.Reason == CancellationReason.Error)
{
Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
Console.WriteLine($"CANCELED: ErrorDetails=[{cancellation.ErrorDetails}]");
Console.WriteLine($"CANCELED: Did you update the subscription info?");
}
}
}
// This is to give some time for the speaker to finish playing back the audio
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
public static async Task SynthesisToVideoAsync()
{
var apiUrl = "https://api.videoindexer.ai";
var accountId = "56fbb8f8-b9a8-4119-b46a-fa5fb6668ddd";
var location = "westus2";
var apiKey = "6f354f730bc141f9bc3e57e73c6001b0";
System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol | System.Net.SecurityProtocolType.Tls12;
// create the http client
var handler = new HttpClientHandler();
handler.AllowAutoRedirect = false;
var client = new HttpClient(handler);
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
// obtain account access token
var accountAccessTokenRequestResult = client.GetAsync($"{apiUrl}/auth/{location}/Accounts/{accountId}/AccessToken?allowEdit=true").Result;
var accountAccessToken = accountAccessTokenRequestResult.Content.ReadAsStringAsync().Result.Replace("\"", "");
client.DefaultRequestHeaders.Remove("Ocp-Apim-Subscription-Key");
// upload a video
var content = new MultipartFormDataContent();
Debug.WriteLine("Uploading...");
// get the video from URL
var videoUrl = "VIDEO_URL"; // replace with the video URL
// as an alternative to specifying video URL, you can upload a file.
// remove the videoUrl parameter from the query string below and add the following lines:
//FileStream video =File.OpenRead(Globals.VIDEOFILE_PATH);
//byte[] buffer =newbyte[video.Length];
//video.Read(buffer, 0, buffer.Length);
//content.Add(newByteArrayContent(buffer));
var uploadRequestResult = client.PostAsync($"{apiUrl}/{location}/Accounts/{accountId}/Videos?accessToken={accountAccessToken}&name=some_name&description=some_description&privacy=private&partition=some_partition&videoUrl={videoUrl}", content).Result;
var uploadResult = uploadRequestResult.Content.ReadAsStringAsync().Result;
// get the video id from the upload result
var videoId = JsonConvert.DeserializeObject<dynamic>(uploadResult)["id"];
Debug.WriteLine("Uploaded");
Debug.WriteLine("Video ID: " + videoId);
// obtain video access token
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
var videoTokenRequestResult = client.GetAsync($"{apiUrl}/auth/{location}/Accounts/{accountId}/Videos/{videoId}/AccessToken?allowEdit=true").Result;
var videoAccessToken = videoTokenRequestResult.Content.ReadAsStringAsync().Result.Replace("\"", "");
client.DefaultRequestHeaders.Remove("Ocp-Apim-Subscription-Key");
// wait for the video index to finish
while (true)
{
Thread.Sleep(10000);
var videoGetIndexRequestResult = client.GetAsync($"{apiUrl}/{location}/Accounts/{accountId}/Videos/{videoId}/Index?accessToken={videoAccessToken}&language=English").Result;
var videoGetIndexResult = videoGetIndexRequestResult.Content.ReadAsStringAsync().Result;
var processingState = JsonConvert.DeserializeObject<dynamic>(videoGetIndexResult)["state"];
Debug.WriteLine("");
Debug.WriteLine("State:");
Debug.WriteLine(processingState);
// job is finished
if (processingState != "Uploaded" && processingState != "Processing")
{
Debug.WriteLine("");
Debug.WriteLine("Full JSON:");
Debug.WriteLine(videoGetIndexResult);
break;
}
}
// search for the video
var searchRequestResult = client.GetAsync($"{apiUrl}/{location}/Accounts/{accountId}/Videos/Search?accessToken={accountAccessToken}&id={videoId}").Result;
var searchResult = searchRequestResult.Content.ReadAsStringAsync().Result;
Debug.WriteLine("");
Debug.WriteLine("Search:");
Debug.WriteLine(searchResult);
// get insights widget url
var insightsWidgetRequestResult = client.GetAsync($"{apiUrl}/{location}/Accounts/{accountId}/Videos/{videoId}/InsightsWidget?accessToken={videoAccessToken}&widgetType=Keywords&allowEdit=true").Result;
var insightsWidgetLink = insightsWidgetRequestResult.Headers.Location;
Debug.WriteLine("Insights Widget url:");
Debug.WriteLine(insightsWidgetLink);
// get player widget url
var playerWidgetRequestResult = client.GetAsync($"{apiUrl}/{location}/Accounts/{accountId}/Videos/{videoId}/PlayerWidget?accessToken={videoAccessToken}").Result;
var playerWidgetLink = playerWidgetRequestResult.Headers.Location;
Debug.WriteLine("");
Debug.WriteLine("Player Widget url:");
Debug.WriteLine(playerWidgetLink);
}
static void Main()
{
RecognizeSpeechAsync().Wait();
SynthesisToSpeakerAsync().Wait();
SynthesisToVideoAsync().Wait();
Console.WriteLine("Please press a key to continue.");
Console.ReadLine();
}
}
}

How will USB get devices information

how can i in a UWP app get devices information connected via usb port ,at which port also. and how can i check in case of phone. can i also check that device external power source ,means device is charging via adapter or via usb cable .
You can check the remarks and code from here UsbDevice class
See the following code:
protected override async void OnLaunched1(LaunchActivatedEventArgs args)
{
UInt32 vid = 0x045E;
UInt32 pid = 0x078F;
string aqs = UsbDevice.GetDeviceSelector(vid, pid);
var myDevices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(aqs, null);
if (myDevices.Count == 0)
{
ShowError("Device not found!");
return;
}
UsbDevice device = await UsbDevice.FromIdAsync(myDevices[0].Id);
// Send a control transfer.
UsbSetupPacket initSetupPacket = new UsbSetupPacket()
{
Request = initRequest,
RequestType = new UsbControlRequestType() {
Recipient = UsbControlRecipient.DefaultInterface,
ControlTransferType = UsbControlTransferType.Vendor
}
};
await device.SendOutControlTransferAsync(initSetupPacket);
}
From which you can loop the deviceinformation for details. Please check if you can find the info you want.

Google+ unable to insert moment - A Year and 6 Revisions After

NOTE: Using the Sign-in button is NOT an option
A year ago I was having a problem creating a moment. Back then I was using version 1.2 of the Google+ API .Net client. As I described in this post, I had it working although the code failed to insert a moment from time to time. I was hoping that the process is more stable and easier to implement now, and it seems like it as can be seen in the example that you can download here - the current version as of this writing is v1.8. So I created a simple project following the SimpleOAuth2 sample in the download, but implementing Google+. This is the code I came up:
public partial class _Default : System.Web.UI.Page
{
private PlusService service;
// Application logic should manage users authentication.
// This sample works with only one user. You can change
// it by retrieving data from the session.
private const string UserId = "user-id";
protected void Page_Load(object sender, EventArgs e)
{
GoogleAuthorizationCodeFlow flow;
var assembly = Assembly.GetExecutingAssembly();
using (var stream = assembly.GetManifestResourceStream(
"GPlusSample.client_secrets.json"))
{
flow = new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
DataStore = new FileDataStore("GPlusSample.Store"),
ClientSecretsStream = stream,
//
// Tried only this scope but it did not work
//Scopes = new[] { PlusService.Scope.PlusMe }
//
// I tried the following: but did not work either
//Scopes = new[] { PlusService.Scope.PlusMe,
// "https://www.googleapis.com/auth/plus.moments.write" }
//
// I tried this as well and it failed
//Scopes = new[] { PlusService.Scope.PlusLogin }
//
// Maybe this... but still no joy
Scopes = new[] { PlusService.Scope.PlusLogin,
PlusService.Scope.PlusMe }
});
}
var uri = Request.Url.ToString();
var code = Request["code"];
if (code != null)
{
var token = flow.ExchangeCodeForTokenAsync(UserId, code,
uri.Substring(0, uri.IndexOf("?")), CancellationToken.None).Result;
// Extract the right state.
var oauthState = AuthWebUtility.ExtracRedirectFromState(
flow.DataStore, UserId, Request["state"]).Result;
Response.Redirect(oauthState);
}
else
{
var result = new AuthorizationCodeWebApp(flow, uri, uri)
.AuthorizeAsync(UserId, CancellationToken.None).Result;
if (result.RedirectUri != null)
{
// Redirect the user to the authorization server.
Response.Redirect(result.RedirectUri);
}
else
{
// The data store contains the user credential,
// so the user has been already authenticated.
service = new PlusService(new BaseClientService.Initializer
{
ApplicationName = "Plus API Sample",
HttpClientInitializer = result.Credential
});
}
}
}
/// <summary>Gets the TasksLists of the user.</summary>
public async System.Threading.Tasks.Task InsertMoment()
{
try
{
var me = service.People.Get("me").Execute();
var request = service.Moments.Insert(new Moment()
{
Target = new ItemScope {
Id=Guid.NewGuid().ToString(),
Image="http://www.google.com/s2/static/images/GoogleyEyes.png",
Type="",
Name = "test message",
Description="test",
Text="test message",
},
Type = "http://schemas.google.com/AddActivity",
}, me.Id, MomentsResource.InsertRequest.CollectionEnum.Vault);
var response =await request.ExecuteAsync();
output.Text = "<h1>" + response.Id + "</h1>";
}
catch (Exception ex)
{
var str = ex.ToString();
str = str.Replace(Environment.NewLine, Environment.NewLine + "<br/>");
str = str.Replace(" ", " ");
output.Text = string.Format("<font color=\"red\">{0}</font>", str);
}
}
protected async void createMomentButton_Click(object sender, EventArgs e)
{
await InsertMoment();
}
}
That code always give me a 401 Unauthorized error, even if I have the Google+ API turned on for my project. Here's the actual error I got:
The service plus has thrown an exception: Google.GoogleApiException:
Google.Apis.Requests.RequestError Unauthorized [401] Errors [
Message[Unauthorized] Location[ - ] Reason[unauthorized]
Domain[global] ]
It's interesting to see that the insert moment is failing even though the call to People.Get("me") works - get("me") works with all of the scope combinations I listed above. It's important to note that each time I try a new scope, I first log out of my Google account and delete the access token that is stored in GPlusSample.Store.
EDIT
I tried setting just the Url instead of individual items as suggested by Ian and I got the exact same error.
var request = service.Moments.Insert(new Moment()
{
Target = new ItemScope {
Url = "https://developers.google.com/+/web/snippet/examples/thing"
},
Type = "http://schemas.google.com/AddActivity",
}, me.Id, MomentsResource.InsertRequest.CollectionEnum.Vault);
var response =await request.ExecuteAsync();
https://www.googleapis.com/auth/plus.login is the right scope for writing moments, but you need to have requested the specific app activity types you want to write as well. The parameter for this is request_visible_actions, and it takes a space separated list of arguments of the types (Listed on https://developers.google.com/+/api/moment-types/ - e.g. http://schemas.google.com/AddActivity).
The client library may not have a method for adding request_visible_actions, so you may have to add it on to the auth URL you redirect the user to manually (remember to URLencode the app activity type URLs!)

How to get profile picture(Image) from People App

I'm tring to get the profile picture from People App. I used
Windows.ApplicationModel.Contacts.Contact contact = new Contact();
I got Thumbnail from propety contact.Thumbnail.
I need to convert this Thumbnail to StorageFile. Could you please give inputs to solve this issue?
And, while using the following code:
IRandomAccessStreamWithContentType stream = awaitcontactInfo.Thumbnail.OpenReadAsync();
if(stream != null && stream.Size > 0)
{
//
}
Sometimes I'm getting RPC Server is unavailable Exception. Sometimes the streamSize is Zero.
You are creating new instance of Contact class. You don't have to do that to pick contact from people. You should use ContactPicker.
var contactPicker = new Windows.ApplicationModel.Contacts.ContactPicker();
contactPicker.CommitButtonText = "Select";
ContactInformation contact = await contactPicker.PickSingleContactAsync();
if (contact != null)
{
IRandomAccessStreamWithContentType stream = await contact.GetThumbnailAsync();
if (stream != null && stream.Size > 0)
{
var file = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("MyContactThumb.png", CreationCollisionOption.GenerateUniqueName);
// You can also use FileSavePicker to save file in user defined location.
Windows.Storage.Streams.Buffer MyBuffer = new Windows.Storage.Streams.Buffer(Convert.ToUInt32(stream.Size));
IBuffer iBuf = await stream.ReadAsync(MyBuffer, MyBuffer.Capacity, InputStreamOptions.None);
await FileIO.WriteBufferAsync(file, iBuf);
}
}