Ionic Bluetooth BLE read message all the time - ionic-framework

I want read data from sensor by bluetooth all the time. I follow from documentation but I can't set my phone read data from sensor by bluetooth. First i connect mobile with sensor next I add notification by:
this.ble.startNotification(peripheral.id,SERVICE_UUID,
CHARACTERISTIC_UUID).subscribe(
data => {this.onChange(data);}
)
where onChane(data) is :
onChange(buffer :ArrayBuffer){
console.log("onChange method")
var data = new Float32Array(buffer);
console.log(data[0]); }
Next I
this.ble.read(peripheral.id,SERVICE_UUID,CHARACTERISTIC_UUID).then(
(data) => {this.onChange(data);},
(err) => {console.log(err);}
)
I have failed in this.ble.read. CHARACTERISTIC_UUID and SERVICE_UUID are const. What is wrong? How can I correct this that my phone received datas all the time?

If you're using notifications, you don't need to read the characteristic's value. Once you subscribe for notifications, the peripheral will notify you with the new value whenever the value changes. It looks like your onChange function does this.
If your characteristic supports the read property, you can optionally read the value. Look at the peripheral data returned to the connect success callback to see the characteristic properties.
Take a look at my Ionic BLE example code. The thermometer example connects to a peripheral, subscribes for notifications, and reads the value one time so IU can update the UI with the current value. See https://github.com/don/ionic-ble-examples/blob/d0acd2b47ea08011be4d1aa844c4f74426a22273/thermometer/src/pages/detail/detail.ts#L37-L55

Related

how to send hexadecimal data packets using Bluetooth in flutter

