How to disable Enable connection to IoT Hub? - java

I am rehistering succesfully a device in a Azure IoT hub via device provisioning service, but i want to disable the property
Enable connection to IoT Hub
to disable for every registered device.
Is there any way to do this from the code.

You can use the REST API that allows to create or update enrollments (either group enrollments or single enrollments), in particular the provisioningStatus flag. (there is a similar API for individual enrollments).
Next time your device tries to use DPS to get its provisioning info, it will be denied access. If you're caching the IoT Hub credentials, you will need to use the IoT Hub REST API to disable the device (see status flag) that DPS provisioned in the registry.

Yes, there are plenty of libraries available in different different languages.
I am using RegistryManager class of C#. Here's a link!.
Let me share C# code which I am using for same,
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Devices;
public static class EnableDevice
{
static RegistryManager registryManager;
static string iotHubConnectionString = Environment.GetEnvironmentVariable("iotHubConnectionString");
[FunctionName("EnableDevice")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
ILogger log)
{
JObject response = new JObject();
try
{
string deviceId = req.Query["device_id"];
if (string.IsNullOrEmpty(deviceId))
{
response.Add("message", "Please provide valid device_id in request params or in the request body");
response.Add("code", 400);
return new BadRequestObjectResult(response);
}
registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString);
Device device = await registryManager.GetDeviceAsync(deviceId);
if (device == null)
{
response.Add("message", $"Error while enabling device: Device with {deviceId} not found.");
response.Add("code", 400);
return new BadRequestObjectResult(response);
}
device.Status = DeviceStatus.Enabled; // DeviceStatus.Disabled to Disable device
await registryManager.UpdateDeviceAsync(device);
response.Add("message", "Device enabled successfully");
response.Add("code", 200);
return new OkObjectResult(response);
}
catch (Exception e)
{
response.Add("message", e.Message);
response.Add("stacktrace", e.StackTrace);
response.Add("code", 500);
return new BadRequestObjectResult(response);
}
}
}

Related

How to generate access token in Java for Google AutoML Vision API without gcloud?

I am making an Android App that will utilize the Google AutoML Vision API. I am looking for a way to get a permanent access token or generate them in code so that I do not need to use gcloud everytime I want to use my app. How would I go about doing this?
I have created the AutoML model, set up my service account, and coded my app in Android Studio so that it makes the request to the API using Volley. The problem is, they require you to generate and pass an access token using gcloud. I can generate the token and put it in my code but it only lasts for an hour and then it expires. The REST API requires the access token as shown below.
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-
token)"
I have looked into different ways around this problem. For example, there are some Google Client Libraries for Java and Google Cloud Applications that show how to add the service account credentials into the code. I am confused how I would add the Json key file into the code when running it from a phone. I have also read that Firebase could be used but I am unfamiliar about what the process for that would be.
Currently, I will open up gcloud on my computer, generate the access token, paste it into my code and run the app as follows with the header and this returns the desired results for up to an hour until the access code expires.
#Override
public Map<String, String> getHeaders() throws AuthFailureError{
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + accesstoken);
return headers;
}
I would like this to be a stand alone application that can run on an Android phone. What is the best way to go about doing this?
UPDATE:
I was able to add the file into Android Studio and then use some functions to get an access token and it appears to work in the Emulator. I am not sure how secure this method is though because the json file with the key needs to be kept private.
InputStream is = getAssets().open("app.json");
GoogleCredentials credentials =
GoogleCredentials.fromStream(i).createScoped(Lists.newArrayList(scope));
credentials.refreshIfExpired();
AccessToken accesstoken = credentials.getAccessToken();
Add firebase to you android project. https://firebase.google.com/docs/android/setup You will create a project in Firebase and download a json file for configuration and add it in app directory. Add also dependencies in gradle files.
On Firebase console go to ML Kit section and create a AUTML model with your photos.
Train the model
When the training is finished you can download your model and downloaded 3 files in your assets/model directory. And it is ready to use. By this way you will use Firebase AutoML SDK and you dont need to generate the token.
Use your model and do predictions from application.
Steps are :
Prepare image for prediction
Prepare the model
Get the image labeler
Process the image for classification
public void findLabelsWithAutoML() {
Bitmap bitmap = null;
File file = new File(currentPhotoPath);
System.out.println("file "+file);
try {
bitmap = MediaStore.Images.Media
.getBitmap(getContentResolver(), Uri.fromFile(file));
} catch (Exception e) {
e.printStackTrace();
}
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
.setWidth(480) // 480x360 is typically sufficient for
.setHeight(360) // image recognition
.setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
.setRotation(FirebaseVisionImageMetadata.ROTATION_0)
.build();
FirebaseVisionImage firebaseVisionImage = FirebaseVisionImage.fromBitmap(bitmap);
System.out.println("firebaseVisionImage :"+firebaseVisionImage);
FirebaseAutoMLLocalModel localModel = new FirebaseAutoMLLocalModel.Builder()
.setAssetFilePath("model/manifest.json")
.build();
FirebaseVisionOnDeviceAutoMLImageLabelerOptions labelerOptions = new FirebaseVisionOnDeviceAutoMLImageLabelerOptions.Builder(localModel)
.setConfidenceThreshold(0.65F) // Evaluate your model in the Firebase console
// to determine an appropriate value.
.build();
FirebaseVisionImageLabeler firebaseVisionImageLabeler = null;
try {
firebaseVisionImageLabeler = FirebaseVision.getInstance().getOnDeviceAutoMLImageLabeler(labelerOptions);
} catch (Exception e) {
e.printStackTrace();
}
firebaseVisionImageLabeler.processImage(firebaseVisionImage)
.addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionImageLabel>>() {
#Override
public void onSuccess(List<FirebaseVisionImageLabel> labels) {
for (FirebaseVisionImageLabel label : labels) {
System.out.println("label " + label.getText() + " score: " + (label.getConfidence() * 100));
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
//
}
});
}

