Need Guidance for better approch on raspberry pi - raspberry-pi

i want to toggle relays on/off remotely using raspberry pi model b running windows iot core, that raspberry pi have to connect with azure iot hub , and initially i can toggle relay on/off by accessing ui with browser over internet ,
Better approach(c#, node.js on windows iot core), link to related article will be appreciated.

For using Azure IoT Hub, you can utilize direct method.
Device side:
For Windows IoT Core, you can start with UWP app.
The following is a simple sample of implementing the direct method on the device:
using Microsoft.Azure.Devices.Client;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
namespace App1
{
public sealed partial class MainPage : Page
{
private string connectionStr = "HostName=[YOUR HUB NAME].azure-devices.net;DeviceId=[YOUR DEVICE ID];SharedAccessKey=[SHARED ACCESS KEY]";
private DeviceClient deviceClient;
public MainPage()
{
this.InitializeComponent();
AddDirectMethod();
}
private async void AddDirectMethod()
{
deviceClient = DeviceClient.CreateFromConnectionString(connectionStr, TransportType.Mqtt);
await deviceClient.SetMethodHandlerAsync("TurnOn", new MethodCallback(TurnOnRelay), null);
await deviceClient.SetMethodHandlerAsync("TurnOff", new MethodCallback(TurnOffRelay), null);
}
private Task<MethodResponse> TurnOffRelay(MethodRequest methodRequest, object userContext)
{
Debug.WriteLine("Direct method name:" + methodRequest.Name);
// Put Relay toggle code here.
// ...
string result = "{\"Relay Status\":\"The Relay is OFF.\"}";
return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 200));
}
private Task<MethodResponse> TurnOnRelay(MethodRequest methodRequest, object userContext)
{
Debug.WriteLine("Direct method name:" + methodRequest.Name);
// Put Relay toggle code here.
// ...
string result = "{\"Relay Status\":\"The Relay is ON.\"}";
return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 200));
}
}
}
You need install NuGet package microsoft.azure.devices.client to your UWP app. Here is a detailed tutorial of a .NET console app you can reference.
Cloud side:
You can call direct method from Azure Portal like this:

Related

Runnable.Run / StartCoroutine calles to Watson services from Unity

