Uart / GPS driver sample buffer overflow - uart

I am trying the sample for the GPS driver with a raspberry pi 3 and the Ultimate GPS V3 breakout board.
Here is the full source code: https://github.com/androidthings/drivers-samples/tree/master/gps
The GPS board is connected following this schematics:
When launching the sample app, I get the following error:
com.example.androidthings.driversamples E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.androidthings.driversamples, PID: 1299
java.nio.BufferOverflowException
at java.nio.Buffer.nextPutIndex(Buffer.java:508)
at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:142)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule.processBuffer(NmeaGpsModule.java:178)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule.readUartBuffer(NmeaGpsModule.java:160)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule.access$000(NmeaGpsModule.java:35)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule$1.onUartDeviceDataAvailable(NmeaGpsModule.java:139)
at com.google.android.things.pio.UartDevice$UartDeviceCallbackDispatch.dispatchInterruptEvent(UartDevice.java:507)
at com.google.android.things.pio.CallbackDispatch.onFileDescriptorEvents(CallbackDispatch.java:127)
at android.os.MessageQueue.dispatchEvents(MessageQueue.java:282)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:323)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Update 1
After enabling the debug in the contrib-driver project, I see a new error: W/NmeaParser: Invalid checksum (62), expected 108
12-28 17:53:28.638 1378-1378/com.example.androidthings.driversamples D/XXX: Debug version used
12-28 17:53:29.451 1378-1378/com.example.androidthings.driversamples I/Choreographer: Skipped 34 frames! The application may be doing too much work on its main thread.
12-28 17:53:29.862 1378-1378/com.example.androidthings.driversamples W/NmeaParser: Invalid checksum (62), expected 108
12-28 17:53:29.862 1378-1378/com.example.androidthings.driversamples D/XXX: Buffer reset
12-28 17:53:30.427 1378-1378/com.example.androidthings.driversamples D/AndroidRuntime: Shutting down VM
12-28 17:53:30.428 1378-1378/com.example.androidthings.driversamples E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.androidthings.driversamples, PID: 1378
java.nio.BufferOverflowException
at java.nio.Buffer.nextPutIndex(Buffer.java:508)
at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:142)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule.processBuffer(NmeaGpsModule.java:179)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule.readUartBuffer(NmeaGpsModule.java:161)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule.access$000(NmeaGpsModule.java:35)
at com.google.android.things.contrib.driver.gps.NmeaGpsModule$1.onUartDeviceDataAvailable(NmeaGpsModule.java:140)
at com.google.android.things.pio.UartDevice$UartDeviceCallbackDispatch.dispatchInterruptEvent(UartDevice.java:507)
at com.google.android.things.pio.CallbackDispatch.onFileDescriptorEvents(CallbackDispatch.java:127)
at android.os.MessageQueue.dispatchEvents(MessageQueue.java:282)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:323)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
12-28 17:53:30.439 1378-1378/com.example.androidthings.driversamples I/Process: Sending signal. PID: 1378 SIG: 9
Update 2
After increasing the buffer size by 4, I was able to get few messages in. I see some messages have some junk that would explain the overflow:
12-28 23:38:17.393 2366-2366/? D/XXX: message: ��GPGGA,233817.000,3742.1931,N,12208.3976,W,1,04,1.96,164.3,M,-25.5,M,,*58
12-28 23:38:17.394 2366-2366/? D/XXX: Buffer reset
12-28 23:38:17.394 2366-2366/? D/XXX: message: GPGSA,A,3,23,03,26,22,,,,,,,,,2.20,1.96,1.00*0B
12-28 23:38:17.395 2366-2366/? D/XXX: Buffer reset
12-28 23:38:17.544 2366-2366/com.example.androidthings.driversamples D/XXX: message: GP��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RMC,233817.000,A��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������,3742.1931,N,12208.3976,W,0.42,205.67,281216,,,A*71
12-28 23:38:17.545 2366-2366/com.example.androidthings.driversamples D/XXX: Buffer reset
12-28 23:38:17.545 2366-2366/com.example.androidthings.driversamples D/XXX: message: GPVTG,205.67,T,,M,0.42,N,0.78,K,A*32
12-28 23:38:17.546 2366-2366/com.example.androidthings.driversamples D/XXX: Buffer reset
I have no idea where that junk could come from...