Firebase Cloud Functions(Stripe: AddPaymentSource)

I have an Android and iOS application that uses Firebase cloud functions with Stripe to process payments.
On the client side I handle the token operation and then write to the realtime database. When done writing the addPaymentSource cloud function triggers which stores that payment source for future transactions.
Interesting enough the process of creating a token on iOS and then saving that output to my server works as expected. My problem comes along when trying to duplicate my iOS implementation into my Android application. The Firebase cloud function triggers as expected but it is outputting an error to my server.
Error found in server:
"The source hash must include an 'object' key indicating what type of source to create."
Client code:
public void tokenizePaymentFields(){
Stripe stripe = new Stripe(getApplicationContext(), stripePublishableKey);
final Card stripeCard = new Card(validCard.getCardNumber()
,Integer.valueOf(validCard.getExpiredDate().substring(0,2)),Integer.valueOf(validCard.getExpiredDate().substring(3,5)),validCard.getCvvCode());
if (!stripeCard.validateCard()) {
Toast.makeText(getApplicationContext(),
"There was an error validating your card.",
Toast.LENGTH_LONG
).show();
return;
}
stripe.createToken(
stripeCard,
new TokenCallback() {
public void onSuccess(Token token) {
// Send token to your server
pushToServer(token);
}
public void onError(Exception error) {
// Show localized error message
activitySubmitCreditCardBinding.progressCircle.setVisibility(View.INVISIBLE);
Toast.makeText(getApplicationContext(),
error.getLocalizedMessage(),
Toast.LENGTH_LONG
).show();
}
}
);
}
Stripe(Firebase Cloud Functions):
https://github.com/firebase/functions-samples/tree/master/stripe
Rather than sending the entire token object to your server, you should simply send the token's id, like this:
public void onSuccess(Token token) {
// Send token to your server
pushToServer(token.getId());
}
In your server-side (Firebase) code, the charge creation request expects only a token ID in the source parameter, not a full token object.

Microsoft Live Connect for Bing Ads OAuth 2.0 without browser

