Getting all BLE services from Android app - kotlin

I have an Android app, that must connect to a BLE server, discover its services, and read a specific characteristic of a specific service.
The server code is written in go and is a simple template that I took here. From it, I register a service and a characteristic with the followings UUIDs:
MyService: 00010000-0001-1000-8000-00805F9B34FC
MyCharacteristic: 00010000-0002-1000-8000-00805F9B34FC
Then here's my Android code that discovers for services:
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
if (status == BluetoothGatt.GATT_SUCCESS) {
gatt?.services?.forEach { service ->
Log.d("onServicesDiscovered", "new service: ${service.uuid.toString()}")
if (service.uuid == EnrollServiceUUID) {
Log.d("onServicesDiscovered", "SUCCESS")
}
}
} else {
Log.d("onServicesDiscovered", "Error while fetching services: $status")
}
}
if I scan for my go server with an nRF connect app, here's what I get:
(Notice that my declared service is found with the declared UUID)
But when running my android code: Here are the services I find:
onServicesDiscovered: 00001800-0000-1000-8000-00805f9b34fb
onServicesDiscovered: 00001801-0000-1000-8000-00805f9b34fb
onServicesDiscovered: 0000180a-0000-1000-8000-00805f9b34fb
Actually I figured out that my service and my characteristic have been "renamed" to another UUIDs. In fact, only the two first parts are modified, as following:
Go server | Android app
00010000-0001 | 180a-0000
00010000-0002 | 00002a50-0000
I'm able to interact with from my app, but I would like to understand why they have a different UUID that the ones I declare from my Go server and I see with nRF connect.

Related

reuse karate tests from other feature file by passing in params [duplicate]

This question already has an answer here:
Pass Json to karate-config.js file
(1 answer)
Closed 1 year ago.
We have a set of services that all expose certain common endpoints such as a health check, version information etc. I am trying to use karate to write smoke tests for these multiple services in a reusable way that i can just pass in the service name and endpoint and have the tests executed for each service.
basicChecks.feature
Feature: Smoke Test. verify health check and version and index are ok
Scenario: Verify that test server health check is up and running
Given url '#(baseUrl)'
Given path '/health'
When method get
Then status 200
And match response == "'#(name)' ok"
Given path '/version'
When method get
Then status 200
And match response contains {'#(name)'}
testServices.feature
Feature: Smoke Test for services.
Scenario: Verify that test server health check is up and running
* call read('basic.feature') { name: 'service1' , baseUrl : service1Url }
* call read('basic.feature') { name: 'service2' , baseUrl : service2Url }
karate-config.js
function fn() {
var env = karate.env; // get java system property 'karate.env'
karate.log('karate.env system property was:', env);
if (!env) {
env = 'local'; // a custom 'intelligent' default
}
var config = { // base config JSON
appId: 'my.app.id',
appSecret: 'my.secret',
service1Url: 'https://myserver/service1'
service2Url: 'https://myserver/service2'
};
// don't waste time waiting for a connection or if servers don't respond within 5 seconds
karate.configure('connectTimeout', 5000);
karate.configure('readTimeout', 5000);
return config;
}
When i run this i get an error suggesting that the baseUrl is not being picked up when passed in
20:27:22.277 karate.org.apache.http.ProtocolException: Target host is not specified, http call failed after 442 milliseconds for url: /health#(baseUrl) 20:27:22.278 cas/src/test/java/karate/smoke/basic.feature:7 When method get http call failed after 442 milliseconds for url: /health#(baseUrl) cas/src/test/java/karate/smoke/basic.feature:7
I looked at https://intuit.github.io/karate/#code-reuse--common-routines but could not figure out how to use the same tests but pass in different endpoints?
Or maybe since i am totally new to karate there is a much better way of doing this than what i have outlined?
Thank you for your time.
Edit - I am trying to test different micro services in the same environment and not trying to switch different environments etc.
This is not the recommended approach. When you have different URL-s for different environments, you should switch environments using the approach in the documentation (setting karate.env) and NOT depend on re-use via "call" etc.
Example: https://stackoverflow.com/a/49693808/143475
And if you really want you can run suites one after the other switching the karate.env, although that is rare.
Or if you just trying "data" driven testing, there are plenty of ways, just read the docs and search Stack Overflow for Scenario Outline: https://stackoverflow.com/search?tab=newest&q=%5bkarate%5d%20Scenario%20Outline
If you are trying to do this "clever" re-use using "call" I strongly recommend that you don't and please read this for why: https://stackoverflow.com/a/54126724/143475
EDIT - I think you ran into this problem, read the docs please: https://github.com/intuit/karate#rules-for-embedded-expressions