In some cases processBuffer() will process the whole buffer (512 bytes) regardless of how many bytes are read from the UART. If it happens to miss a start or end character you can end up with a lot of '0' in the message buffer. You can modify this to be like this:
int count;
while ((count = uart.read(buffer, buffer.length)) > 0) {
processBuffer(buffer, count);
}
then modify this to be more like this:
private void processBuffer(byte[] buffer, int length) {
for (int i = 0; i < length; i++) {
if (mParser.getFrameStart() == buffer[i]) {
handleFrameStart();
} else if (mParser.getFrameEnd() == buffer[i]) {
handleFrameEnd();
} else {
//Insert all other characters into the buffer
mMessageBuffer.put(buffer[i]);
}
}
}
Then you won't be filling the message buffer with garbage if an end character gets dropped. I noticed this happening in a project I'm working on that uses this source code. The readUartBuffer() method can read split messages, i.e., the start or end of a message. If it does, bad things happen.

Looking at the demo code https://github.com/androidthings/drivers-samples/blob/master/gps/src/main/java/com/example/androidthings/driversamples/GpsActivity.java#L35 the Baud rate is set correctly as per the data sheet: https://cdn-learn.adafruit.com/downloads/pdf/adafruit-ultimate-gps.pdf
And looking at the contrib-driver for NmeaGpsModule the message buffer length is twice the size of the buffer read from the driver https://github.com/androidthings/contrib-drivers/blob/master/gps/src/main/java/com/google/android/things/contrib/driver/gps/NmeaGpsModule.java#L169 so it can't overflow with just one read.
A theory for the issue could be that the message buffer is not being cleared after it receives data - therefore you get a BufferOverflowException after a few packets.
The buffer is reset in 2 places:
When a new frame starts:
https://github.com/androidthings/contrib-drivers/blob/master/gps/src/main/java/com/google/android/things/contrib/driver/gps/NmeaGpsModule.java#L187
Or when a frame ends:
https://github.com/androidthings/contrib-drivers/blob/master/gps/src/main/java/com/google/android/things/contrib/driver/gps/NmeaGpsModule.java#L209
I don't have the hardware to debug your issue, however I can recommend how you could do it:
This goes for anyone wanting to debug a contrib-driver
Fork / Make a copy of this android library: https://github.com/androidthings/contrib-drivers/tree/master/gps
Edit the build.gradle to add this dependency: https://github.com/novoda/bintray-release (follow the README for instructions).
Once you add that dependency the build.gradle will look like this:
apply plugin: 'com.android.library'
apply plugin: 'com.novoda.bintray-release' // new code
android {
compileSdkVersion 24
buildToolsVersion '24.0.3'
defaultConfig {
minSdkVersion 24
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.novoda:bintray-release:0.4.0' // new code
}
}
dependencies {
compile 'com.android.support:support-annotations:24.2.0'
provided 'com.google.android.things:androidthings:0.1-devpreview'
}
publish { // new code
userOrg = 'google'
groupId = 'com.google.android.things.contrib'
artifactId = 'driver-gps'
publishVersion = '0.1-DEBUG'
}
Now you can release your own version of the GPS driver for debugging, but first:
Edit the java files, to add logging. In the NmeaGpsModule.java of your fork/copy, make two changes:
private void init(UartDevice device, int baudRate, Handler handler) throws IOException {
Log.d("XXX", "MY VERSION BEING USED"); // new code
mDevice = device;
mDevice.setBaudrate(baudRate);
mDevice.registerUartDeviceCallback(mCallback, handler);
mParser = new NmeaParser();
}
and
private void resetBuffer() {
Log.d("XXX", "BUFFER BEING RESET"); // new code
mMessageBuffer.clear();
mFrameFlag = false;
}
To release this version run this command in a terminal from the same folder as the build.gradle:
./gradlew clean build bintrayUpload -PdryRun=true
Now you have released a dependency!
Back in your application (in this case the driver-samples) https://github.com/androidthings/drivers-samples/blob/master/gps/build.gradle#L39:
Change the build.gradle to have a different dependency:
compile 'com.google.android.things.contrib:driver-gps:0.1'
becomes
compile 'com.google.android.things.contrib:driver-gps:0.1-DEBUG'
and tell it to look locally for this dependency:
repositories {
mavenLocal()
jcenter()
}
Now rerun the application and you should see your logs! First the sanity log to prove it worked "MY VERSION BEING USED" then the buffer being reset "BUFFER BEING RESET" if the buffer isn't being reset .. you need to check your hard wiring or add more logs to figure out why.

Related

Firebase Messaging fails sporadically with internal-error