In my ExampleStreaming.cs script, once the user utterance is recognized as final, I send it to both the Watson Assistant service and the Tone Analyzer. Because I am keeping the scripts for each service separate as they are, I have to make calls within each script to access the other service. You can see the call I make to the Tone Analyzer below (the .SendToneAnalysis method):
private void OnRecognize(SpeechRecognitionEvent result, Dictionary<string, object> customData)
{
blah blah blah . . .
/// Only send the recognized speech utterance to the
/// Assistant once we know the user has stopped talking.
if (res.final)
{
string _conversationString = alt.transcript;
Runnable.Run( StopRecording(1f) ); // Stop the microphone from listening.
/// Message.
Dictionary<string, object> input = new Dictionary<string, object>
{
["text"] = _conversationString
};
MessageRequest messageRequest = new MessageRequest()
{
Input = input,
Context = _Context
};
_exampleAssistantV1_script.SendMessageAssistant(messageRequest);
_exampleToneAnalyzer.SendToneAnalysis(_conversationString);
. . .
In my ExampleToneAnalyzer.cs script, I make a simple call to the event-handling methods that are meant to contact the service and also handle success & failure:
public void SendToneAnalysis(string conversationString)
{
_service.GetToneAnalyze(OnGetToneAnalyze, OnFail, conversationString);
}
These calls are typically made using StartCoroutines, particularly in the Watson Unity SDK that there is a specialized Runnable.Run which is essentially a helper class for running co-routines without having to inherit from MonoBehavior.
My question is whether my simple method call to the service might be problematic in certain situations or perhaps just wrong or bad programming, or whether it is perfectly OK to go for that method instead of something like the following:
public void SendToneAnalysis(string conversationString)
{
Runnable.Run( SendAssistantToneAnalysis(conversationString) );
}
private IEnumerator SendAssistantToneAnalysis(string conversationString)
{
if ( !_service.GetToneAnalyze(OnGetToneAnalyze, OnFail, conversationString) )
{
Log.Debug("ExampleToneAnalyzer.SendAssistantToneAnalysis()", "Failed to analyze!");
}
while (!_UserUtteranceToneTested)
yield return null;
}
You don't need to make any of the service calls from within a coroutine. Only authentication using iamApikey should be done using a coroutine
IEnumerator TokenExample()
{
// Create IAM token options and supply the apikey. IamUrl is the URL used to get the
// authorization token using the IamApiKey. It defaults to https://iam.bluemix.net/identity/token
TokenOptions iamTokenOptions = new TokenOptions()
{
IamApiKey = "<iam-api-key>",
IamUrl = "<iam-url>"
};
// Create credentials using the IAM token options
_credentials = new Credentials(iamTokenOptions, "<service-url>");
while (!_credentials.HasIamTokenData())
yield return null;
_assistant = new Assistant(_credentials);
_assistant.VersionDate = "2018-02-16";
_assistant.ListWorkspaces(OnListWorkspaces, OnFail);
}
The examples are only meant to show how to invoke the service call. The only reason the code is invoked from a coroutine is so we can wait for the response of one service call before running another service call (i.e. so we don't try to update or delete a workspace before the workspace is created).
It's no problem.
Runnable.Run() eventually calls StartCoroutine() as the follow.
public Routine(IEnumerator a_enumerator)
{
_enumerator = a_enumerator;
Runnable.Instance.StartCoroutine(this);
Stop = false;
ID = Runnable.Instance._nextRoutineId++;
Runnable.Instance._routines[ID] = this;
#if ENABLE_RUNNABLE_DEBUGGING
Log.Debug("Runnable.Routine()", "Coroutine {0} started.", ID );
#endif
}
Please refer to https://github.com/watson-developer-cloud/unity-sdk/blob/master/Scripts/Utilities/Runnable.cs
And the coroutine can be called from any gameobject, if it is active.

Sending an async email without await from a .Net core web service

I have a webservice .Net core2 that has certain methods that send an email. I have it working fine using smtpclient.sendemailasync.
public async Task<bool> SendEmailAsync(MailMessage email)
{
try
{
if (string.IsNullOrWhiteSpace(emailFrom)) email.From = new MailAddress(emailFrom);
using (SmtpClient client = getSMTPClientInstance())
{
await client.SendMailAsync(email);
}
return true;
}
catch (Exception ex)
{
Log.Error(ex, "Error sending email in EmailService.SendEmailAsync");
return false;
}
}
The only issue is that some SMTP servers take a little too long to respond. I want to set up the email, queue it and return without waiting for the result.
Just using an unawaited async is out for 2 reasons;
It is not reliable to continue a method outside a request context in asp
I need access to the database context of my entity framework to write a log
I have to allow for external or internal SMTP (my client specifies), so a collection folder is not a possibility - at least not without a service that manages it.
How could I achieve this? Do I need to write a service that manages this? If so, how would I do that inside my .Net Core App, keeping in mind that the service also needs to access the EF context to write a log
UPDATE
There is plumbing available in .NetCore DI especially for this. Refer to my additional answer below. Use IServiceScopeFactory
You can call the RegisterAsyncTask method on the Page object. That will signal the ASP.NET runtime you want to make sure these are finished before terminating the request context:
Example:
public void Page_Load(object sender, EventArgs e)
{
RegisterAsyncTask(new PageAsyncTask(LoadSomeData));
}
public async Task LoadSomeData()
{
var clientcontacts = Client.DownloadStringTaskAsync("api/contacts");
var clienttemperature = Client.DownloadStringTaskAsync("api/temperature");
var clientlocation = Client.DownloadStringTaskAsync("api/location");
await Task.WhenAll(clientcontacts, clienttemperature, clientlocation);
var contacts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Contact>>(await clientcontacts);
var location = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clientlocation);
var temperature = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clienttemperature);
listcontacts.DataSource = contacts;
listcontacts.DataBind();
Temparature.Text = temperature;
Location.Text = location;
}
https://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx
So, while I have marked an answer, there are a couple of options that are better solutions for my specific example. First is the option to use a library like hangfire to schedule tasks - although that is not technically an answer to the question.
The better solution in .net core is to use IServiceScopeFactory
With IServiceScopeFactory you can rescope a task so it doesnt go out of scope when the request is complete. I did the following directly in a controller (I later moved to using the hangfire approach, but this works). As you can see, the async task is fired off in a new unawaited thread while the controller code continues.
var task = Task.Run(async () =>
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var service = scope.ServiceProvider.GetRequiredService<ApprovalService>();
await service.sendResponseEmailAsync(approvalInfo.ApprovalId, userID, approvalInfo.emailTo, approvalInfo.ccTo);
}
});

Azure mobile service doesn't register push notifications tags on Android