Implementing a 202 ACCEPTED - Retry-After behaviour with RSocket and Project Reactor

I'm implementing a tipical use case in which a client asks for a resource that will be asynchronously generated. Thus, a resourceID is generated and returned right away:
1. CLIENT ---(POST /request-resource)---> SERVER
2. SERVER (Generates resID, launches async process) ---(202 Accepted - resID)---> CLIENT
At this point there is a background task in the SERVER, that will eventually produce a result and store it in a database associated to the resID. The CLIENT would be asking for the resource periodically, retrying until it is available:
3. CLIENT ---(/resource/resID)---> SERVER (checks in Postgres using reactive driver)
4. SERVER ---(404 - Retry-After 5)---> CLIENT
5. CLIENT ---(/resource/resID)---> SERVER (checks in Postgres using reactive driver)
6. SERVER ---(200 - JSON Payload)---> CLIENT
I though RSocket would be a perfect fit in order to avoid this endless CLIENT retry until the resource is available (steps 3. on).
Which interaction model would be more suitable for this problem and how could I implement it?
Consider a repository as follows: ResourceRepository.Mono<Result> getResult(String resID)
If I chose a request/response interaction model I'd be in the same case as before. Unless there was a way to have a Mono that retried until there is a result. Is this possible?
With request/stream I could return results like Flux<Response> with response.status=PROCESSING until the query to Postgre returned a result, then the Flux would have an element with response.status=OK and the Flux would complete. A maximum time would be needed to finish the Flux without a result in a configured period. In this case how could I orquestate this?
I would need to create a Flux, that emits periodically (with a max period timeout), having an element with no result when the repository returns an empty Mono, or the actual value when te repository has it, completing the Flux.
Solution to this problem using RSocket with a RequestResponse interaction model that waits until the resource is available in DB. The key was to use the repeatWhenEmpty operator:
#MessageMapping("request-resource")
fun getResourceWebSocket(resourceRequest: ResourceRequest): Mono<Resource> {
return resourceService.sendResourceRequestProcessing(resourceRequest)
}
override fun sendResourceRequestMessage(resourceRequest: ResourceRequest): Mono<Resource> {
val resourceId = randomUUID().toString()
return Mono.fromCallable {
sendKafkaResourceProcessingRequestMessage(resourceId, resourceRequest)
}.then(poolResourceResponse(resourceId))
}
private fun poolResourceResponse(resourceId: String): Mono<Resource> {
return resourceRepository.findByResourceId(resourceId)
.repeatWhenEmpty(30) { longFlux ->
longFlux.delayElements(Duration.ofSeconds(1))
.doOnNext { logger.info("Repeating {}", it) }
}
}

How to fetch fieldname and structure for additional properties in operation, managedObject etc