I've been getting internal error quite a lot this week while sending messages to my iOS devices through the Node.js library (code is the same, same library version etc.)
It's hard to debug because sometimes it works. When I put a for loop to send 10 messages, my devices would get 3-4.
FirebaseMessagingError: Internal error encountered.
> at FirebaseMessagingError.FirebaseError [as constructor] (/node_modules/firebase-admin/lib/utils/error.js:42:28)
> at FirebaseMessagingError.PrefixedFirebaseError [as constructor] (/node_modules/firebase-admin/lib/utils/error.js:88:28)
> at new FirebaseMessagingError (/node_modules/firebase-admin/lib/utils/error.js:254:16)
> at Function.FirebaseMessagingError.fromServerError (/node_modules/firebase-admin/lib/utils/error.js:287:16)
> at Object.createFirebaseError (/node_modules/firebase-admin/lib/messaging/messaging-errors.js:34:47)
> at FirebaseMessagingRequestHandler.buildSendResponse (/node_modules/firebase-admin/lib/messaging/messaging-api-request.js:119:47)
> at /node_modules/firebase-admin/lib/messaging/messaging-api-request.js:94:30
> at Array.map (<anonymous>)
> at /node_modules/firebase-admin/lib/messaging/messaging-api-request.js:93:30
> at processTicksAndRejections (internal/process/task_queues.js:97:5) {
> errorInfo: {
> code: 'messaging/internal-error',
> message: 'Internal error encountered.'
> },
> codePrefix: 'messaging'
> }
I tried changing the auth key, but still getting errors.
Code is very simple
import * as admin from 'firebase-admin'
admin.initializeApp()
async function sendPushNotification(
tokens: string[],
title: string,
body: string
): Promise<admin.messaging.BatchResponse> {
console.log('sending %s to %d devices', body, tokens.length)
const message = {
notification: {
title: title,
body: body,
},
tokens: tokens,
apns: {
payload: {
aps: {
sound: 'default',
},
},
},
}
return admin.messaging().sendMulticast(message)
}
I have been having the same problem: node.js firebase admin SDK sending notifications to iOS occasionally fails with 500/ISE.
It seems specific to, or at least more common with, iOS as during Android development I never had this issue. I contacted Firebase support and here is what they said:
Internal Server Error are usually due to timeouts. Some minor hiccups can't be avoided that's why we recommend developers to implement exponential back-off retry mechanism. You can refer to this StackOverflow discussion for more information on retry-after and exponential back offs.
It seems like a good idea to build in some retry support on my side in any case. I haven't used it before but I like the look of the cockatiel module on npm. I'm planning on going with the retryWithBreaker example given at the start of their README, just with the backoff attempts and breaker set higher, maybe 5 and 20 respectively.

How to design worker verticle with infinite blocking loop?

