Translate Kotlin to Java BLE callback - java

Im trying to translate this part of a code to Java, i understand its waiting for a callback from a BLE action, if returns any data will be added to statusReport, only issue is that it seems that is doing a loop somewhere because in the real application gets this callback multiple times but on my side i only get one response.
private val statusReportCallback = DataReceivedCallback { _, data -> convertByteArrayToASCII(data.value)?.let { Endpoint.addToStatusReport(it)
if (nextWillBeICCID) iccid = it.also { notifyDeviceEvent(EventType.ICCID) }.also { nextWillBeICCID = false }
when (it) {
"power off" -> Endpoint.commsTestInProgress.set(false)
"ICCID:" -> nextWillBeICCID = true
"POST: Success" -> Endpoint.onServerConnected.value = Event(true)
}
} }

Related

Get the receiver's number from an SMS on Android

I am using the below code to get originatingAddress (the sender's number).
import android.provider.Telephony.Sms.Intents.getMessagesFromIntent
fun getFullMessage(messageParts: Array<SmsMessage>): CompleteSmsMessage {
messageParts = getFullMessage(getMessagesFromIntent(intent))
messageParts.last().also { part ->
return CompleteSmsMessage(
originatingAddress = part.originatingAddress,
body = messageParts
.map { it.messageBody }
.reduce { acc, body -> acc + body }
)
}
}
Since I have multiple SIM slots on my phone, I'd like to get the receiver's number as well. I couldn't find any relevant document here: https://developer.android.com/reference/android/telephony/SmsMessage#getDisplayOriginatingAddress()
Is it possible to get the receiver's number? How?
The incoming intent contains subscription variable, this is the SIM slot:
val slotId = intent.getIntExtra("subscription", -1)

How to implement ZenPolicy rules?

Does anyone here know anything about ZenPolicy and how to implement a rule? I am trying to replicate the Do Not Disturb setting where calls are not allowed through, but exceptions are possible, eg. Media sounds, Touch sounds etc. I have managed to disallow calls but when I toggle the exceptions settings (from my app), this reverts to "starred contacts only".
I am attaching a screenshot of what I am trying to replicate in my app. Here is the code I am using so far:
3 -> {
notificationManager.setInterruptionFilter(
NotificationManager.INTERRUPTION_FILTER_PRIORITY
)
notificationManager.setNotificationPolicy(
NotificationManager.Policy(
PEOPLE_TYPE_NONE,
PRIORITY_SENDERS_ANY,
PRIORITY_SENDERS_ANY
)
)
}
I have also looked through: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/service/notification/ZenModeConfig.java;drc=master;l=754 and https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/service/notification/ZenPolicy.java
and came up with this function, but it doesn't do anything...:
fun zenPolicyBuilder(): ZenPolicy.Builder {
val builder = ZenPolicy.Builder()
val calls = PRIORITY_CATEGORY_CALLS
val repeatCallers = PRIORITY_CATEGORY_REPEAT_CALLERS
val alarms = PRIORITY_CATEGORY_ALARMS
val media = PRIORITY_CATEGORY_MEDIA
val system = PRIORITY_CATEGORY_SYSTEM
val events = PRIORITY_CATEGORY_EVENTS
val reminders = PRIORITY_CATEGORY_REMINDERS
return when {
calls != ZenPolicy.PEOPLE_TYPE_UNSET -> {
builder.allowCalls(PEOPLE_TYPE_NONE)
}
repeatCallers != ZenPolicy.STATE_UNSET -> {
builder.allowRepeatCallers(repeatCallers == ZenPolicy.STATE_ALLOW)
}
alarms != ZenPolicy.STATE_UNSET -> {
builder.allowAlarms(alarms == ZenPolicy.STATE_ALLOW)
}
media != ZenPolicy.STATE_UNSET -> {
builder.allowMedia(media == ZenPolicy.STATE_ALLOW)
}
system != ZenPolicy.STATE_UNSET -> {
builder.allowSystem(system == ZenPolicy.STATE_ALLOW)
}
events != ZenPolicy.STATE_UNSET -> {
builder.allowEvents(events == ZenPolicy.STATE_ALLOW)
}
reminders != ZenPolicy.STATE_UNSET -> {
builder.allowReminders(reminders == ZenPolicy.STATE_ALLOW)
}
else -> builder
}
}
For anyone who might be interested in future, the first code snippet that I posted actually works fine. The problem was coming from another part of my code which was interfering with this.

ZMQ missing events being propagated in jeromq scala

I am new to ZeroMQ and seem to be losing messages in a loop in my begin() method.
I'm wondering if I am missing a piece where I am not queuing messages or something?
When I cause an event on my publisher, that sends two messages to my subscriber with a small gap in between, I seem not to be getting the second message that is relayed. What am I missing?
class ZMQSubscriber[T <: Transaction, B <: Block](
socket: InetSocketAddress,
hashTxListener: Option[HashDigest => Future[Unit]],
hashBlockListener: Option[HashDigest => Future[Unit]],
rawTxListener: Option[Transaction => Future[Unit]],
rawBlockListener: Option[Block => Future[Unit]]) {
private val logger = BitcoinSLogger.logger
def begin()(implicit ec: ExecutionContext) = {
val context = ZMQ.context(1)
// First, connect our subscriber socket
val subscriber = context.socket(ZMQ.SUB)
val uri = socket.getHostString + ":" + socket.getPort
//subscribe to the appropriate feed
hashTxListener.map { _ =>
subscriber.subscribe(HashTx.topic.getBytes(ZMQ.CHARSET))
logger.debug("subscribed to the transaction hashes from zmq")
}
rawTxListener.map { _ =>
subscriber.subscribe(RawTx.topic.getBytes(ZMQ.CHARSET))
logger.debug("subscribed to raw transactions from zmq")
}
hashBlockListener.map { _ =>
subscriber.subscribe(HashBlock.topic.getBytes(ZMQ.CHARSET))
logger.debug("subscribed to the hashblock stream from zmq")
}
rawBlockListener.map { _ =>
subscriber.subscribe(RawBlock.topic.getBytes(ZMQ.CHARSET))
logger.debug("subscribed to raw block")
}
subscriber.connect(uri)
subscriber.setRcvHWM(0)
logger.info("Connection to zmq client successful")
while (true) {
val notificationTypeStr = subscriber.recvStr(ZMQ.DONTWAIT)
val body = subscriber.recv(ZMQ.DONTWAIT)
Future(processMsg(notificationTypeStr, body))
}
}
private def processMsg(topic: String, body: Seq[Byte])(implicit ec: ExecutionContext): Future[Unit] = Future {
val notification = ZMQNotification.fromString(topic)
val res: Option[Future[Unit]] = notification.flatMap {
case HashTx =>
hashTxListener.map { f =>
val hash = Future(DoubleSha256Digest.fromBytes(body))
hash.flatMap(f(_))
}
case RawTx =>
rawTxListener.map { f =>
val tx = Future(Transaction.fromBytes(body))
tx.flatMap(f(_))
}
case HashBlock =>
hashBlockListener.map { f =>
val hash = Future(DoubleSha256Digest.fromBytes(body))
hash.flatMap(f(_))
}
case RawBlock =>
rawBlockListener.map { f =>
val block = Future(Block.fromBytes(body))
block.flatMap(f(_))
}
}
}
}
So this seems to have been solved by using a ZMsg.recvMsg() in the while-loop instead of
val notificationTypeStr = subscriber.recvStr(ZMQ.DONTWAIT)
val body = subscriber.recv(ZMQ.DONTWAIT)
I'm not sure why this works, but it does. So here is what my begin method looks like now
while (run) {
val zmsg = ZMsg.recvMsg(subscriber)
val notificationTypeStr = zmsg.pop().getString(ZMQ.CHARSET)
val body = zmsg.pop().getData
Future(processMsg(notificationTypeStr, body))
}
Future.successful(Unit)
}
What am I missing?
How the blocking v/s non-blocking modus operandi work :
The trick is in the (non-)blocking mode of the respective call to the .recv() method.
A second call to the subscriber.recv( ZMQ.DONTWAIT )-method thus returns immediately, so your second part, ( the body ) may and will legally contain nothing, even though your promise stated a pair of messages was indeed dispached from the publisher-side ( a pair of .send() method calls - one may also object, there are chances the sender was actually sending just one message, in a multi-part fashion - MCVE-code is not specific on this part ).
So, once you have moved your code from non-blocking mode ( in the O/P ) into a principally blocking-mode ( which locked / sync-ed the further flow of the code with the external event of an arrival of any plausibly formatted message, not returning earlier ), in:
val zmsg = ZMsg.recvMsg(subscriber) // which BLOCKS-till-a-1st-zmsg-arrived
both the further processed .pop()-ed parts just unload the components ( ref. the remark on actual ZMsg multi-part structure actually sent by the published-side, presented above )
Safety next :unlimited alloc-s v/s a mandatory blocking / dropping messages ?
the code surprised me on several points. Besides a rather very "late" call to the .connect()-method, compared to all the previous socket-archetype detailed settings ( that normally get arranged "after" a request to setup a connection ). While this may work fine, as intended, yet it exposes even tighter ( smaller ) time-window for the .Context()-instance to setup and (re-)negotiate all the relevant connection-details so as to become RTO.
One particular line attracted my attention: subscriber.setRcvHWM( 0 ) this is a version-archetype dependent trick. Yet, the value of zero causes an application to become vulnerable and I would not advise doing so in any production-grade application.

