I speak english a little bit sorry. I need your help because I have invested many hours, and I can not finish the last detail: _ (
I have to connect a mobile phone with bluetooth LE to a relay, to open or close the door. Provide with native Bluetooth and with sockets, but there was no way to do anything that worked. After researching a lot, I found the RxAndroidBle library and got the first results.
The problem is that I'm not used to programming with the reactive paradigm and I really do not know what I'm doing. I pass the code and the steps that follow, to see if something escapes me.
Steps:
Connect directly by known MAC address to device
Send opening hexadecimal command
In successful case, execute closing command with DELAY
private void SendCommandRele(String enable, String disable, int time) {
bleDevice = rxBleClient.getBleDevice("BB:A0:56:06:0A:0A");
byte[] data = hexStringToByteArray (enable);
UUID uuid = UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb");
connectionDisposable = bleDevice.establishConnection(false)
.observeOn(AndroidSchedulers.mainThread())
.flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(uuid, data))
.doOnError(error -> errorConnection())
.doOnComplete(new Action() {
#Override
public void run() throws Exception {
CloseDevice(disable);
}
})
//.repeat(3)
.retryWhen(io.reactivex.Observable::cache)
.doAfterNext(next -> CloseDevice(disable))
//.take(1)
.subscribe(
well -> {
Handler handler = new Handler();
handler.postDelayed(
new Runnable() {
#Override
public void run() {
CloseDevice(disable);
}
},
time
);
},
failed -> Log.e("E","Error: ")
);
progressDialog.dismiss();
//connectionDisposable.dispose();
}
--
private void CloseDevice(String disable) {
bleDevice = rxBleClient.getBleDevice("BB:A0:56:06:0A:0A");
byte[] data = hexStringToByteArray (disable);
connectionDisposable = bleDevice.establishConnection(false)
.observeOn(AndroidSchedulers.mainThread())
.flatMapSingle(rxBleConnection ->
rxBleConnection.writeCharacteristic(UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"), data)
)
.doOnError(error -> {errorConnection();})
//.repeat(3)
//.retry(3)
.take(1)
.subscribe(
);
progressDialog.dismiss();
}
Actual results:
In general, the results I have are quite positive since sometimes it works, but sometimes it does not. A rath, works 10 times in a row, and the other does not work at all. Of course I need a stable connection.
Expected results:
correct work
I found this errors:
- Task COMMON_BROADCAST_MESSAGE_RECIVED failed or timed out. Client disconnecting.
- bta_gattc_mark_bg_conn unable to find the bg connection mask for: XX:XX:XX:XX:XX
Related
despite being new to JDA I havent had any big problems till now, maybe I am just missing something crucial. To quickly explain what following code SHOULD do:
Whenever the bot gets started, the onGuildReady event creates an Object containing a loop which sends a single message to a specified channel and after 1 minute edits said message.
#Override
public void onGuildReady(GuildReadyEvent event) {
System.out.println("ON GUILD READY: " + event.getGuild());
new AutoController(event, channelid);
}
Now with my understanding, the guildReady event should enable me to send messages to specified channels in every guild my bot is connected to AND edit them or do stuff with them.
String messageId = null;
String channelId;
public AutoController(GuildReadyEvent event, String channelId){
this.event = event;
start();
}
#Override
public void run(){
try {
while (true) {
sleep((long) timer);
if(messageId == null){
event.getGuild().getTextChannelById(channelId).sendMessage("A").queue();
this.messageId = event.getGuild().getTextChannelById(channelId).getLatestMessageId();
}else{
event.getGuild().getTextChannelById(channelId).editMessageById(messageId,"B").queue();
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Sending a message whenever the bot goes online works, but as soon as it gets in the 2nd loop where the edit should happen, it throws me an ErrorResponseException saying the message is unkknown.
[ForkJoinPool.commonPool-worker-1] ERROR RestAction - RestAction queue returned failure: [ErrorResponseException] 10008: Unknown Message net.dv8tion.jda.api.exceptions.ContextException at net.dv8tion.jda.api.exceptions.ContextException.here(ContextException.java:54) at net.dv8tion.jda.api.requests.Request.<init>(Request.java:73) at net.dv8tion.jda.internal.requests.RestActionImpl.queue(RestActionImpl.java:200) at net.dv8tion.jda.api.requests.RestAction.queue(RestAction.java:572) at net.dv8tion.jda.api.requests.RestAction.queue(RestAction.java:538) at org.gsbunker.controller.AutoController.run(AutoController.java:45)
I really dont understand why the message is unknown, ive already checked that the messageid and channelid are not null when passed - still getting the same error. the code is slightly simplified for understanding purposes, if questions occur feel free to ask. pleeeeeeeaase help me and my brain <3
Sitting back and relaxing your brain sometimes really is the best solution!
Putting the thread to sleep after queuing made sure that the message is online and ready for retrieval when executing the editMessage method
if(messageId == null){
event.getGuild().getTextChannelById(channelId).sendMessage("A").queue();
sleep(3000);
this.messageId = event.getGuild().getTextChannelById(channelId).getLatestMessageId();
}else{
event.getGuild().getTextChannelById(channelId).editMessageById(messageId,"B").queue();
}
after reviewing the documentation again, if found that the complete() method would be even better suited for a use case like this.
if(messageId == null){
event.getGuild().getTextChannelById(channelId).sendMessage("A").complete();
this.messageId = event.getGuild().getTextChannelById(channelId).getLatestMessageId();
}else{
event.getGuild().getTextChannelById(channelId).editMessageById(messageId,"B").queue();
}
yeeaahh not that big of a problem if you clear your head and stop forgetting java basics, happy coding :D
I am a newbie (6 months going or so) and creating an app on Android (Java) that utilizes FireBase Auth with Google Sign In. (with only a few days of NodeJS exposure now) In other words my end user signs in with the Google Account. That part (I think) works pretty well so far. I use the Firestore Database heavily for a lot of things in the app.
So now I've gotten to the point where I want to use (Callable) Cloud Functions with HTTP Triggers. (never having done any of this before) I'm trying to get a proof of concept working at this time. The actual function works and I can trigger it from my app.
It appears that I cannot figure out how to make the function "private" though; as in "adding proper Members" to the Cloud function who have the right to invoke the function.
I have tried a few different things by trial error, but first let me show what I have.
This is the Cloud Function and I'm passing in an arbitrary String as a test, works nicely: (as long as "allUsers" have the role/right to invoke the function; in other words when the function is public.
exports.createTest = functions.https.onCall((data, context) => {
const text = data.text;
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const email = context.auth.token.email || null;
console.log('UID: ', uid);
console.log('Name: ', name);
console.log('Email: ', email);
console.log('Message: ', text);
});
The above function gets triggered in my Android/Java code like this: (I think this code came from Google Doc/Sample/Example
private FirebaseFunctions mFunctions;
...
private void testing() {
mFunctions = FirebaseFunctions.getInstance();
Log.e(LOG_TAG, "Testing executed!");
String testMessage = "Hello Hello Testing 123 Mic Check";
createTest(testMessage)
.addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
FirebaseFunctionsException.Code code = ffe.getCode();
Object details = ffe.getDetails();
Log.e(LOG_TAG, "FFE: " + ffe.getMessage() );
Log.e(LOG_TAG, "Code: " + code);
Log.e(LOG_TAG, "Details:" + details);
}
// ...
}
// ...
}
});
}
private Task<String> createTest(String text) {
// Create the arguments to the callable function.
Map<String, Object> data = new HashMap<>();
data.put("text", text);
data.put("push", true);
return mFunctions
.getHttpsCallable("createTest") //this is the function name
.call(data)
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
// This continuation runs on either success or failure, but if the task
// has failed then getResult() will throw an Exception which will be
// propagated down.
String result = (String) task.getResult().getData();
if (result != null) {
Log.e(LOG_TAG, "Result: " + result);
}
return result;
}
});
}
Only when I have "allUsers" added with the role/right to "invoke Cloud Function" then I get this working. My understanding of HTTP Requests and such is pretty limited, which is not making things easier.
I tried using the "allAuthenticatedUsers" options, which I figured would do the trick, because I actually authenticate my Users in the app through Firebase/Google Sign In. This Cloud Function shall only be available to either a) authenticated users or b) users of a specific domain. (I have a domain, let's say #testorganization.com) Or if I can identify my particular app (api key?) then that would work, too.
The moment I add a member "allAuthenticatedUsers" with role to invoke the function (and remove "allUsers) nothing happens. I also tried adding the entire domain, but that wouldn't work. (duh) Also tried adding my service account (trial and error at this point) and didn't seem to work.
In my Node JS code I am actually receiving the UID of the authenticated user, so it appears that some kind of user authentication information is already being exchanged.
With that knowledge, I can (successfully tried this) get the UID and cross check that against my database and verify a user that way, but seems unnecessary and I should be able to make the permissions work. (lock the function down entirely) Plus this took a really long time just finish this cross check. Or is this pretty standard procedure to do?
Like this-->
const usersRef = admin.firestore().collection('users').doc(uid)
usersRef.get()
.then((docSnapshot) => {
if (docSnapshot.exists) {
usersRef.onSnapshot((doc) => {
console.log('User Type logged in: ', doc.data().userCategory)
console.log('User Title: ', doc.data().userTitle)
});
} else {
console.log('User does not exist')
}
});
Edit:
So while not having figured out how to shut down the function entirely, I did discover that instead of cross checking my users, I can simple check for auth like this:
if (context.auth){
//user is auth'd
} else {
//no auth
}
That's a little bit better, I guess. (but still doesn't technically prevent access to the function?!)
Thank you so much for any help. Much appreciated.
Edit2:
Here is a screensshot of the area in the cloud console (for cloud function roles/privileges) that I am referring to:
https://imgur.com/cBsjaaL
With a Callable Cloud Function, if you want to ensure that only authenticated users can trigger it's business logic, you actually don't need to configure any extra "cloud function roles/privileges" as shown at the bottom of your question.
By default, with a Callable Cloud Function you will get, when available, "Firebase Authentication and FCM tokens automatically included in requests" and it will "automatically deserializes the request body and validates auth tokens", as explained in the doc.
So you just have to follow the doc and use the context parameter. As you have mentioned in your question, you can check the user is authenticated by doing:
if (context.auth) {
//...
}
If you want to verify the user email, you would do:
exports.addMessage = functions.https.onCall((data, context) => {
const uid = context.auth.uid;
return admin.auth().getUser(uid)
.then(userRecord => {
const userEmail = userRecord.email;
//....
})
.catch(function(error) {
console.log('Error fetching user data:', error);
// Send back an error to the front end
// See https://firebase.google.com/docs/functions/callable#handle_errors
});
});
You will find more examples on how to "work with" users with the Admin SDK here in the doc.
I'm getting this exception in my logs: "clarifai2.exception.ClarifaiException: Maximum attempts reached of getting a default model." which is being generated by a large number of my android app users, but I am unable to replicate the exception or determine what is causing it. Any help on how to recreate or even better prevent this exception from occurring would be very helpful.
UPDATE:
I found the issue and am able to reproduce on demand, if no internet connection is available the Clarifai library throws this exception, there is no check for network connection state within the library. I can check for network connection in my app before building the clarifai client, but if the network connection is lost after the client is built this exception is generated, any ideas on how to prevent this? Thank you.
1 - Ensure data connection to internet is available on phone.
2 - Build clarifai client in onCreate
3 - Send clarifai predict request to food model
4 - Disable wifi and mobile data connections on phone
5 - Wait 10 to 15 seconds, can navigate to other activities, then clarifai throws "Clarifai Exception: Maximum attempts reached of getting a default model" and crashes the app.
Clarifai Library class which can throw this exception is available HERE
I call the buildClarifaiClient method below in my onCreate of the requesting activity.
private void buildClarifaiClient(){
if(clarifaiClient == null){
clarifaiClient = new ClarifaiBuilder("KeyString")
.client(new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
//.addInterceptor(new HttpLoggingInterceptor(logger::info).setLevel(HttpLoggingInterceptor.Level.BASIC))
.build()
)
.buildSync();
}
}
Request to Clarifai on ActivityResult after a picture is taken:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
if(clarifaiClient != null) {
snapSearchActivityResult = true;
taskClarifaiRequest = new AsyncTask<Void, Void, ClarifaiResponse<List<ClarifaiOutput<Concept>>>>() {
#Override
protected void onPreExecute() {
}
#Override
protected ClarifaiResponse<List<ClarifaiOutput<Concept>>> doInBackground(Void... params) {
// The default Clarifai model that identifies concepts in images
// Use this model to predict, with the image that the user just selected as the input
return clarifaiClient.getDefaultModels().foodModel().predict()
.withInputs(ClarifaiInput.forImage(ClarifaiImage.of(getPicByteData())))
.executeSync();
}
#Override
protected void onPostExecute(ClarifaiResponse<List<ClarifaiOutput<Concept>>> response) {
//setBusy(false);
if (!response.isSuccessful()) {
showErrorSnackbar(getString(R.string.clarifaiAPIContactError));
return;
}
final List<ClarifaiOutput<Concept>> predictions = response.get();
if (predictions.isEmpty()) {
showErrorSnackbar(getString(R.string.clarifaiAPIResultsError));
return;
}
List<Concept> concepts = predictions.get(0).data();
int conceptsSize = concepts.size();
Log.d("conceptsSize", String.valueOf(conceptsSize));
for (Concept c : concepts) {
// Do something with the value
Log.d("foodName", String.valueOf(c.name()));
Log.d("foodProb", String.valueOf(c.value()));
}
}
private void showErrorSnackbar(String errorString) {
Snackbar.make(
parentLayout,
errorString,
Snackbar.LENGTH_LONG
).show();
}
};
taskClarifaiRequest.execute();
} else {
Snackbar.make(
parentLayout,
"Unable to connect to Image API, try again.",
Snackbar.LENGTH_LONG
).show();
buildClarifaiClient();
}
}
Stacktrace:
Exception clarifai2.exception.ClarifaiException: Maximum attempts
reached of getting a default model.
clarifai2.dto.model.DefaultModels.update ()
clarifai2.dto.model.DefaultModels.access$000 ()
clarifai2.dto.model.DefaultModels$1.run ()
java.util.concurrent.ThreadPoolExecutor.runWorker
(ThreadPoolExecutor.java:1113)
java.util.concurrent.ThreadPoolExecutor$Worker.run
(ThreadPoolExecutor.java:588)
java.lang.Thread.run (Thread.java:818)
I'd say that the API key you use here doesn't have permissions for doing get model request. When you access the food model via getDefaultModels(), the model is first updated (via get model request) and only after that the predict request is run. If the first one fails, the second one doesn't run.
In the Java API client 2.3 which is about to be released next week, the call getDefaultModels() will no longer initiate get model request since most of the time you require only an ID of a default model, not the complete model data which get model request returns. Since only predict request will be performed, you will not need to have get model request permissions on your API key.
In the meanwhile, you can do one of two things. Either:
Add Models:Get permission to your API key. You do this by going to the API keys page, editing your API key, clicking ADVANCED under Scopes and checking Models:Get. You probably already have Predict permission checked.
Or use the model ID directly on the predict call. I've inserted the food default model ID (which you can also see in the DefaultModels.java link you posted above) into the predict call for you: client.predict("bd367be194cf45149e75f01d59f77ba7").withInputs(...).executeSync();.
I have searched stackoverflow but I could find any answer using ListenableFuture or similar things. Here is what I want to do:
I have 50 webservice APIs. I want to call them, each in a seperate thread & put their responses in a Map where the key is the URL of API & value is response. Problem is when I am giving a debugger at 'Line 1' (mentioned in the code snippet) then everything runs fine. But if there is no debugger I get a 'false' in 'Line 2' i.e the HashMap is not populated. I have tried the following:
Obviously this is happening as the current thread proceeds to execute Line 1 & 2 while the other threads are still working. But I don't know how to make the current thread wait until other threads complete their processing.
Another question: If one of the API takes too much time then how can I stop waiting for it & cancel it & proceed with what I have.
I have tried the following:
for (final StringBuilder url : urlList) {
final URIBuilder uriBuilder = new URIBuilder(url.append(new AuthKeyGenerator().getKey()).toString());
final ListenableFuture<String> response = pool.submit(new Callable<String>() {
#Override
public String call() throws Exception {
ClientResource clientResource = new ClientResource(uriBuilder.build());
clientResource.setResponseEntityBuffering(true);
String response = clientResource.get(String.class);
return response;
}
});
Futures.addCallback(response, new FutureCallback<String>() {
public void onSuccess(String response) {
final UrlResponse urlResponse = new UrlResponse();
urlResponse.setProdResponse(response);
urlResponseMap.put(url.toString(), urlResponse);
}
public void onFailure(Throwable thrown) {
//logger.warn(".......sections of term failed {}", thrown);
}
}, MoreExecutors.sameThreadExecutor());
}
Set<String> set = urlResponseMap.keySet();-----------Line 1
System.out.println("********"+ set.isEmpty());-------Line 2
Hi.
I'm coding a website parser that is aimed to be fast and thus multi-threaded.
The external libraries I'm using are: apache HTTP client, Jsoup (for HTML parsing) and GPars (for message-driven threads).
Now I'll show some concept that I'm trying to implement
static StaticDispatchActor<String> httpActor;
public static void main(String[] args) throws ClientProtocolException, IOException {
int numThreads = 25;
try{
numThreads = Integer.parseInt(args[0]);
} catch (Exception e){
System.out.println("Number of threads defaulted to "+numThreads);
}
final int numberOfThreads = numThreads;
final ExecutorService threadpool = Executors.newCachedThreadPool();
final Async async = Async.newInstance().use(threadpool);
AtomicInteger jobCount = new AtomicInteger(0);
//.....
// This is a parser itself which parses usernames out of every page.
Actor jsoupUser = new StaticDispatchActor<String>(){ // actor to parse users
HashSet<String> users = new HashSet<>(); // found users
public void onMessage(String html){ // takes html -> adds parsed users 2 set
users.addAll(Jsoup.parse(html)
.select("a[href*=/profile/]").stream() // select links
.map(e -> e.text()) // extract usernames
.filter(s -> s.length() > 0) // empty lines -> out
.collect(Collectors.toSet()));
System.out.print("Users: "+users.size()+", Jobs: "+jobCount.get()+"\r");
}
}.start();
// This actor shall extract new links to parse out of every page
Actor jsoupLinker = new StaticDispatchActor<String>(){ // link extractor
HashSet<String> usedLinks = new HashSet<>(); // already found links
public synchronized void removeBack(String url){
#Override
public void onMessage(String html) {
Set<String> links = Jsoup.parse(html).select("a[href]").stream().parallel()
.map(e -> e.attr("href").replace("#comments", "")// here also some replacements...
)
.filter(s -> (!usedLinks.contains(s) && /* other filters */ )
.collect(Collectors.toSet());
links.forEach(url -> httpActor.send(url)); // send to process new URLs
}
}.start(); // start actor
// this actor is the processor of new links and where the error comes in:
httpActor = new StaticDispatchActor<String>(){ // process responses async
public void onMessage(String url) {
try{
while(jobCount.get()>numberOfThreads); // wait for running threads to be less than wanted value; without this number of running jobs goes out of any control
async.execute(Request.Get(defaultWebSiteUrl+url), new FutureCallback<Content>(){ #Override // do request and process async
public void completed(Content c) {
jobCount.decrementAndGet();
try{
String s = c.asString();
jsoupUser.send(s);
jsoupLinker.send(s);
} catch (OutOfMemoryError e1){
System.out.println("out of my memory, "); // This is the thrown error the question is about - [1]
}
}
#Override public void failed(Exception e) {
jobCount.decrementAndGet();
try {
throw e;
} catch (ConnectException e4){ // if the request is timed out resend it
httpActor.send(url);
System.out.println("resent\r\n");
} catch (HttpResponseException e0){
} catch (Exception e1) { // for all other exceptions
e1.printStackTrace();
}
}
#Override public void cancelled() {
jobCount.decrementAndGet(); // never done actually
}
});
jobCount.incrementAndGet();
} catch (IllegalArgumentException e3){
System.out.println("some illigal shit");
}
}
};
httpActor.start();
Now the problem is, although I limited a number of running jobs, my code somehow goes out of memory (search for [1] in the code to see where).
Maybe you have any idea on how to resolve it. Or there is some showcase for similar task, because I fill very wrong about the whole application design and maybe I should change it at all?
Thank you.
So, using BiziClop's tip, I was able to figure out the mistake.
If some is interested, I, as you can see above, was sending HTML code received from server as a string to 2 different actors and than, inside these actors, parsing them. That was the cause for all out-of-memory errors, since these HTML pages are pretty big especially given how many of them are waiting to be processed in the message queue.
The solution I used is just parse the document and select needed elements and transfer their list to matching actors for further processing.
Document doc = Jsoup.parse(c.asString());
jsoupUser.send(doc.select("a[href*=/profile/]"));
jsoupLinker.send(doc.select("a[href]"));
Still, if any one has anything to say about how to improve the algorithm I'll really appreciate it.