I am trying to compose a worker verticle that will bridge Google cloud PubSub topic subscription with an event-bus of the vert.x by adopting kotlin example of PubSub combined with this answer regarding worker with an infinite blocking loop processing.
It does works but Vert.X keep nagging into the log that Thread blocked by throwing an exception sometime after the message was from PubSub was received (please ignore blocking initialization for now):
9:15:12 AM: Executing task 'run'...
WARNING: You are a using release candidate 2.0.0-rc5. Behavior of this plugin has changed since 1.3.5. Please see release notes at: https://github.com/GoogleCloudPlatform/app-gradle-plugin.
Missing a feature? Can't get it to work?, please file a bug at: https://github.com/GoogleCloudPlatform/app-gradle-plugin/issues.
:compileKotlin UP-TO-DATE
:compileJava NO-SOURCE
:processResources NO-SOURCE
:classes UP-TO-DATE
Mar 10, 2019 9:15:18 AM io.vertx.core.impl.launcher.commands.Watcher
INFO: Watched paths: [/home/username/IdeaProjects/project_name/./src]
Mar 10, 2019 9:15:18 AM io.vertx.core.impl.launcher.commands.Watcher
INFO: Starting the vert.x application in redeploy mode
:run
Starting vert.x application...
f48ba7fd-a52b-487f-b553-2b74473e58ba-redeploy
Creating topic gcs-project-id:vertx.
Mar 10, 2019 9:15:18 AM com.google.auth.oauth2.DefaultCredentialsProvider warnAboutProblematicCredentials
WARNING: Your application has authenticated using end user credentials from Google Cloud SDK. We recommend that most server applications use service accounts instead. If your application continues to use end user credentials from Cloud SDK, you might receive a "quota exceeded" or "API not enabled" error. For more information about service accounts, see https://cloud.google.com/docs/authentication/.
Mar 10, 2019 9:15:21 AM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-0,5,main] has been blocked for 2759 ms, time limit is 2000 ms
Topic gcs-project-id:vertx successfully created.
Creating subscription gcs-project-id:kotlin.
Mar 10, 2019 9:15:22 AM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-0,5,main] has been blocked for 3759 ms, time limit is 2000 ms
Mar 10, 2019 9:15:23 AM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-0,5,main] has been blocked for 4758 ms, time limit is 2000 ms
Mar 10, 2019 9:15:24 AM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-0,5,main] has been blocked for 5759 ms, time limit is 2000 ms
io.vertx.core.VertxException: Thread blocked
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:469)
at com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly(Uninterruptibles.java:142)
at com.google.common.util.concurrent.Futures.getUnchecked(Futures.java:1309)
at com.google.api.gax.rpc.ApiExceptions.callAndTranslateApiException(ApiExceptions.java:52)
at com.google.api.gax.rpc.UnaryCallable.call(UnaryCallable.java:112)
at com.google.cloud.pubsub.v1.SubscriptionAdminClient.createSubscription(SubscriptionAdminClient.java:359)
at com.google.cloud.pubsub.v1.SubscriptionAdminClient.createSubscription(SubscriptionAdminClient.java:260)
at com.example.project.MainVerticle.subscribeTopic(MainVerticle.kt:76)
at com.example.project.MainVerticle.init(MainVerticle.kt:46)
at io.vertx.core.impl.DeploymentManager.lambda$doDeploy$8(DeploymentManager.java:492)
at io.vertx.core.impl.DeploymentManager$$Lambda$28/1902260856.handle(Unknown Source)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:320)
at io.vertx.core.impl.EventLoopContext.lambda$executeAsync$0(EventLoopContext.java:38)
at io.vertx.core.impl.EventLoopContext$$Lambda$29/1640639994.run(Unknown Source)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Subscription gcs-project-id:kotlin successfully created.
Listening to messages on kotlin:
Mar 10, 2019 9:15:25 AM io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer
INFO: Succeeded in deploying verticle
Message Id: 462746807438186 Data: Bazinga
Message Id: 462746750387788 Data: Another message
Mar 10, 2019 9:16:25 AM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-worker-thread-0,5,main] has been blocked for 60171 ms, time limit is 60000 ms
io.vertx.core.VertxException: Thread blocked
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:492)
at java.util.concurrent.LinkedBlockingDeque.take(LinkedBlockingDeque.java:680)
at com.example.project.MainVerticle$start$1.handle(MainVerticle.kt:32)
at com.example.project.MainVerticle$start$1.handle(MainVerticle.kt:13)
at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$2(ContextImpl.java:272)
at io.vertx.core.impl.ContextImpl$$Lambda$33/1101004004.run(Unknown Source)
at io.vertx.core.impl.TaskQueue.run(TaskQueue.java:76)
at io.vertx.core.impl.TaskQueue$$Lambda$26/1213216872.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Mar 10, 2019 9:16:26 AM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-worker-thread-0,5,main] has been blocked for 61172 ms, time limit is 60000 ms
io.vertx.core.VertxException: Thread blocked
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:492)
at java.util.concurrent.LinkedBlockingDeque.take(LinkedBlockingDeque.java:680)
at com.example.project.MainVerticle$start$1.handle(MainVerticle.kt:32)
at com.example.project.MainVerticle$start$1.handle(MainVerticle.kt:13)
at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$2(ContextImpl.java:272)
at io.vertx.core.impl.ContextImpl$$Lambda$33/1101004004.run(Unknown Source)
at io.vertx.core.impl.TaskQueue.run(TaskQueue.java:76)
at io.vertx.core.impl.TaskQueue$$Lambda$26/1213216872.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
And here is source-code:
package com.example.project_name
import com.google.api.gax.rpc.ApiException
import com.google.cloud.pubsub.v1.*
import com.google.pubsub.v1.ProjectSubscriptionName
import com.google.pubsub.v1.ProjectTopicName
import com.google.pubsub.v1.PubsubMessage
import com.google.pubsub.v1.PushConfig
import io.vertx.core.*
import java.util.concurrent.LinkedBlockingDeque
class MainVerticle : MessageReceiver, AbstractVerticle() {
private val projectId = "gcs-project-id"
private val topicId = "vertx"
private val topic: ProjectTopicName = ProjectTopicName.of(projectId, topicId)
private val subscriptionId = "kotlin"
private val subscription = ProjectSubscriptionName.of(projectId, subscriptionId)
private val messages = LinkedBlockingDeque<PubsubMessage>()
private lateinit var subscriber: Subscriber
override fun receiveMessage(message: PubsubMessage, consumer: AckReplyConsumer) {
messages.offer(message)
consumer.ack()
}
override fun start() {
vertx.executeBlocking<Void>({
try {
println("Listening to messages on $subscriptionId:")
subscriber.awaitRunning()
while (true) {
val message = messages.take()
println("Message Id: ${message.messageId} Data: ${message.data.toStringUtf8()}")
}
} finally {
subscriber.stopAsync()
it.complete()
}
}, { println("done, ${it.cause()}") })
}
override fun init(vertx: Vertx?, context: Context?) {
super.init(vertx, context)
try {
createTopic()
subscribeTopic()
subscriber = Subscriber.newBuilder(subscription, this).build()
subscriber.startAsync()
} catch (e: ApiException) {
// example : code = ALREADY_EXISTS(409) implies topic already exists
println("Failed: $e")
}
}
override fun stop(stopFuture: Future<Void>?) {
super.stop(stopFuture)
try {
deleteSub()
deleteTopic()
} catch (e: ApiException) {
println("Failed: $e")
} finally {
subscriber.stopAsync()
stopFuture!!.complete()
}
}
private fun createTopic() { // expects 1 arg: <topic> to create
println("Creating topic ${topic.project}:${topic.topic}.")
TopicAdminClient.create().use { topicAdminClient -> topicAdminClient.createTopic(topic) }
println("Topic ${topic.project}:${topic.topic} successfully created.")
}
private fun subscribeTopic() { // expects 2 args: <topic> and <subscription>
println("Creating subscription ${subscription.project}:${subscription.subscription}.")
SubscriptionAdminClient.create().use { it.createSubscription(subscription, topic, PushConfig.getDefaultInstance(), 0) }
println("Subscription ${subscription.project}:${subscription.subscription} successfully created.")
}
private fun deleteTopic() {
println("Deleting topic ${topic.project}:${topic.topic}.")
TopicAdminClient.create().use { it.deleteTopic(topic) }
println("Topic ${topic.project}:${topic.topic} successfully deleted.")
}
private fun deleteSub() { // expects 1 arg: <subscription> to delete
println("Deleting subscription ${subscription.project}:${subscription.subscription}.")
SubscriptionAdminClient.create().use { it.deleteSubscription(subscription) }
println("Subscription ${subscription.project}:${subscription.subscription} successfully deleted.")
}
}
fun main(vararg args: String) {
Vertx.vertx().deployVerticle(MainVerticle(), DeploymentOptions().apply {
isWorker = true
})
}
I am clearly missing something. Also if you have a better approach that can integrate/unify Google’s PubSub library (that has its own async loop) with Vert.X I’d be happy to hear over my primitive example approach.
The problem is with your while loop.
"Blocking" in this case does not mean that you can just keep running forever.
Your call to it.complete() is never reached, and at some point Vert.x will complain about that.
See the manual on Running blocking code, specifically the WARNING section.
To solve your problem, you will need to schedule your calls to messages.take() in one way or another, for example using setPeriodic. Inside the interval handler, empty your queue with executeBlocking, then give back control by calling complete(), either before or after you have scheduled the processing of the messages, depending if you care about the result.