Direct messaging communication failure over BLE between Android and Garmin FR230 (SDK 1.3.x)

Hi fellow Garmin developers,
I have been trying to develop a direct messaging communication setup over BLE between my Android App and my connectIQ app (on Garmin Forerunner 230, SDK version 1.3.x). The goal here is that the Android app is collecting some data, and then pushing it to the watch app.
Following the details on the developer site, I have managed to get this to work, but there are a lot of dropped messages that don't get sent, and the watch receives fewer values than what is being sent.
On Android, I get this status (ConnectIQ.IQMessageStatus) = FAILURE_DURING_TRANSFER in my debug statements. '240' is the data being sent.
D/GarminMessenger: onMessageStatus: Message: 240, device: Forerunner 230, FAILURE_DURING_TRANSFER
This is my app code on the garmin:
SampleApp.mc
using Toybox.Application as App;
using Toybox.Communications as Comm;
using Toybox.WatchUi as Ui;
using Toybox.System as Sys;
var mailMethod;
var crashOnMessage = false;
var msg;
class SampleApp extends App.AppBase {
function initialize() {
AppBase.initialize();
Sys.println("app-initialize()");
msg = "0";
mailMethod = method(:onMail);
Comm.setMailboxListener(mailMethod);
Sys.println("app-initialize(): mail box listener has been set");
}
// onStart() is called on application start up
function onStart(state) {
System.println("app-onStart()");
}
// Return the initial view of your application here
function getInitialView() {
Sys.println("app-getInitialView()");
return [ new SampleAppView() ];
}
function onMail(mailIter) {
var mail = mailIter.next();
while(mail!=null) {
Sys.println("app-onMail: received - "+mail);
message = mail.toString();
Ui.requestUpdate();
mail = mailIter.next();
}
Comm.emptyMailbox();
}
// onStop() is called when your application is exiting
function onStop(state) {
System.println("app-onStop()");
}
}
class CommListener extends Comm.ConnectionListener {
function initialize() {
Comm.ConnectionListener.initialize();
sys.println("commlistener-initialize");
}
function onComplete() {
Sys.println("commlistener-onComplete: Transmit Complete");
}
function onError() {
Sys.println("commlistener-onError: Transmit Failed");
}
}
Any ideas on what could be causing this issue? I am performing all the necessary checks on the Android side to verify if the Garmin watch is paired and connected (&the app is open).
One reason this could be happening is that I am trying to send 1-2 data values (each with a ConnectIQ.sendMessage()) every second, so perhaps the Garmin device/BLE module does not support communication at that rate?
Thanks in advance for solutions and suggestions.
I think that the Connect messaging system just gets into some broken state and then no messages will go through.
What you could try is to set up the Mailbox listener in onStart method instead of initialize.
Also there is a new method to make the message reading a lot easier. It is still largely undocumented, but I got a word it will be documented with the next SDK release. However, it is already working on every ConnectIQ watch.
The method is:
Comm.registerForPhoneAppMessages(method(:onMsg));
where in your callback method you do:
function onMsg(msg) {
handleIncomingMessage(msg.data.toString());
}
or something similar. The input object msg is of class
Toybox::Communications::Message
probably (this is not documented yet).
So I posted a similar question on the Garmin developer forum here, and got a partial answer to my problem. Posting a summary from there.
What I was hoping to implement was something life the following:
Assuming the messages from Android are 1, 2, 3, 4, 5: I would like the
app to do update the UI as the messages are received, in real-time like this:
app-onMail: received - 1
//update the UI
app-onMail: received - 2
//update the UI
app-onMail: received - 3
//update the UI
app-onMail: received - 4
//update the UI
app-onMail: received - 5
//update the UI
Instead, this happens
app-onMail: received - 1
app-onMail: received - 2
app-onMail: received - 3
app-onMail: received - 4
app-onMail: received - 5
//update the UI
//update the UI
//update the UI
//update the UI
//update the UI
THE ANSWER
The framework polls to see if there are new, unread mail messages. If there are any, it invokes the application onMail() callback which consumes each message from the queue, and repeatedly sets a flag that indicates the UI needs to update. After the call returns, the framework checks the flag to see if the UI needs to be updated, and if so it calls onUpdate() for the active view.
As such, I could only display every message if I send messages from Android at 5sec intervals. I could not find a way to receive and display data at higher rates due to its message polling frequency.
My responder suggested maintaining a queue of mail items (or just a counter) and then handling the mail items between draws, like this:
class MyApp extends App.AppBase
{
hidden var _M_messages;
hidden var _M_count;
function initialize() {
AppBase.initialize();
_M_messages = new [10];
_M_count = 0;
}
function getInitialView() {
return [ new MyView() ];
}
function onStart(params) {
Comm.setMailboxListener(self.method(:onMail));
}
function onStop(params) {
Comm.setMailboxListener(null);
}
function onMail(mailIter) {
var mail = mailIter.next();
while (mail != null) {
// only track up to 10 messages
if (_M_count < 10) {
_M_messages[_M_count] = mail;
++_M_count;
}
else {
break;
}
mail = mailIter.next();
}
Comm.emptyMailbox();
startProcessingMessages();
}
hidden function startProcessingMessages() {
if (_M_timer == null) {
_M_timer = new Timer.Timer();
_M_timer.start(self.method(:processOneMessage), 250, true);
}
}
hidden function stopProcessingMessages() {
if (_M_timer != null) {
_M_timer.stop();
_M_timer = null;
}
}
function getMessageCount() {
return _M_messages;
}
function processOneMessage() {
if (_M_count != 0) {
--_M_count;
var mail = _M_messages[_M_count];
_M_messages[_M_count] = null;
// process the message here
Ui.requestUpdate();
if (_M_count == 0) {
stopProcessingMessages();
}
}
}
}
class MyView extends Ui.View
{
hidden var _M_app;
function initialize(app) {
View.initialize();
_M_app = app;
}
function onUpdate(dc) {
var mailMessages = _M_app.getMessageCount();
// draw the number of mail messages
}
}