I'm trying to use the following code to send push notifications to specific users with tags (VS Cordova Project using Azure mobile service).
var tags = [userid, platform];
// Get the handle returned during registration.
var handle = data.registrationId;
// Set the device-specific message template.
if (platform == "android" || platform == "Android") {
// Template registration.
var template = '{ "data" : {"message":"$(message)"}}';
// Register for notifications.
mobileServiceClient.push.gcm.registerTemplate(handle,
"myTemplate", template, null, tags)
.done(registrationSuccess, registrationFailure);
} else if (platform == "iOS") {
// Template registration.
var template = '{"aps": {"alert": "$(message)"}}';
// Register for notifications.
mobileServiceClient.push.apns.registerTemplate(handle,
"myTemplate", template, null, tags)
.done(registrationSuccess, registrationFailure);
}
It registered successfully with the tags for Apple APNS , however on android it only registered the device, but the tags doesn't get registered.
I'm using push plugin 1.4.4 and Azure mobile service 1.2.9
Does anyone knows how to fix this? Any suggestion is appreciated, thanks!
After tracing the source code of azure mobile service plugin, I found that
gcm.prototype.registerTemplate = function (deviceId, name, bodyTemplate, tags)
is missing the "expiryTemplate" parameter. Changing it to
gcm.prototype.registerTemplate = function (deviceId, name, bodyTemplate, expiryTemplate, tags)
fix the problem.
My blog here details on how to receive notifications based on tags in a Cordova client. Basically you'll need a bit of server side code to update your installation / registration to handle specific tags. That's this bit of code:
NotificationHubClient _hub = NotificationHubClient.CreateClientFromConnectionString(notificationHubConnection, notificationHubName);
public async Task CreateOrUpdateInstallationAsync(string installationId, string registrationId, IEnumerable<string> tags)
{
Installation installation = new Installation();
installation.InstallationId = installationId;
installation.PushChannel = registrationId;
installation.Tags = tags.ToArray();
installation.Platform = NotificationPlatform.Gcm;
await _hub.CreateOrUpdateInstallationAsync(installation);
}

google anaylitics visitor counter fail to return using API

I have written following code in a handler to get visitor counter in asp.net website
using Google.Analytics;
using Google.GData.Analytics; //v2.2.0.0
public class Visitor : IHttpHandler {
public void ProcessRequest (HttpContext context) {
AccountQuery feedQuery = new AccountQuery();
AnalyticsService service = new AnalyticsService("kiranaAnalytic");
service.setUserCredentials("myemailid#gmail.com", "mypassword");
DataQuery pageViewQuery = new DataQuery("https://www.google.com/analytics/feeds/data");//https://www.google.com/analytics/feeds/data
pageViewQuery.Ids = "ga:xxxx";
pageViewQuery.Metrics = "ga:visitors";
pageViewQuery.GAStartDate = "2014-05-01";//DateTime.Now.AddMonths(-1).ToString("yyyy-MM-dd");
pageViewQuery.GAEndDate = DateTime.Now.ToString("yyyy-MM-dd");
DataEntry pvEntry = service.Query(pageViewQuery).Entries[0] as DataEntry;
context.Response.ContentType = "text/plain";
context.Response.Write(pvEntry.Metrics[0].Value);
}
public bool IsReusable {
get {
return false;
}
}
}
It was working fine till yeaterday. But I am suddenly started getting following error.
"Google.GData.Client.GDataRequestException: Execution of authentication request returned"
Has anyone have idea about it or did google made some changes ?
This means there is something wrong with your authentication. You appear to be using Login and password which is called client login.
Client login which was discontinued / shutdown on April 20 2015 and I suspect turned off on Tuesday for Google Analytics. You can no longer use client login with Google Analytics API, you need to switch to Oauth2 or a service account. I recommend using the Google .net client library.
tutorial: Google Analytics API C# Oauth2
Google shutdown the old account-password authentication. You need to move your code to use Oauth.

Possible to force the C# Facebook SDK to use HTTP instead of HTTPS?