It's my first time using Dart and Flutter.
I want to send and receive data packets to some device.
I tried a lot of things through google but failed.
Please let me know how I can send it.
Please help me.
void sendData() async {
Uint8List list = new Uint8List(13);
list[0]=0x80;
list[1]=0x80;
list[2]=0xF0;
list[3]=0x7D;
list[4]=0x05;
list[5]=0x00;
list[6]=0x0E;
list[7]=0x01;
list[8]=0x70;
list[9]=0x70;
list[10]=127;
list[11]=0x80;
list[12]=0xF7;
print(list);
await _curPeripheral.discoverAllServicesAndCharacteristics();
_curPeripheral.writeCharacteristic(
"Service Uuid",
"Charactoristic Uuid",
Uint8List.fromList(list), false);
---- debug Console ----
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(22538): on native side observed method: discoverAllServicesAndCharacteristics
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(22538): on native side observed method: writeCharacteristicForDevice
There are multiple different libraries to choose if you want to send and receive data using Bluetooth Low Energy. For flutter you could use flutter_reactive_ble for example. The description includes usage examples.
Another library for flutter is flutter_blue.

How to send data back from iOS to Flutter?

I am trying to get iOS to send data back to flutter. More specifically the Control Center Media Controls. I am working on a music app and I can get data sent from Flutter to iOS, thus allowing it to be displayed in the Media Controls.
However, how would I get iOS to send data back on its own channel if I were to control play pause next previous? Basically have Flutter listen to iOS sending data.
Assuming that you are using Swift in your plugin (called XXX), you will have a SwiftXXXPlugin class, with a static register method. Move channel to become a static, rather than a local variable of register. Then create some static methods for your iOS to Dart methods and call invokeMethod like this:
channel.invokeMethod("someMethod", arguments: "someValue")
arguments is Any and could be anything that the channel knows how to encode, for example, byte array, String, int, double, etc. It can also encode lists and maps of the basic objects.
At the Dart end, you have XXX.dart. Add a static method called, for example, setHandler, and implement the implementations of the methods. You will need to call setHandler once before using the channel.
static setHandler() {
_channel.setMethodCallHandler(methodCallHandler);
}
static Future<dynamic> methodCallHandler(MethodCall methodCall) async {
switch (methodCall.method) {
case 'someMethod':
print(methodCall.arguments); // prints the argument - "someValue"
return null; // could return a value here
default:
throw PlatformException(code: 'notimpl', message: 'not implemented');
}
}

When using MDA, should you differentiate between idempotent and non-idempotent event handlers?

The question assumes the use of Event Sourcing.
When rebuilding current state by replaying events, event handlers should be idempotent. For example, when a user successfully updates their username, a UsernameUpdated event might be emitted, the event containing a newUsername string property. When rebuilding current state, the appropriate event handler receives the UsernameUpdated event and sets the username property on the User object to the newUsername property of the UsernameUpdated event object. In other words, the handling of the same message multiple times always yields the same result.
However, how does such an event handler work when integrating with external services? For example, if the user wants to reset their password, the User object might emit a PasswordResetRequested event, which is handled by a portion of code that issues a 3rd party with a command to send an SMS. Now when the application is rebuilt, we do NOT want to re-send this SMS. How is this situation best avoided?
There are two messages involved in the interaction: commands and events.
I do not regard the system messages in a messaging infrastructure the same as domain events. Command message handling should be idempotent. Event handlers typically would not need to be.
In your scenario I could tell the aggregate root 100 times to update the user name:
public UserNameChanged ChangeUserName(string username, IServiceBus serviceBus)
{
if (_username.Equals(username))
{
return null;
}
serviceBus.Send(new SendEMailCommand(*data*));
return On(new UserNameChanged{ Username = userName});
}
public UserNameChanged On(UserNameChanged #event)
{
_username = #event.UserName;
return #event;
}
The above code would result in a single event so reconstituting it would not produce any duplicate processing. Even if we had 100 UserNameChanged events the result would still be the same as the On method does not perform any processing. I guess the point to remember is that the command side does all the real work and the event side is used only to change the state of the object.
The above isn't necessarily how I would implement the messaging but it does demonstrate the concept.
I think you are mixing two separate concepts here. The first is reconstructing an object where the handlers are all internal methods of the entity itself. Sample code from Axon framework
public class MyAggregateRoot extends AbstractAnnotatedAggregateRoot {
#AggregateIdentifier
private String aggregateIdentifier;
private String someProperty;
public MyAggregateRoot(String id) {
apply(new MyAggregateCreatedEvent(id));
}
// constructor needed for reconstruction
protected MyAggregateRoot() {
}
#EventSourcingHandler
private void handleMyAggregateCreatedEvent(MyAggregateCreatedEvent event) {
// make sure identifier is always initialized properly
this.aggregateIdentifier = event.getMyAggregateIdentifier();
// do something with someProperty
}
}
Surely you wouldn't put code that talks to an external API inside an aggregate's method.
The second is replaying events on a bounded context which could cause the problem you are talking about and depending on your case you may need to divide your event handlers into clusters.
See Axon frameworks documentation for this point to get a better understanding of the problem and the solution they went with.
Replaying Events on a Cluster
TLDR; store the SMS identifier within the event itself.
A core principle of event sourcing is "idempotency". Events are idempotent, meaning that processing them multiple times will have the same result as if they were processed once. Commands are "non-idempotent", meaning that the re-execution of a command may have a different result for each execution.
The fact that aggregates are identified by UUID (with a very low percentage of duplication) means that the client can generate the UUIDs of newly created aggregates. Process managers (a.k.a., "Sagas") coordinate actions across multiple aggregates by listening to events in order to issue commands, so in this sense, the process manager is also a "client". Cecause the process manager issues commands, it cannot be considered "idempotent".
One solution I came up with is to include the UUID of the soon-to-be-created SMS in the PasswordResetRequested event. This allows the process manager to only create the SMS if it does not yet already exist, hence achieving idempotency.
Sample code below (C++ pseudo-code):
// The event indicating a password reset was successfully requested.
class PasswordResetRequested : public Event {
public:
PasswordResetRequested(const Uuid& userUuid, const Uuid& smsUuid, const std::string& passwordResetCode);
const Uuid userUuid;
const Uuid smsUuid;
const std::string passwordResetCode;
};
// The user aggregate root.
class User {
public:
PasswordResetRequested requestPasswordReset() {
// Realistically, the password reset functionality would have it's own class
// with functionality like checking request timestamps, generationg of the random
// code, etc.
Uuid smsUuid = Uuid::random();
passwordResetCode_ = generateRandomString();
return PasswordResetRequested(userUuid_, smsUuid, passwordResetCode_);
}
private:
Uuid userUuid_;
string passwordResetCode_;
};
// The process manager (aka, "saga") for handling password resets.
class PasswordResetProcessManager {
public:
void on(const PasswordResetRequested& event) {
if (!smsRepository_.hasSms(event.smsUuid)) {
smsRepository_.queueSms(event.smsUuid, "Your password reset code is: " + event.passwordResetCode);
}
}
};
There are a few things to note about the above solution:
Firstly, while there is a (very) low possibility that the SMS UUIDs can conflict, it can actually happen, which could cause several issues.
Communication with the external service is prevented. For example, if user "bob" requests a password reset that generates an SMS UUID of "1234", then (perhaps 2 years later) user "frank" requests a password reset that generates the same SMS UUID of "1234", the process manager will not queue the SMS because it thinks it already exists, so frank will never see it.
Incorrect reporting in the read model. Because there is a duplicate UUID, the read side may display the SMS sent to "bob" when "frank" is viewing the list of SMSes the system sent him. If the duplicate UUIDs were generated in quick succession, it is possible that "frank" would be able to reset "bob"s password.
Secondly, moving the SMS UUID generation into the event means you must make the User aggregate aware of the PasswordResetProcessManager's functionality (but not the PasswordResetManager itself), which increases coupling. However, the coupling here is loose, in that the User is unaware of how to queue an SMS, only that an SMS should be queued. If the User class were to send the SMS itself, you could run into the situation in which the SmsQueued event is stored while the PasswordResetRequested event is not, meaning that the user will receive an SMS but the generated password reset code was not saved on the user, and so entering the code will not reset the password.
Thirdly, if a PasswordResetRequested event is generated but the system crashes before the PasswordResetProcessManager can create the SMS, then the SMS will eventually be sent, but only when the PasswordResetRequested event is re-played (which might be a long time in the future). E.g., the "eventual" part of eventual consistency could be a long time away.
The above approach works (and I can see that it should also work in more complicated scenarious, like the OrderProcessManager described here: https://msdn.microsoft.com/en-us/library/jj591569.aspx). However, I am very keen to hear what other people think about this approach.

How do I call a method on my ServiceWorker from within my page?

I have a ServiceWorker registered on my page and want to pass some data to it so it can be stored in an IndexedDB and used later for network requests (it's an access token).
Is the correct thing just to use network requests and catch them on the SW side using fetch, or is there something more clever?
Note for future readers wondering similar things to me:
Setting properties on the SW registration object, e.g. setting self.registration.foo to a function within the service worker and doing the following in the page:
navigator.serviceWorker.getRegistration().then(function(reg) { reg.foo; })
Results in TypeError: reg.foo is not a function. I presume this is something to do with the lifecycle of a ServiceWorker meaning you can't modify it and expect those modification to be accessible in the future, so any interface with a SW likely has to be postMessage style, so perhaps just using fetch is the best way to go...?
So it turns out that you can't actually call a method within a SW from your app (due to lifecycle issues), so you have to use a postMessage API to pass serialized JSON messages around (so no passing callbacks etc).
You can send a message to the controlling SW with the following app code:
navigator.serviceWorker.controller.postMessage({'hello': 'world'})
Combined with the following in the SW code:
self.addEventListener('message', function (evt) {
console.log('postMessage received', evt.data);
})
Which results in the following in my SW's console:
postMessage received Object {hello: "world"}
So by passing in a message (JS object) which indicates the function and arguments I want to call my event listener can receive it and call the right function in the SW. To return a result to the app code you will need to also pass a port of a MessageChannel in to the SW and then respond via postMessage, for example in the app you'd create and send over a MessageChannel with the data:
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(event) {
console.log(event.data);
};
// This sends the message data as well as transferring messageChannel.port2 to the service worker.
// The service worker can then use the transferred port to reply via postMessage(), which
// will in turn trigger the onmessage handler on messageChannel.port1.
// See https://html.spec.whatwg.org/multipage/workers.html#dom-worker-postmessage
navigator.serviceWorker.controller.postMessage(message, [messageChannel.port2]);
and then you can respond via it in your Service Worker within the message handler:
evt.ports[0].postMessage({'hello': 'world'});
To pass data to your service worker, the above mentioned is a good way. But in case, if someone is still having a hard time implementing that, there is an other hack around for that,
1 - append your data to get parameter while you load service-worker (for eg., from sw.js -> sw.js?a=x&b=y&c=z)
2- Now in service worker, fetch those data using self.self.location.search.
Note, this will be beneficial only if the data you pass do not change for a particular client very often, other wise it will keep changing the loading url of service worker for that particular client and every time the client reloads or revisits, new service worker is installed.

How to get added record (not just the id) through publishAdd()-notification?

Each Sails.js model has the method publishAdd(). This notifies every listener, when a new record was added to a associated model.
This notification does not contain the newly created record. So I have to start another request from the client side to get the new record.
Is there a possibility, that Sails.js sends the new record with the notification, so I can reduce my request count?
Solution
I realized the accepted answer like that:
https://gist.github.com/openscript/7016c5fd8c5053b5e3a3
There's no way to get this record using the default publishAdd method. However, you can override that method and do the child record lookup in your implementation.
You can override publishAdd on a per-model basis by adding a publishAdd method to that model class, or override it for all models by adding the method to the config/models.js file.
I would start by copying the default publishAdd() method and then tweaking as necessary.
I know this is old, but I just had to solve this again, and didn't like the idea of dropping in duplicate code so if someone is looking for alternative, the trick is to update the model of the newly created record with an afterCreate: method.
Say you have a Game that you want to your Players to subscribe to. Games have notifications, a collection of text alerts that you only want players in the game to receive. To do this, subscribe to Game on the client by requesting it. Here I'm getting a particular game by calling game/gameId, then building my page based on what notifications and players are already on the model:
io.socket.get('/game/'+gameId, function(resData, jwres) {
let players = resData.players;
let notifications = resData.notifications;
$.each(players, function (k,v) {
if(v.id!=playerId){
addPartyMember(v);
}
});
$.each(notifications, function (k,v) {
addNotification(v.text);
});
});
Subscribed to game will only give the id's, as we know, but when I add a notification, I have both the Game Id and the notification record, so I can add the following to the Notification model:
afterCreate: function (newlyCreatedRecord, cb) {
Game.publishAdd(newlyCreatedRecord.game,'notifications',newlyCreatedRecord);
cb();}
Since my original socket.get subscribes to a particular game, I can publish only to those subscriber by using Game.publishAdd(). Now back on the client side, listen for the data coming back:
io.socket.on('game', function (event) {
if (event.attribute == 'notifications') {
addNotification(event.added.text);
}
});
The incoming records will look something like this:
{"id":"59fdd1439aee4e031e61f91f",
"verb":"addedTo",
"attribute" :"notifications",
"addedId":"59fef31ba264a60e2a88e5c1",
"added":{"game":"59fdd1439aee4e031e61f91f",
"text":"some messages",
"createdAt":"2017-11-05T11:16:43.488Z",
"updatedAt":"2017-11-05T11:16:43.488Z",
"id":"59fef31ba264a60e2a88e5c1"}}