tokbox : Subscriber time out error on Safari

Using opentok.js v2,  the video channel works fine with Chrome and Firefox . The opentok version used is from this link: https://static.opentok.com/v2/js/opentok.min.js
But it doesn't work with safari 11.0.3.
On session's stream created event, it generates following error message "The stream was unable to connect due to a network error. Make sure your connection isnt blocked by a firewall"
The publisher is published successfully i.e session.publish(..) works fine.
The code below is used to make a video call:
this.session=OT.initSession(this.apiKey, this.sessionId);
this.session.on({
streamCreated: (event) => {
 
this.session.subscribe(event.stream, 'subscriber');
},
streamDestroyed: (event) => {
console.log(`Stream ${event.stream.name} ended because ${event.reason}`);
}
});
this.session.connect(this.token, () => {
this.publisher=OT.initPublisher('publisher');
this.session.publish(this.publisher);
});
}
 
Other exceptions in console generated by opentok.js are as follows: 
[Error] OT.exception :: title: undefined (1554) msg: OT.Subscriber PeerConnection Error: OT.Subscriber failed to subscribe to a stream in a reasonable amount of time
error
_exceptionHandler (vendor.js:150924)
handleJsException (vendor.js:151002)
onPeerConnectionFailure (vendor.js:162673)
(anonymous function) (vendor.js:162414)
onInvokeTask (vendor.js:4239)
runTask (polyfills.js:3:10225)
invokeTask (polyfills.js:3:16182)
n (polyfills.js:2:31400)
[Error] OT_ICE_WORKFLOW_FAILED: ICEWorkflow: Subscriber PeerConnection with connection (not found) failed: OT.Subscriber failed to subscribe to a stream in a reasonable amount of time
error
dispatchOTError (vendor.js:159161)
(anonymous function) (vendor.js:160080)
handleThisOnce (vendor.js:137437)
(anonymous function) (vendor.js:137675)
onInvokeTask (vendor.js:4239)
runTask (polyfills.js:3:10225)
invokeTask (polyfills.js:3:16182)
n (polyfills.js:2:31400)
[Error] OT.exception :: title: undefined (1554) msg: ICEWorkflow: Subscriber PeerConnection with connection (not found) failed: OT.Subscriber failed to subscribe to a stream in a reasonable amount of time
error
_exceptionHandler (vendor.js:150924)
handleJsException (vendor.js:151002)
dispatchOTError (vendor.js:159163)
(anonymous function) (vendor.js:160080)
handleThisOnce (vendor.js:137437)
(anonymous function) (vendor.js:137675)
onInvokeTask (vendor.js:4239)
runTask (polyfills.js:3:10225)
invokeTask (polyfills.js:3:16182)
n (polyfills.js:2:31400)
 
 
All the above errors  are generated only on Safari browser. 
You need to make sure you have created a Safari Project in your OpenTok Account Portal. More details at https://tokbox.com/developer/sdks/js/safari/
It looks like you're using a polyfills.js file. If that is the polyfill from Angular that includes zone.js then you will need to include the fix for RTCPeerConnections 'zone.js/dist/webapis-rtc-peer-connection' in your polyfills.js file.
import 'zone.js/dist/webapis-rtc-peer-connection';
You will also probably want to include the polyfill for getUserMedia. More details at https://github.com/angular/zone.js/issues/948#issuecomment-357558384