Test WebSocket in PlayFramework

I have a WebSocket in my Play application and I want to write a test for it, but I couldn't find any example on how to write such a test. I found a discussion in the play-framework Google group but there has been no activity recently.
So, are there any ideas on how to test WebSocket's in a Java test?
You can retrieve underlying Iteratee,Enumerator and test them directly. This way you don't need to use a browser. You need akka-testkit though, to cope with asynchronous nature of iteratees.
A Scala example:
object WebSocket extends Controller {
def websocket = WebSocket.async[JsValue] { request =>
Future.successful(Iteratee.ignore[JsValue] -> Enumerator.apply[JsValue](Json.obj("type" -> "error")))
}
}
class WebSocketSpec extends PlaySpecification {
"WebSocket" should {
"respond with error packet" in new WithApplication {
val request = FakeRequest()
var message: JsValue = null
val iteratee = Iteratee.foreach[JsValue](chunk => message = chunk)(Akka.system.dispatcher)
Controller.websocket().f(request)(Enumerator.empty[JsValue],iteratee)
TestKit.awaitCond(message == Json.obj("type" -> "error"), 1 second)
}
}
}
I test WebSockets code using Firefox:
https://github.com/schleichardt/stackoverflow-answers/commit/13d5876791ef409e092e4a097f54247d851e17dc#L8R14
For Java it works similar replacing 'HTMLUNIT' with 'FIREFOX': http://www.playframework.com/documentation/2.1.x/JavaFunctionalTest
Chrome provides a plugin to test websocket service.
Edit
So using the plugin (as shown in picture below) you can provide websocket url and the request data and send message to service. And message log shows the message sent from client and also service response.
Assume that you have a websocket library that returns the Future[Itearatee[JsValue, Unit], Enumerator[JsValue]] your controller uses
trait WSLib {
def connect: Future[Itearatee[JsValue, Unit], Enumerator[JsValue]]
}
And you wanna test this library.
Here is a context you can use:
trait WebSocketContext extends WithApplication {
val aSecond = FiniteDuration(1, TimeUnit.SECONDS)
case class Incoming(iteratee: Iteratee[JsValue, Unit]) {
def feed(message: JsValue) = {
iteratee.feed(Input.El(message))
}
def end(wait: Long = 100) = {
Thread.sleep(wait) //wait until all previous fed messages are handled
iteratee.feed(Input.EOF)
}
}
case class OutGoing(enum: Enumerator[JsValue]) {
val messages = enum(Iteratee.fold(List[JsValue]()) {
(l, jsValue) => jsValue :: l
}).flatMap(_.run)
def get: List[JsValue] = {
Await.result(messages, aSecond)
}
}
def wrapConnection(connection: => Future[Iteratee[JsValue, Unit], Enumerator[JsValue]]): (Incoming, OutGoing) = {
val (iteratee, enumerator) = Await.result(conn, aSecond)
(Incoming(iteratee), OutGoing(enumerator))
}
}
Then your tests can be written as
"return all subscribers when asked for info" in new WebSocketContext {
val (incoming, outgoing) = wrapConnection(myWSLib.connect)
incoming.feed(JsObject("message" => "hello"))
incoming.end() //this closes the connection
val responseMessages = outgoing.get //you only call this "get" after the connection is closed
responseMessages.size must equalTo(1)
responseMessages must contain(JsObject("reply" => "Hey"))
}
Incoming represent the messages coming from the client side, while the outgoing represents the messages sent from the server. To write test, you first feed in the incoming messages from incoming and then close the connection by calling incoming.end, then you get the complete list of outgoing messages from the outgoing.get method.

Categories

Resources