My overall goal is to be able to automatically download a daily report using the bing ads API. To do this, I need to authenticate with OAuth (the old PasswordAuthentication method doesn't work because I have a new microsoft account). I have been through the "Authorization Code Grant Flow" manually and authorised myself successfully. The problem is:
the token is only valid for 1 hour
when the token expires, the process requires the user to manually login using a web browser again and re-allow the app access
Here's an example desktop app using OAuth
Does somebody know either
a more fitting way of authenticating?
or a way of bypassing the user interaction?
SOLUTION:
As mentioned by #eric urban it is only necessary to authorize manually, once. after that, the refresh token will do. (Not really obvious just looking at the example desktop app!)
I wrote a class to deal with all the OAuth stuff and persist the refresh token to a file
public class OAuthRefreshToken {
private static String refreshTokenFileName = "./bingAdsRefreshToken.txt";
private static String ClientId = "XXXXX";
private final OAuthDesktopMobileAuthCodeGrant oAuthDesktopMobileAuthCodeGrant = new OAuthDesktopMobileAuthCodeGrant(ClientId);
private String refreshToken;
public OAuthRefreshToken() {
oAuthDesktopMobileAuthCodeGrant.setNewTokensListener(new NewOAuthTokensReceivedListener() {
#Override
public void onNewOAuthTokensReceived(OAuthTokens newTokens) {
String refreshTime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new java.util.Date());
refreshToken = newTokens.getRefreshToken();
System.out.printf("Token refresh time: %s\n", refreshTime);
writeRefreshTokenToFile();
}
});
getRefreshTokenFromFile();
refreshAccessToken();
}
public OAuthRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
writeRefreshTokenToFile();
}
public OAuthDesktopMobileAuthCodeGrant getoAuthDesktopMobileAuthCodeGrant() {
return oAuthDesktopMobileAuthCodeGrant;
}
private void refreshAccessToken(){
oAuthDesktopMobileAuthCodeGrant.requestAccessAndRefreshTokens(refreshToken);
}
private void getRefreshTokenFromFile(){
try {
refreshToken = readFile(refreshTokenFileName, Charset.defaultCharset());
} catch (IOException e) {
e.printStackTrace();
}
}
private static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
private void writeRefreshTokenToFile(){
File refreshTokenFile = new File(refreshTokenFileName);
try {
FileWriter f2 = new FileWriter(refreshTokenFile);
f2.write(refreshToken);
f2.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
System.out.printf("New refresh token: %s\n", refreshToken);
System.out.printf("Stored Safely in: %s\n", refreshTokenFileName);
}
}
Use it in your app like:
final OAuthRefreshToken oAuthRefreshToken = new OAuthRefreshToken();
final OAuthDesktopMobileAuthCodeGrant oAuthDesktopMobileAuthCodeGrant = oAuthRefreshToken.getoAuthDesktopMobileAuthCodeGrant();
You are correct that user consent is required up front (once). Thereafter you can use the refresh token to request additional access tokens without user interaction. For details about Authorization Code grant flow using the Bing Ads Java SDK please see Getting Started Using Java with Bing Ads Services. Does this help?
The refresh token should not expire that quickly, they are usually permanent or last a very long time. These can however be revoked, or invalidated if you request too many of them. i believe when you have requested more than 25 different refresh tokens, they older ones start to become invalid.

Physical device testing and google-app-engine back-end