WebRTC to Gstreamer Bridge

I'm trying to stream audio from a browser to a gstreamer pipeline on a server.
I'm currently using Kurento, and modifying the Hello World example to try to connect an RTP Endpoint to the pipeline -- but am having trouble.
I know the media is getting there because when I swap in a Recording Endpoint, I get a valid recording.
The Kurento Node JS is:
pipeline.create("RtpEndpoint", {}, function(error, rtpEndpoint) {
if (error) {
console.log("Recorder problem");
return sendError(res, 500, error);
}
console.log("Creating WebRtcEndpoint");
pipeline.create('WebRtcEndpoint', function(error, webRtcEndpoint) {
if (error) {
return sendError(res, 500, error);
}
console.log("Processing sdpOffer at server and generating sdpAnswer");
webRtcEndpoint.processOffer(sdpOffer, function(error, sdpAnswer) {
if (error) {
webRtcEndpoint.release();
return sendError(res, 500, error);
}
console.log("Connecting loopback");
webRtcEndpoint.connect(webRtcEndpoint, function(error) {
if(error){
webRtcEndpoint.release();
return sendError(res, 500, error);
}
console.log("Sending sdpAnswer to client");
console.log(sdpAnswer);
webRtcEndpoint.connect(rtpEndpoint, function(error) {
if(error) {
webRtcEndpoint.release();
return sendError(res, 500, error);
}
rtpEndpoint.generateOffer(function(error, offer) {
fs.writeFile('/tmp/test.sdp',offer);
console.log("RTP OFFER GENERATED.");
});
});
res.type('application/sdp');
res.send(sdpAnswer);
});
});
});
});
and my GStreamer pipeline is:
gst-launch-1.0 -vvvv filesrc location=/tmp/test.sdp ! sdpdemux ! decodebin ! autovideosink
which returns
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Got context from element 'autovideosink0-actual-sink-glimage': gst.gl.GLDisplay=context, gst.gl.GLDisplay=(GstGLDisplay)"\(GstGLDisplayX11\)\ gldisplayx11-0";
Setting pipeline to PLAYING ...
New clock: GstSystemClock
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstUDPSrc:udpsrc0: timeout = 10000000000
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstUDPSrc:udpsrc2: timeout = 10000000000
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstRtpBin:rtpbin0/GstRtpSession:rtpsession0.GstPad:send_rtcp_src: caps = application/x-rtcp
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstRtpBin:rtpbin0.GstGhostPad:send_rtcp_src_0: caps = application/x-rtcp
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstUDPSink:udpsink0.GstPad:sink: caps = application/x-rtcp
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstRtpBin:rtpbin0.GstGhostPad:send_rtcp_src_0.GstProxyPad:proxypad4: caps = application/x-rtcp
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstRtpBin:rtpbin0/GstRtpSession:rtpsession1.GstPad:send_rtcp_src: caps = application/x-rtcp
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstRtpBin:rtpbin0.GstGhostPad:send_rtcp_src_1: caps = application/x-rtcp
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstUDPSink:udpsink1.GstPad:sink: caps = application/x-rtcp
/GstPipeline:pipeline0/GstSDPDemux:sdpdemux0/GstRtpBin:rtpbin0.GstGhostPad:send_rtcp_src_1.GstProxyPad:proxypad7: caps = application/x-rtcp
ERROR: from element /GstPipeline:pipeline0/GstSDPDemux:sdpdemux0: Could not read from resource.
Additional debug info:
gstsdpdemux.c(1213): gst_sdp_demux_handle_message (): /GstPipeline:pipeline0/GstSDPDemux:sdpdemux0:
Could not receive any UDP packets for 10.0000 seconds, maybe your firewall is blocking it.
Execution ended after 0:00:10.062018001
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...
It doesnt work on FFPMEG, VLC, etc -- results are similar to "Attempt 5.3" here: https://altanaitelecom.wordpress.com/2015/02/26/continue-streaming-broadcasting-live-video-call-to-non-webrtc-supported-browsers-and-media-players/
I don't think theres a firewall issue as the pipeline and kurento instance are on the same virtual machine (which has no firewall) -- and the recording endpoint works. Is it being linked badly? Is there an easier way?
Using RtpEndpoint is tricky because you need to complete de SDP negotiation. This means that somewhere after the
rtpEndpoint.generateOffer(...
you should be invoking
rtpEndpoint.processAnswer(sdpAnswer, ...)
The tricky part is that you need to obtain the sdpAnswer from your gstreamer pipeline and this is not trivial if you want to it just using gst-launch. Probably your best option is to write a small programm creating the pipeline and generating the sdpAnswer so that you can give it back to the rtpEndpoint through your signaling mechanism.

FTDI via libusb error EPIPE

I'm trying to work with an FTDI-based USB device and I'm getting a -32 (EPIPE) error:
08-06 16:32:16.328: WARN/System.err(15547): ftdi_usb_open_dev()
08-06 16:32:16.328: WARN/System.err(15547): usb_detach_kernel_driver_np()libusb: 0.029116 debug [libusb_detach_kernel_driver] interface 0
08-06 16:32:16.328: WARN/System.err(15547): ftdi claim interface ...
08-06 16:32:16.328: WARN/System.err(15547): libusb-compat debug: usb_claim_interface: interface 0
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.030246 debug [libusb_claim_interface] interface 0
08-06 16:32:16.328: WARN/System.err(15547): claiming interface using fd = 4
08-06 16:32:16.328: WARN/System.err(15547): ftdi_usb_reset ...
08-06 16:32:16.328: WARN/System.err(15547): libusb-compat debug: usb_control_msg: RQT=40 RQ=0 V=0 I=0 len=0 timeout=300
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.031222 debug [libusb_get_next_timeout] next timeout in 0.300000s
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.031527 debug [libusb_handle_events_timeout_completed] doing our own event handling
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.032046 debug [handle_events] poll() 2 fds with timeout in 300ms
08-06 16:32:16.328: WARN/System.err(15547): libusb: 0.033023 debug [handle_events] poll() returned 1
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.033389 debug [reap_for_handle] urb type=2 status=-32 transferred=0
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.033755 debug [handle_control_completion] handling completion status -32
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.034091 debug [handle_control_completion] unsupported control request
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.034366 debug [usbi_handle_transfer_completion] transfer 0x2915e0 has callback 0x5ccb4
08-06 16:32:16.338: WARN/System.err(15547): libusb: 0.034732 debug [ctrl_transfer_cb] actual_length=0
The USB request seems to be exactly as it is required according to FTDI Chip Commands.
FTDI context is initialized without errors, usb_dev is not null and it seems to be okay. The cable is okay as I can use it for uploading Arduino sketches to Duemilanove (FTDI) boards.
So I'm completely stuck.. What should I do?
My code
struct ftdi_context *ftdi_ctx;
struct usb_device *dev;
usb_dev_handle *udev;
// ...
ftdi_ctx = ftdi_new();
if (ftdi_ctx == NULL) {
fprintf(stderr, "error init ftdi context\n");
return 1;
}
ftdi_ctx->usb_write_timeout = 0;
ftdi_ctx->usb_read_timeout = 0;
// ...
udev = usb_open(dev);
int ret = ftdi_usb_open_dev(ftdi_ctx, dev, udev);
if (ret < 0) {
fprintf(stderr, "error opening ftdi device\n");
return ret;
}
ftdi_usb_open_dev() is slightly modified to get ready usb_device and don't do usb_open inside:
libftdi-0.1 code (ftdi.c):
int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev, struct usb_dev_handle *usb_dev)
{
int detach_errno = 0;
int config_val = 1;
fprintf(stderr, "ftdi_usb_open_dev()\n");
if (ftdi == NULL) {
fprintf(stderr, "ftdi context invalid\n");
ftdi_error_return(-8, "ftdi context invalid");
}
// 4ntoine (no need to open device if usb_dev is already passed)
if (usb_dev == NULL) {
if (!(ftdi->usb_dev = usb_open(dev)))
ftdi_error_return(-4, "usb_open() failed");
} else {
ftdi->usb_dev = usb_dev;
}
#ifdef LIBUSB_HAS_GET_DRIVER_NP
// Try to detach ftdi_sio kernel module.
// Returns ENODATA if driver is not loaded.
//
// The return code is kept in a separate variable and only parsed
// if usb_set_configuration() or usb_claim_interface() fails as the
// detach operation might be denied and everything still works fine.
// Likely scenario is a static ftdi_sio kernel module.
fprintf(stderr, "detaching kernel driver... \n");
if (ftdi->module_detach_mode == AUTO_DETACH_SIO_MODULE)
{
fprintf(stderr, "usb_detach_kernel_driver_np() ...\n");
if (usb_detach_kernel_driver_np(ftdi->usb_dev, ftdi->interface) != 0 && errno != ENODATA) {
fprintf(stderr, "failed to detach\n");
detach_errno = errno;
}
}
#endif
fprintf(stderr, "ftdi claim interface ...\n");
if (usb_claim_interface(ftdi->usb_dev, ftdi->interface) != 0)
{
fprintf(stderr, "failed to claim interface\n");
ftdi_usb_close_internal (ftdi);
if (detach_errno == EPERM)
{
ftdi_error_return(-8, "inappropriate permissions on device!");
}
else
{
ftdi_error_return(-5, "unable to claim usb device. Make sure the default FTDI driver is not in use");
}
}
fprintf(stderr, "ftdi claimed interface\n");
fprintf(stderr, "ftdi_usb_reset ...\n");
if (ftdi_usb_reset (ftdi) != 0)
{
ftdi_usb_close_internal (ftdi);
ftdi_error_return(-6, "ftdi_usb_reset failed");
}
I've tested it with another FTDI-board (Arduino Nano v3) and still the same error, so the problem is not in the board most likely...
I've tested it on another Android device with USB host support too and another Android OS version (4.0.x) and still the same error...
Is your host system Windows or Linux?
It seems that the device failed to respond to the control message issued by ftdi_usb_reset(). And the ftdi_usb_reset() is actually called by ftdi_usb_open_dev().
If checking the libftdi source code:
http://www.intra2net.com/en/developer/libftdi/documentation/ftdi_8c_source.html#l00522
We found that it shall return -6 if ftdi_usb_reset() fails. The entire error log is not posted here, so I wonder if it is what truly happened finally. And maybe there are more interesting things to go see there.
Maybe showing your code here can help get a better understanding. :)
If possible on your side, when trying to do the same thing with D2XX driver provided by ftdichip.com, will the result be the same?
Correct me if my understanding is wrong: You are developing native code that works on Android (the underlying Linux system) that calls libftdi and libusb, right? And I assume the purpose is to use Android devices through libusb without root needed?
A little search on Google tells me that there is no "official" Android port for libusb. Some platform works with libusb while some cannot. People are having different kinds of feedbacks.
So if going back to basics, say, using only the functions in libusb, without the libftdi code you've modified, can you perform device open, close, and send control message to your FTDI device through basic libusb functions?
Or, if possible, try with an unmodified libftdi. Will it to the job it is supposed to do?
And by the way, why libftdi0.1? I knew it should be version 1.0 by now. Older versions could be buggy...
I just try to provide something that is worth trying. It could be a libusb problem, a libftdi problem, or simply a problem of the sequence how you operate the device. So if not sure where it goes wrong, then break them down to pieces and identify what are correct would be what I would try.