I am trying to figure out which fragments are related to operation:
managedObject
event
measurement
alarm
So , Is there a way to get all these fragments ?
Also there are additional Properties for which field name is defined as * and the value can be an Object or anything else(*). I have gone through the device management library and sensor library in cumulocity documentation but found it does not contain all the possible fragments and there is no clarity as in which object the fragment goes i.e does it go in operation or managedObject, or both?
Since every user, device and application can contribute such fragments, there is no "global list" of them that you could refer to. Normally, a client (application, device) knows what data it sends or what data it requests, so it's also in most cases not required.
Regarding the relationship between operations and managed objects, there are some typical design pattern. Let's say you want to configure something in a device, like a polling interval:
"mydevice_Configuration": { "pollingRate": 60 }
What your application would do is to send that fragment as an operation to a device:
POST /devicecontrol/operations HTTP/1.1
...
{
"deviceId": "12345",
"mydevice_Configuration": { "pollingRate": 60 }
}
The device would accept the operation (http://cumulocity.com/guides/rest/device-integration/#step-6-finish-operations-and-subscribe) and change its configuration. When it does that successfully, it will update its managed object to contain the new configuration:
PUT /inventory/managedObjects/12345 HTTP/1.1
{
"mydevice_Configuration": { "pollingRate": 60 }
}
This way, your inventory reflects as closely as possible the true state of devices.
Hope that helps ...

SoftLayer API: - How to get the ID of a bare metal server on create

I'm using 'SoftLayer_Hardware', 'createObject' to deploy new servers, however this call returns no id, as on the example on http://sldn.softlayer.com/reference/services/SoftLayer_Hardware/createObject
So if I have no id how can I query info for that server? I noticed there's a globalIdentifier variable but no mention at all on what it is and how to use it
you can use the goblal identifier instead the ID in your request
e.g.
Get https://api.softlayer.com/rest/v3.1/SoftLayer_Hardware/$GloblalIdentifier/getObject
Note: replace the $GloblalIdentifier
The reason why the id is not displayed is because the server was not created yet, your order has to be approved and when the provisioning is ended the id will show up, meanwhile you can use the global identifier when the provisioning ends you will be able to see the id
regards
Here SoftLayer_Hardware::createObject says:
To determine when the server is available you can poll the server via
SoftLayer_Hardware::getObject,
checking the provisionDate property. When provisionDate is not null,
the server will be ready. Be sure to use the globalIdentifier as your
initialization parameter.
Please see this example:
https://[username]:[apikey]#api.softlayer.com/rest/v3/SoftLayer_Hardware/[globalIdentifier_value]/getObject
Method: GET
Also, you can get Bare Metal information using SoftLayer_Account::getHardware with some filters:
https://[username]:[apikey]#api.softlayer.com/rest/v3/SoftLayer_Account/getHardware?objectFilter={"hardware":{"hostname":{"operation": "myhostname"}, "domain":{"operation": "mydomain"}}}&objectMask=mask[id,fullyQualifiedDomainName,provisionDate]
Method: GET
Note: You can add some masks in order to get more information than by default, i.e. In the previous request you can see the provisionDate(When provisionDate is not null, the server will be ready).
List Bare metal servers filtering by username who created them:
https://[username]:[apikey]#api.softlayer.com/rest/v3/SoftLayer_Account/getHardware?objectFilter={ "hardware": { "billingItem": { "orderItem": { "order": { "userRecord": { "username": { "operation": "myusername" } } } } } } }&objectMask=mask[id,fullyQualifiedDomainName,billingItem.orderItem.order.userRecord.username,provisionDate]
Method: GET
Also you can review:
Softlayer API to get virtual guest owner
thank you for your answers. Unfortunately this is a chicken/egg problem. Once the API call is sent, I get an GloblalIdentifier but not an id.
If I ask for this GloblalIdentifier I get a response with id as null
If I get the listing of the hardware servers, I see the new machine is there, has an id, but the GloblalIdentifier is None.
Makes no sense.

WCF Windows Service and Windows Store App Non-Meaningful Reply Error Message

I'm having a lot of problems getting tyres on the ground with Windows 8 Programming.
One problem is, I cannot install IIS as Windows 8 is giving me problems because I am dual booting it with 7. Any OS updates fail, including configuration changes such as adding IIS.
But anyway, to get around this, I decided to host a WCF service in a Windows Service with a TCP endpoint, and consume that service in my Store app. For inserts, it works, not a problem.
But when I go to retrieve some data (a very small data set - 3 records), the following error displays: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
I've Googled that error and it seems to be a common one - meaning it could be anything. But I am a total noob with WCF.
My code in the ViewModel is simply:
private async void PopulatePeople()
{
var people = await licenceBucketService.GetAllPersonsAsync();
FirstName = people.First().FirstName;
LastName = people.First().LastName;
}
The GetAllPersons method is:
public ObservableCollection<Person> GetAllPersons()
{
ObservableCollection<Person> people = null;
using (var context = new LicenceBucketContext())
{
people = new ObservableCollection<Person>(context.People);
}
return people;
}
The async version in the Reference.cs file looks like:
public System.Threading.Tasks.Task<System.Collections.ObjectModel.ObservableCollection<Win8UI.LicenceBucketService.Person>> GetAllPersonsAsync() {
return base.Channel.GetAllPersonsAsync();
}
Do any WCF gurus see my issue?