I need to do some connectivity simulations to see that my code handles various connectivity errors to Facebook. I want to be able to simulate 500s, timeouts etc.
The easiest way to do that is to use Fiddler, but it seems to not be working with HTTPS (I get 403s when I try).
Is ther a way to force the SDK to work with HTTP instead of HTTPS for debugging purposes?
Facebook C# SDK supports your scenario for mocking the entire HttpWebRequest and HttpWebResponse. In fact we actually use that internally in our unit tests so that every single line of the code in Facebook C# SDK actually gets executed and the result is always the same. https://github.com/facebook-csharp-sdk/facebook-csharp-sdk/blob/v5/Source/Facebook.Tests/TestExtensions.cs For now you will need to check these tests in v5 branch as we haven't yet migrated those tests to v6.
For v5, you will need to override the protected CreateHttpWebRequest method in FacebookClient.
Here is an example for v5 when there is no internet connection. There are three hidden classes HttpWebRequestWrapper, HttpWebResponseWrapper and WebExceptionWrapper that you will need to make use of.
public static void NoInternetConnection(this Mock<Facebook.FacebookClient> facebookClient, out Mock<HttpWebRequestWrapper> mockRequest, out Mock<WebExceptionWrapper> mockWebException)
{
mockRequest = new Mock<HttpWebRequestWrapper>();
mockWebException = new Mock<WebExceptionWrapper>();
var mockAsyncResult = new Mock<IAsyncResult>();
var request = mockRequest.Object;
var webException = mockWebException.Object;
var asyncResult = mockAsyncResult.Object;
mockRequest.SetupProperty(r => r.Method);
mockRequest.SetupProperty(r => r.ContentType);
mockRequest.SetupProperty(r => r.ContentLength);
mockAsyncResult
.Setup(ar => ar.AsyncWaitHandle)
.Returns((ManualResetEvent)null);
mockWebException
.Setup(e => e.GetResponse())
.Returns<HttpWebResponseWrapper>(null);
mockRequest
.Setup(r => r.GetResponse())
.Throws(webException);
mockRequest
.Setup(r => r.EndGetResponse(It.IsAny<IAsyncResult>()))
.Throws(webException);
AsyncCallback callback = null;
mockRequest
.Setup(r => r.BeginGetResponse(It.IsAny<AsyncCallback>(), It.IsAny<object>()))
.Callback<AsyncCallback, object>((c, s) =>
{
callback = c;
})
.Returns(() =>
{
callback(asyncResult);
return asyncResult;
});
var mockRequestCopy = mockRequest;
var mockWebExceptionCopy = mockWebException;
facebookClient.Protected()
.Setup<HttpWebRequestWrapper>("CreateHttpWebRequest", ItExpr.IsAny<Uri>())
.Callback<Uri>(uri =>
{
mockRequestCopy.Setup(r => r.RequestUri).Returns(uri);
mockWebExceptionCopy.Setup(e => e.Message).Returns(string.Format("The remote name could not be resolved: '{0}'", uri.Host));
})
.Returns(request);
}
You can then write your tests as below.
[Fact]
public void SyncWhenThereIsNotInternetConnectionAndFiddlerIsNotOpen_ThrowsWebExceptionWrapper()
{
var mockFb = new Mock<FacebookClient> { CallBase = true };
Mock<HttpWebRequestWrapper> mockRequest;
Mock<WebExceptionWrapper> mockWebException;
mockFb.NoInternetConnection(out mockRequest, out mockWebException);
Exception exception = null;
try
{
var fb = mockFb.Object;
fb.Get(_parameters);
}
catch (Exception ex)
{
exception = ex;
}
mockFb.VerifyCreateHttpWebRequest(Times.Once());
mockRequest.VerifyGetResponse();
mockWebException.VerifyGetReponse();
Assert.IsAssignableFrom<WebExceptionWrapper>(exception);
}
In v6 we have made mocking the HttpWebRequest and HttpWebResponse much easier.
Create your custom HttpWebRequest and HttpWebResponse by inheriting HttpWebRequestWrapper and HttpWebReponseWrapper.
Then change the default http web request factory for Facebook C# SDK. Here is the sample of the default factory.
FacebookClient.SetDefaultHttpWebRequestFactory(uri => new HttpWebRequestWrapper((HttpWebRequest)WebRequest.Create(uri)));
If you want to change the HttpWebRequestFactor per FacebookClient instance then use the following code.
var fb = new FacebookClient();
fb.HttpWebRequestFactory = uri=> new MyHttpWebRequestWrapper(uri);
Note: HttpWebRequestWrapper, HttpWebResponseWrapper, WebExceptionWrapper, FacebookClient.SetDefaultHttpWebRequestFactory and FacebookClient.HttpWebRequestFactory has the attribute [EditorBrowsable(EditorBrowsableState.Never)] so you might not see it in the intellisense.
Things like no internet connection that you mention should actually be a part of facebook c# sdk tests and not your app unit tests. The sdk should guarantee that when there is not internet conenction it always throws WebExceptionWrapper and your app unit tests should actually be handling the WebExceptionWrapper exception and not mocking the entire httpwebrequest and httpwebresponse.
I'd suggest you introduce another level of abstraction to your code and code to that abstraction rather than the implementation. Eg.
public interface IFacebookClient {
IEnumerable<Friend> GetFriends();
}
public class HttpsClient : IFacebookClient {
public IEnumerable<Friend> GetFriends() {
// Make a call out to the Facebook API, as per usual
};
}
In your consuming code you'd do something like;
public class ConsumingCode {
private IFacebookClient _client;
public ConsumingCode(IFacebookClient client) {
_client = client;
foreach (Friend friend in _client.GetFriends()) {
// Do something with each Friend
}
}
}
If you're using an IoC container this can all get wired up for you automatically. MVVM frameworks like Caliburn.Micro tend to support this as well.
Then when it comes to unit testing (or manual testing) you can change the implementation of your interface;
public class Http403Client : IFacebookClient {
public IEnumerable<Friend> GetFriends() {
throw new HttpException(403, "Forbidden");
}
}
Obviously this is just a mock up example but I think it demonstrates the concept that you want to implement.