Cannot read property 'bluetoothGattService' of undefined - bluetooth-lowenergy

I'm working on a Nativescript bluetooth app. I'm using the plugin: https://market.nativescript.org/plugins/nativescript-bluetooth
I'm able to scan for nearby devices and discover the services. I'm trying to attach a service/characteristic of 'write' to a button on my app. My function keeps returning an error when I click the button. It doesn't seem to even return the error inside the function. I've checked if my UUIDs are correct. Here is the CLI log:
Successfully transferred services-page.js.
Refreshing application...
Successfully synced application org.nativescript.myBLERegister on device FA72A03
04236.
JS: ---- Lollipop+ scanCallback result: {"type":"scanResult","UUID":"3A:01:3A:6A
:30:C6","name":null,"RSSI":-82,"state":"disconnected","advertisement":"Hv8GAAEJI
AImj9KgkqUJogD8bF6YsY/ZcTe3c0IL9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","ma
nufacturerId":6,"manufacturerData":{}}
JS: ---- Lollipop+ scanCallback result: {"type":"scanResult","UUID":"EB:FA:DB:31
:1B:A7","name":"Adafruit Bluefruit LE","RSSI":-64,"state":"disconnected","advert
isement":"AgEGAgoAEQaeytwkDuWp4JPzo7UBAEBuFglBZGFmcnVpdCBCbHVlZnJ1aXQgTEUAAAAAAA
AAAAAAAAAAAAA="}
JS: ---- Lollipop+ scanCallback result: {"type":"scanResult","UUID":"30:AA:13:7D
:1F:4C","name":null,"RSSI":-86,"state":"disconnected","advertisement":"Hv8GAAEJI
AK0AyV4bcITNKXNBmQPDloOKoOyCtp+sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","ma
nufacturerId":6,"manufacturerData":{}}
JS: !!&&&&***** Clicked item with index 1
JS: --- peri selected: EB:FA:DB:31:1B:A7
JS: Connecting to peripheral with UUID: EB:FA:DB:31:1B:A7
JS: ------- _MyGattCallback.onConnectionStateChange, status: 0, new state: 2
JS: ---- discovering services..
JS: ------- _MyGattCallback.onServicesDiscovered, status (0=success): 0
JS: ------- Peripheral connected: {"UUID":"EB:FA:DB:31:1B:A7","name":"Adafruit B
luefruit LE","state":"connected","services":[{"UUID":"1800","characteristics":[{
"UUID":"2a00","name":"2a00","properties":{"read":true,"write":true,"writeWithout
Response":false,"notify":false,"indicate":false,"broadcast":false,"authenticated
SignedWrites":false,"extendedProperties":false},"descriptors":[]},{"UUID":"2a01"
,"name":"2a01","properties":{"read":true,"write":false,"writeWithoutResponse":fa
lse,"notify":false,"indicate":false,"broadcast":false,"authenticatedSignedWrites
":false,"extendedProperties":false},"descriptors":[]},{"UUID":"2a04","name":"2a0
4","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify"
:false,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"ext
endedProperties":false},"descriptors":[]}]},{"UUID":"1801","characteristics":[{"
UUID":"2a05","name":"2a05","properties":{"read":false,"write":false,"writeWithou
tResponse":false,"notify":false,"indicate":true,"broadcast":false,"a...
JS: ---- ###### adding service: 1800
JS: ---- ###### adding service: 1801
JS: ---- ###### adding service: 00001530-1212-efde-1523-785feabcd123
JS: ---- ###### adding service: 180a
JS: ---- ###### adding service: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
JS: Error in Bluetooth.writeWithoutResponse: TypeError: Cannot read property 'bl
uetoothGattService' of undefined
JS: Error in Bluetooth.writeWithoutResponse: TypeError: Cannot read property 'bl
uetoothGattService' of undefined
JS: Error in Bluetooth.writeWithoutResponse: TypeError: Cannot read property 'bl
uetoothGattService' of undefined
services.page.js
function onWriteOpen() {
bluetooth.writeWithoutResponse(
{
UUID: _peripheral.UUID,
serviceUUID: '6e400001-b5a3-f393-e0a9-e50e24dcca9e', // read write service of BLE device
characteristicUUID: '6e400002-b5a3-f393-e0a9-e50e24dcca9e', // transmit characteristic of BLE device service
value: '0x4f',
//awaitResponse: false // if false you will not get notified of errors (fire and forget)
}
).then(
function(result) {
console.log("Writing " + value + "on " + _peripheral.UUID);
},
function(err) {
console.log("Failed to write " + value + "on "+ _peripheral.UUID + err);
}
);
}
xml file with button component
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="pageLoaded">
<StackLayout col="0" orientation="vertical">
<StackLayout col="0" orientation="vertical" class="tab-content">
<StackLayout orientation="horizontal">
<Label text="{{ name }}" class="details-label-title" />
<Label text=" services" class="details-label-title details-label-title-postfix" />
</StackLayout>
<Label text="{{ UUID }}" class="details-services-uuid" />
<!--<Label text="{{ state }}" />-->
<Button text="disconnect" tap="onDisconnectTap" class="button button-positive" />
</StackLayout>
<ActivityIndicator busy="{{ isLoading }}"/>
<StackLayout>
<Button text="Open" tap="onWriteOpen" class="button button-positive" />
</StackLayout>
<GridLayout rows="*">
<ListView items="{{ services }}" itemTap="onServiceTap" separatorColor="#90c3d4">
<ListView.itemTemplate>
<StackLayout col="0" class="tab-content">
<Label text="{{ name }}" />
<Label text="{{ UUID }}" visibility="{{ name != UUID ? 'visible' : 'collapse' }}" />
</StackLayout>
</ListView.itemTemplate>
</ListView>
</GridLayout>
</StackLayout>
</Page>
UPDATE 10/16:
Testing on Pixel 1 with Android 9 OS.
The plugin AndroidManifest file in the bluetooth plugin already includes the suggested permission line.
The device is shown when I scan. Here are two screenshots of the app:
https://imgur.com/a/KLQS1mD
When I select the device I can then see the available services. I want to use the last one for my buttons. I have used the demo app to manually write a hex value to the device and it works. I'm just trying to attach the entire action to buttons.
Original demo app: https://github.com/EddyVerbruggen/nativescript-bluetooth-demo
10/17/18:
Running the demo and manually selecting the write/read service and then the write characteristic sending a value I get these results.
JS: --- peri selected: EB:FA:DB:31:1B:A7
JS: Connecting to peripheral with UUID: EB:FA:DB:31:1B:A7
JS: ------- _MyGattCallback.onConnectionStateChange, status: 0, new state: 2
JS: ---- discovering services..
JS: ------- _MyGattCallback.onServicesDiscovered, status (0=success): 0
JS: ------- Peripheral connected: {"UUID":"EB:FA:DB:31:1B:A7","name":"ZoneFirst BLE","state":"connected","services":[{"UUID":"1800","characteristics":[{"UUID":"2a00","name":"2a00",
"properties":{"read":true,"write":true,"writeWithoutResponse":false,"notify":false,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":false},
"descriptors":[]},{"UUID":"2a01","name":"2a01","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify":false,"indicate":false,"broadcast":false,"authenticated
SignedWrites":false,"extendedProperties":false},"descriptors":[]},{"UUID":"2a04","name":"2a04","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify":false,"
indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":false},"descriptors":[]}]},{"UUID":"1801","characteristics":[{"UUID":"2a05","name":"2a05","
properties":{"read":false,"write":false,"writeWithoutResponse":false,"notify":false,"indicate":true,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":false},
"descriptors":[{"UUID":"2902","value":null}]}]},{"UUID":"00001530-1212-efde-1523-785feabcd123","characteristics":[{"UUID":"00001532-1212-efde-1523-785feabcd123","name":"00001532-12
12-efde-1523-785feabcd123","properties":{"read":false,"write":false,"writeWithoutResponse":true,"notify":false,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,
"extendedProperties":false},"descriptors":[]},{"UUID":"00001531-1212-efde-1523-785feabcd123","name":"00001531-1212-efde-1523-785feabcd123","properties":{"read":false,"write":true,"
writeWithoutResponse":false,"notify":true,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":false},"descriptors":[{"UUID":"2902","value":nul
l}]},{"UUID":"00001534-1212-efde-1523-785feabcd123","name":"00001534-1212-efde-1523-785feabcd123","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify":fals
e,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":false},"descriptors":[]}]},{"UUID":"180a","characteristics":[{"UUID":"2a29","name":"2a29
","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify":false,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":fals
e},"descriptors":[]},{"UUID":"2a24","name":"2a24","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify":false,"indicate":false,"broadcast":false,"authentica
tedSignedWrites":false,"extendedProperties":false},"descriptors":[]},{"UUID":"2a28","name":"2a28","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify":fals
e,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":false},"descriptors":[]},{"UUID":"2a26","name":"2a26","properties":{"read":true,"write":
false,"writeWithoutResponse":false,"notify":false,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":false},"descriptors":[]},{"UUID":"2a27",
"name":"2a27","properties":{"read":true,"write":false,"writeWithoutResponse":false,"notify":false,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProp
erties":false},"descriptors":[]}]},{"UUID":"6e400001-b5a3-f393-e0a9-e50e24dcca9e","characteristics":[{"UUID":"6e400003-b5a3-f393-e0a9-e50e24dcca9e","name":"6e400003-b5a3-f393-e0a9-
e50e24dcca9e","properties":{"read":false,"write":false,"writeWithoutResponse":false,"notify":true,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProp
erties":false},"descriptors":[{"UUID":"2901","value":null},{"UUID":"2902","value":null}]},{"UUID":"6e400002-b5a3-f393-e0a9-e50e24dcca9e","name":"6e400002-b5a3-f393-e0a9-e50e24dcca9
e","properties":{"read":false,"write":true,"writeWithoutResponse":true,"notify":false,"indicate":false,"broadcast":false,"authenticatedSignedWrites":false,"extendedProperties":fals
e},"descriptors":[{"UUID":"2901","value":nul
JS: l}]}]}]}
JS: ---- ###### adding service: 1800
JS: ---- ###### adding service: 1801
JS: ---- ###### adding service: 00001530-1212-efde-1523-785feabcd123
JS: ---- ###### adding service: 180a
JS: ---- ###### adding service: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
JS: --- service selected: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
JS: ------- _MyGattCallback.onCharacteristicWrite
JS: android.bluetooth.BluetoothGattCharacteristic#75d8936
I can see the callback of the write in this case. But using a button returns the TypeError: Cannot read property 'bluetoothGattService' of undefined

Related

Vue 3 Internal server error: v-model cannot be used on a prop, because local prop bindings are not writable

I found this error and blocked my webapps.
2:32:22 PM [vite] Internal server error: v-model cannot be used on a prop, because local prop bindings are not writable.
Use a v-bind binding combined with a v-on listener that emits update:x event instead.
Plugin: vite:vue
File: /Users/julapps/web/myapp/src/components/switch/AudienceTimerSlide.vue
I want to make timer data become data model (editable) and its default value from component props. Why this not work? I'm very new in vuejs, how can i solve this problem? Kindly Please Help...
<template>
----
<div class="field-body">
<div class="field">
<div class="control">
<input #keypress.enter="save" v-model="timer" type="number" class="input is-normal">
</div>
</div>
</div>
-----
</template>
<script>
export default {
props:['id', 'timer'],
setup(props, context){
-----
const save = async() => {
// save form
}
return {
}
}
}
</script>
you have to change defineProps(['question', 'choices'])
to
const props=defineProps(['question', 'choices'])
call as props.question in script like
<TextInput :text="props.question" ></TextInput>
Props are read-only One-Way Data Flow
Use an internal data property with timer as initial value. Like this:
data() {
return {
localTimer: timer
}
}
and
<input #keypress.enter="save" v-model="localTimer" type="number" class="input is-normal">
Or replace v-model with v-bind:value & emit an event
#input="$emit('update:modelValue', $event.target.value)"
Like this:
<input #keypress.enter="save" :value="timer" #input="$emit('update:modelValue', $event.target.value)" type="number" class="input is-normal">

Vue 3 vuelidate how can I update user information without password update?

I'm using vuelidate 3 for vue 3 composition api.
When I try to update user information without password, $invalid always return true.
For this reason save button is always return true and disabled.
How to update without password?
Below code is template.
<q-input
v-model="editedItem.name"
label="User Name"
#blur="v$.name.$touch()"
:error="v$.name.$error"
:error-message="v$.name.$errors.length ? v$.name.$errors[0].$message : null"
></q-input>
<q-input
v-model="editedItem.email"
label="User email"
#blur="v$.email.$touch()"
:error="v$.email.$error"
:error-message="v$.email.$errors.length ? v$.email.$errors[0].$message : null"
></q-input>
<q-input
v-model="editedItem.avatar"
label="User Avatar"
></q-input>
<q-input
v-model="editedItem.password"
label="Password"
type="password"
#blur="v$.password.$touch()"
:error="v$.password.$error"
:error-message="v$.password.$errors.length ? v$.password.$errors[0].$message : null"
></q-input>
<q-input
v-model="editedItem.password_confirm"
label="Password Confirm"
type="password"
#blur="v$.password_confirm.$touch()"
:error="v$.password_confirm.$error"
:error-message="v$.password_confirm.$errors.length ? v$.password_confirm.$errors[0].$message : null"
></q-input>
<q-toggle
v-model="editedItem.is_active"
:true-value="1"
:false-value="0"
label="Activation"
></q-toggle>
<q-btn
#click="save()"
flat
color="primary"
label="Save"
:disabled="v$.$invalid"
></q-btn>
Below code is for rules
const rules = {
name: {
required
},
email: {
required,
email
},
password: {
minLength: minLength(6)
},
password_confirm: {
minLength: minLength(6),
sameAsPassword: sameAs('password')
}
}
Thank you so much guys.
I have some mistake that parameter of sameAs method was wrong, according to reference of vuelidate site parameter must be password's v-model name not 'password'...OMG

How to load a dynamic form in Modal in angular 7 where the formcontrols (input fields ) also loaded from api call

The problem is that the input fields to be put in as formcontrols are got from API back end call as it keeps changing. The form keeps throwing error "cannot find control name".By the time the http call returns (using subscribe), the form is delivered on the screen and I am unable to create formcontrols on time.. Thus throwing the error..
Has anyone done such scenario?
You can create forms dynamically from your response. - >
for (item of response.items) {
const formGroup = {
form: this.formBuilder.group({
fromVal: ['', Validators.required],
toVal: ['', Validators.required],
}),
};
this.fromArray.push(formGroup);
}
Then you can access them in your view - >
<mat-cell *matCellDef="let riskClass; let i = index;" class="px-0 col">
<form [formGroup]="fromArray[i].form" >
<label class="no-wrap mr-3">FROM : </label>
<input formControlName="fromVal"
[value]="fromArray[i].form.get('fromVal').value"
class="form-control no-radius mt-0 mr-3"/>
</form>
</mat-cell>

Store Document Reference in Firebase from HTML <select multiple> using Vue.js

I am trying to create an array of references with Vue.js + Firebase. In the SELECT INPUT using multiple, when I try to store, it (obsviously) create an array, so my reference doens't work. I understood why, but I don't know how to solve this. When the OPTIONS from SELECT enters un the field to go to Firebase, it grabs and Array, so my reference link looks like 'todos / Item1 , Item2 , Item3' ... Sorry if it is a newbie question, but I just started with vue.js and firebase. Thanks.
HTML:
<form class="new-todo-form">
<label class="new-todo-label">
Day and Hour
<input v-model="date" type="date" class="new-todo-input"/>
</label>
<label class="new-todo-label">
Participantes:
<select v-model="participants" class="select-input" multiple>
<option v-for="todo in todos" v-bind:value="todo.institution">{{todo.institution}}</option>
</select>
</label>
<button type="submit" #click.prevent="addTest()" class="new-todo-button">Add</button>
</form>
addTest() {
testsCollection.doc(this.date).set({
id: this.tests.length,
date: this.date,
participants: todosCollection.doc('todos/' + this.participants),
})
.then(function(docRef) {
console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
console.error("Error adding document: ", error);
});
},
Error in Console:
[Vue warn]: Error in v-on handler: "FirebaseError: [code=invalid-argument]: Function CollectionReference.doc() requires its first argument to be of type non-empty string, but it was: an array"
found in
---> <App> at src/App.vue
<Root> vue.esm.js:628
FirebaseError: "Function CollectionReference.doc() requires its first argument to be of type non-empty string, but it was: an array"
FirestoreError index.cjs.js:352
validateType index.cjs.js:673
validateArgType index.cjs.js:574
doc index.cjs.js:21267
addTeste App.vue:481
click App.vue:386
VueJS 3

Nativescript radlistview crashes navigating back from the details page

When slow loading the big list of items in a Component with < RadListView > in it's template, user can navigate to Details page of item by tap, and after navigating Back get such error:
JS: ERROR Error: java.lang.IndexOutOfBoundsException: Invalid index 5, size is 2
JS: java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
JS: java.util.ArrayList.add(ArrayList.java:147)
JS: com.telerik.widget.list.ListViewAdapter.add(ListViewAdapter.java:65)
I think this means that Component is "frozen" in a cache but data is still going from Observable object from the service. And after Component started to continue of creating new items in listview it is crashed because has already missed few.
How to properly bind stream of data to RadListView component with possibility to still loading it when Component is not active? I would like that user can navigate to Details page and back during process of loading data...
This is the Template part:
<RadListView id="listView" [items]="listings" height="100%" class="page page-content">
<ListViewGridLayout tkListViewLayout spanCount="{{ spanCount }}">
<ng-template let-item="item" let-i="index">
<StackLayout class="card-view" id="{{ i }}" listing_id="{{ item.listing_id }}" orientation="vertical" (tap)="onTap($event)">
<Image class="card-image" src="{{ item.url_170x135 }}" height="135" width="170" stretch="aspectFill"></Image>
<StackLayout orientation="vertical" horizontalAlignment="center">
<Label className="nameLabel" [text]="getTitle(item.title)"></Label>
</StackLayout>
</StackLayout>
</ng-template>
</ListViewGridLayout>
</RadListView>
This is the Component code:
listings = new ObservableArray<any>();
constructor(private productService: ProductService, private page: Page, private routerExtensions: RouterExtensions) {}
ngOnInit(): void {
this.productService.getListingsAdopted().subscribe((item) => this.listings.push(item));
Just added listView.refresh() when return to the page with list of items:
ngOnInit(): void {
this.page.on("navigatedTo", (data: NavigatedData) => {
if (data.isBackNavigation) {
this.listView = <RadListView>(this.page.getViewById("listView"));
this.listView.resumeUpdates(true); // works too
// this.listView.refresh();
return;
...

Resources