I'm following this tutorial to try to make an andorid app with a backend on google app-engine.
I'm at the point where I want to test the connection between my app and GAE Api locally so I try to execute the following code on my Nexus 5 phone (not emulated).
MainActivity.java
public class MainActivity extends FragmentActivity {
private final String DEBUG_TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* AsyncTask for calling Mobile Assistant API for checking into a place (e.g., a store)
*/
private class CheckInTask extends AsyncTask<Void, Void, Void> {
/**
* Calls appropriate CloudEndpoint to indicate that user checked into a place.
*
* #param params the place where the user is checking in.
*/
#Override
protected Void doInBackground(Void... params) {
CheckIn checkin = new CheckIn();
// Set the ID of the store where the user is.
// This would be replaced by the actual ID in the final version of the code.
checkin.setPlaceId("StoreNo123");
Checkinendpoint.Builder builder = new Checkinendpoint.Builder(
AndroidHttp.newCompatibleTransport(), new JacksonFactory(),
null);
builder = CloudEndpointUtils.updateBuilder(builder);
Checkinendpoint endpoint = builder.build();
try {
endpoint.insertCheckIn(checkin).execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
}
And I get this
Where I shouldget this
(source: google.com)
And the log shows :
java.net.SocketTimeoutException: failed to connect to /10.0.2.2 (port 8888) after 20000ms
No CheckIn is available on the "entity kind" list
I've lauched the appengine locally i get : INFOS: Dev App Server is now running
I've CloudEndPointUtils.java setting to : LOCAL_ANDROID_RUN = true; LOCAL_APP_ENGINE_SERVER_URL = "http://localhost:8888/"; and LOCAL_APP_ENGINE_SERVER_URL_FOR_ANDROID = "http://10.0.2.2:8888";
I feel like it's because I'm using a physical device for debugging...
What do you think and how to make it work ?
(I can't figure out how run an emulator of android on my computer so if there is another solution that would be great)
Edit: I've tried to deploy the app but I'm having the same issue with the same log error.
This is beacause 10.0.2.2 is the address of localhost when using the emulator. If you want to try it on your device and all your computer and device are connected to the local network, try changing the server address to http://local-network-ip:port/_ah/api. When launching the appengine application set the host address to 0.0.0.0 to make it accessible to other machines on the network.

How I get menu click event

I created a custom menu using mirror api.
menu created method on MainServlet
public List<MenuItem> makeDealMenu(String appBaseUrl) {
String dealMenuIconUrl = appBaseUrl + "static/images/deal_50.png";
MenuValue dealMenuValue = new MenuValue();
dealMenuValue.setDisplayName("DEAL");
dealMenuValue.setIconUrl(dealMenuIconUrl);
List<MenuValue> dealMenuValueList = new ArrayList<MenuValue>();
dealMenuValueList.add(dealMenuValue);
MenuItem dealMenuItem = new MenuItem();
dealMenuItem.setAction("CUSTOM");
dealMenuItem.setId("dealMenu");
dealMenuItem.setValues(dealMenuValueList);
List<MenuItem> customMenuItemList = new ArrayList<MenuItem>();
customMenuItemList.add(dealMenuItem);
return customMenuItemList;
}
From doPost method I call MirrorClient
MirrorClient.insertSubscription(credential,
WebUtil.buildUrl(request, "/notify"), userId, "timeline");
In MirrorClient define method insertSubscription
public static Subscription insertSubscription(Credential credential,
String callbackUrl, String userId, String collection)
throws IOException {
LOG.info("Attempting to subscribe verify_token " + userId
+ " with callback " + callbackUrl);
callbackUrl = callbackUrl.replace("appspot.com", "Appspot.com");
Subscription subscription = new Subscription();
subscription.setCollection(collection);
subscription.setCallbackUrl(callbackUrl);
subscription.setUserToken(userId);
return getMirror(credential).subscriptions().insert(subscription)
.execute();
}
then in NotifyServlet receive the event this way..
JsonFactory jsonFactory = new JacksonFactory();
Notification notification = jsonFactory.fromString(notificationString,
Notification.class);
if (notification.getUserActions().contains(
new UserAction().setType("CUSTOM"))) {
String selectedCustomMenuItemId = notification.getItemId();
if ("dealMenu".equals(selectedCustomMenuItemId)) {
LOG.info("********** I am here in event");
}
}
In Google Cloud Console I set callback url
http://localhost:8080/oauth2callback
https://mirrornotifications.appspot.com/forward?url=http://localhost:8080/notify
http://localhost:8080
How can I get menu's click event or action from my Servlet? Please somebody help....
From mirror api java sample app you can see NotifyServlet implementation. (Or what type server you have find the relevant sample project from quickstart samples).
Firstly you have to define your notification callback to the mirror api. Then you must subscribe register for notifications. After this all menu selections for your glassware are going to be passed to your notification callback(servlet for notifications) througt mirror api.
If your servlet is written on Java try this at your notification callBack:
JsonFactory jsonFactory = new JacksonFactory();
// notificationString is parsed form httpRequest's inputstream which is send from Mirror API
Notification notification = jsonFactory.fromString(notificationString, Notification.class);
if (notification.getUserActions().contains(new UserAction().setType("CUSTOM").setPayload("dealMenu")) {
// User selected CUSTOM menu item on your glassware
}
Edit: Define your notification callback url https. from this:
http://localhost:8080/notify
To this:
https://mirrornotifications.appspot.com/forward?url=http://localhost:8080/notify
To subscribe to notifications in a production environment, you must
provide a callback URL with a valid SSL certificate to handle the
notification. For development purposes, you can use a subscription
proxy server provided by Google that forwards notifications to a
non-SSL callback URL.
https://developers.google.com/glass/tools-downloads/subscription-proxy
Edit2 I modified sample java project a little bit to make it work for notifications on localhost. You may want to put below code to MirrorClient class's insertSubscription method:
// To work with notifications, modify the notify callback's url by adding subscription-proxy
// callbackUrl = "https://mirrornotifications.appspot.com/forward?url=" + callbackUrl;
if("http://localhost:8080/notify".equals(callbackUrl)) {
callbackUrl = "https://mirrornotifications.appspot.com/forward?url=" + callbackUrl;
}

Categories

Resources