Worklight & Location Services questions - ibm-mobilefirst

I read the Worklight Location Services tutorial, and I have a few questions.
I need more clarity on the difference between WL.Device.Geo.acquirePosition & WL.Device.startAcquisition
Can WL.Device.Geo.acquirePosition give you the latitude & longitudes? How do I get the area names, city etc? Do I have to use google maps API?
Can you please elaborate on the below accessPointFilters configuration in a wifi policy?
Wifi : {
interval : 10000,
accessPointFilters : {
[{ SSID : "Net1" },
{ SSID : "Net2", MAC : "* "} ]
}
}
I have read that in the acquisition policy, if I mention enableHightSecurity as true, it uses GPS? If I don't use it, which mechanism will it use?
Geo: {
timeout: 3000,
enableHighAccuracy: true
},

WL.Device.Geo.acquirePosition - get your current geographic location.
WL.Device.startAcquisition - I think of it more of like doing some kind of geofencing. for more info look at http://www-01.ibm.com/support/knowledgecenter/SSHS8R_6.3.0/com.ibm.worklight.dev.doc/devref/t_creating_a_geofence.html?lang=en
WL.Device.Geo.acquirePosition can give you a position object based on this W3C specification. If you want to get city, state, country and other information like that you can use Google Maps API geocoding or any other geocoding api out there
From the MobileFirst Platform documentation
"{object[]} policy.Wifi.accessPointFilters Optional - An array object that specifies the WiFi access points that you want to detect. Each entry has an SSID name specification, and optionally a MAC specification. The MAC specification can be a wildcard value, represented by an asterisk (), in which case all MACs for this SSID are reported. If no MAC is specified, and this WiFi is visible, then only its SSID is reported; only a single entry appears, regardless of the number of access points that have this SSID. The SSID specification can be a wildcard, represented by an asterisk (), in which case all visible networks are reported. "
You can read more at http://www-01.ibm.com/support/knowledgecenter/SSHS8R_6.3.0/com.ibm.worklight.apiref.doc/html/refjavascript-server/html/WL.Device.html?cp=SSHS8R_6.3.0%2F9-1-0-1-0&lang=en
policy.Geo.enableHighAccuracy is required. If you set it to false it won't use high accuracy sensors "GPS", instead it will get your location from other means, i.e.: Network, Wifi
for more info check http://www-01.ibm.com/support/knowledgecenter/SSHS8R_6.3.0/com.ibm.worklight.apiref.doc/html/refjavascript-server/html/WL.Device.html?cp=SSHS8R_6.3.0%2F9-1-0-1-0
I hope this helps. To get more documentation about IBM MobileFirst Platform foundation V6.3 you can visit the Knowledge Center at http://www-01.ibm.com/support/knowledgecenter/SSHS8R_6.3.0/wl_welcome.html?lang=en

Yoel gave a great answer; regarding point #1 for additional clarification - WL.Device.Geo.acquirePosition is a single acquisition; WL.Device.startAcquisition is on-going and allows you to define various kinds of geo-fences.

Related

GoogleFit on iphone: problem with REST API calls

I'm trying to query, with the Fit rest API, segmented data from an iphone that have installed GoogleFit and configured the sync between apple health and googelfit.
To my android phone, I get the data as expected with this POST:
(*)
"aggregateBy": [
{
"dataSourceId": "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps",
"dataTypeName": "com.google.step_count.delta"
},
{
"dataSourceId": "derived:com.google.distance.delta:com.google.android.gms:merge_distance_delta",
"dataTypeName": "com.google.distance.delta"
}
{
"dataSourceId": "derived:com.google.active_minutes:com.google.android.gms:merge_active_minutes",
"dataTypeName": "com.google.active_minutes"
}
],
"endTimeMillis": 1643325227000,
"startTimeMillis": 1640991600000,
"bucketByActivitySegment": {
"minDurationMillis": 600000
}
}
But from the iphone user, this returns an empty bucket.
I checked the available data dataSources for the apple user. I did some "trial and error" on the dataSourceIds connected to "active_minutes". In particular
derived:com.google.active_minutes:com.google.ios.fit:appleinc.:iphone:1148c16f:top_level
derived:com.google.active_minutes:com.google.ios.fit:appleinc.:watch:f40f5c4a:top_level
The trial and error werer conducted with aggregateBy post with one of the above sources, so no distance and step_count involved. The two above dataSourceIds were obtained from a "list post query" for available dataSources, done by the iphone user, with the following scopes:
fitness.activity.read
fitness.location.read
No segmented data is returned from either dataSourceIds (an empty bucket as well).
Contents within the apple user's app indicates that there should be segmented data somewhere, see screenshot link.
(Edit: also tried setting "minDurationMillis: 0")
Meanwhile, queries such as:
(**)
{
"aggregateBy": [
{
"dataSourceId": "derived:com.google.distance.delta:com.google.android.gms:merge_distance_delta",
"dataTypeName": "com.google.distance.delta"
}
],
"endTimeMillis": 1643325227000,
"startTimeMillis": 1640991600000,
"bucketByTime": {
"durationMillis": 2333627000
}
}
does return data from the apple user. But I'm really interested in segments (minimum 10 minutes long)
So, question: Anyone with experience getting segmented data from apple-googlefit users?
Figure:
iphone screenshot
Update.
Since (**) (see first post) did return data from the iphones, I went with a 1-hour "bucketByTime"-solution for both androids and iphones.
If segments is important, it is possible to parse/filter the "bucketByTime" data into segments. However, activity type is not obtained with this POST.
New problem(s) have arisen:
As mentioned, (**) POST returned data. Particularly when:
"startTimeMillis" = [start of 2022]
and
"endTimeMillis" = [now].
A cron executor is configured such that (**) is repeated once a day where:
"startTimeMillis" = ["previous now"]
and
"endTimeMillis" = [now].
However, this does not return any data from the iphone users. To clarify, no daily data is received from the iphones.
Some preformed check-ups:
The iphone users see data as normal on the front-end view of the GoogleFit app (see screenshot link in first post).
Attempted (**) with every "dataStreamId" and "name" available (returned from "list post query" for available dataSources) - Nothing is returned.
Asked the iphone users to check GoogleFit's permissions, in accordance with this support page. (I'll have to take their word that it's configured correctly)
Important finding:
For one iphone user, "incomplete"[2] data is occasionally returned. I'm imagining this data is data recorded by his apple watch. I asked him to wear his watch today.
You'd figure, when asking for eg. merge_distance_delta the app merges the available sources into a neat timeline. Questions on this level is not available publicly (to my knowledge).
[2] The sum does not (come close) to matching the GoogleFiT front-end results (as it does for the android users).

IBM Domino 10 - integrating with Resource Reservations via Domino Data Services API

We're trying to integrate with IBM Domino via REST API to pull out information about reservations/events in a specific room and also be able to create new events/reservations remotely. We already integrated with other services such as Microsoft Exchange, but IBM seems to be the toughest of them all.
I studied deeply into it and read thousands of articles & stack overflow questions, and got pretty far but still can't make any real use out of it.
What I currently plan on doing is this:
Pull information about reservations from /api/data/collections/name/($Reservations) or ($Calendar)
Create events/reservations using the documents api, POSTing to /api/data/documents?form=Reservation, I already tried doing it and my reservation even showed in Domino Admin (not in Notes client though), but it had some errors (probably just some json problem on my side)
While it looks kinda clear and easy, it really isn't. I have a few questions:
How can I get reservations/calendar for a specific room? ($Calendar) returns all events in the database, not even including in which room it is, to get that information I would need to additionally query each reservation by it's unid and that would probably kill the entire app
Is there any way I could filter/search the /api/data/documents to return only documents whose form field has a value of Reservation or any other value? This way I could get all the reservation documents without querying each of the documents directly (/api/data/documents only returns the href to the document without any interesting data), I wouldn't also need to additionally enable DAS for each view I want to use.
What are the fields like $25 returned in the json, and how can I know what's their purpose if they don't have any real name? They often contain interesting data, such as the room name.
I also looked into the FreeBusy api service, and it's pretty interesting and I could easily use it to look for reservations (/busytimes) in the room I want, if it ever returned what resource/reservation is causing the busy time. It just shows the start and end time, nothing else..
I also read suggestions that one should create a 'main' user to handle the reservations and use his calendar api (/api/calendar/events), but afaik it can't be done that way.
However I tried creating events in the users calendar in specified room, and kinda got it to work by adding the following attendee in the json |(PHP syntax, actually):
'organizer' => [ 'email' => 'admin/test#test.com' ],
'attendees' => [
[
'role' => 'req-participant',
'userType' => 'room',
'status' => 'accepted',
'rsvp' => true,
'email' => 'testroom#test.com',
],
],
But it doesn't really get displayed in the room reservations, unlike normal events created in IBM Notes. It also cannot be edited or deleted in IBM Notes, and it has "Accepted: " in front of the subject, and it says "attendance is delegated for admin". To delete it, I need to delete it via API through its unid directly. x-lotus-noticetype is being set to A so I guess it's not being treated as a meeting but as an notice, no idea why though.
I'd really like some help or suggestions on how I could get this working, are there any other ways that would have any sense?
Edit:
After struggling a lot and reading Dave's reply, I think it would be a good solution to have a single user that would do the reservations via calendar api, because the direct data api probably won't work. I could just only pull the list of all reservations from Rooms database ($Calendar) or ($Reservations) view, or make some sort of my own view.
However! I cannot get the calendar method to work on my local IBM Domino server. Dave pointed to me that I need to specify a valid email (internet address) of the organizer, so I set my user's internet address to testmail#test.test (test.test is mapped to 127.0.0.1 in the hosts file). Now as soon as I try to use that address like that:
"organizer": {
"email": "testmail#test.test"
}
I cannot even create the event/reservation (through /mail/admin.nsf/api/calendar/events), it's returning 500 internal error with cserror 1026, and Domino logs
[CS API]> Error | calendarapi.c(379) : There was an error sending out notices to meeting participants. (0x8E4)
Error connecting to server test/test: The remote server is not a known TCP/IP host.
So it has a problem with sending the notice, and doesn't create the event at all. I thought it may not work with localhost, so I set my users email to an external mail service, and I even received the email, but the event was still created incorrectly (x-lotus-noticetype A is being added automatically and overrides whatever I send as the value), it's not visible in the Room Reservations database.
Here's the json object of an event created via Notes client:
"events": [
{
"href":"\/mail\/admin.nsf\/api\/calendar\/events\/2B35FABBC50EA4D0C12583BC002E26FA-Lotus_Notes_Generated",
"id":"2B35FABBC50EA4D0C12583BC002E26FA-Lotus_Notes_Generated",
"summary":"Notes client meeting",
"location":"Test room\/Test site#test",
"start": {
"date":"2019-03-13",
"time":"09:30:00",
"tzid":"Central European Standard Time"
},
"end": {
"date":"2019-03-13",
"time":"10:30:00",
"tzid":"Central European Standard Time"
},
"class":"public",
"transparency":"opaque",
"sequence":0,
"last-modified":"20190313T082436Z",
"attendees": [
{
"role":"chair",
"status":"accepted",
"rsvp":false,
"displayName":"admin\/test",
"email":"testmail#test.test"
},
{
"role":"req-participant",
"userType":"room",
"status":"needs-action",
"rsvp":true,
"displayName":"Test room\/Test site",
"email":"room#test.test"
}
],
"organizer": {
"displayName":"admin\/test",
"email":"testmail#test.test"
},
"x-lotus-broadcast": {
"data":"FALSE"
},
"x-lotus-notesversion": {
"data":"2"
},
"x-lotus-appttype": {
"data":"3"
}
}
]
As you can see, Notes is able to create the event with testmail#test.test successfully.
Now here's an event created with my API, but with admin/test#test.test as the organizer's email (because normal email doesn't let me create the event):
"events": [
{
"href":"\/mail\/admin.nsf\/api\/calendar\/events\/E1D1F752203FC2DFC12583BC002FCB12-Lotus_Auto_Generated",
"id":"E1D1F752203FC2DFC12583BC002FCB12-Lotus_Auto_Generated",
"summary":"Api reservation test",
"location":"Test room\/Test site#test\r\nCN=Test room\/O=Test site",
"description":"API Generated event\r\n",
"start": {
"date":"2019-03-20",
"time":"11:00:00",
"utc":true
},
"end": {
"date":"2019-03-20",
"time":"15:00:00",
"utc":true
},
"class":"public",
"transparency":"opaque",
"sequence":0,
"last-modified":"20190313T084201Z",
"attendees": [
{
"role":"chair",
"status":"accepted",
"rsvp":false,
"displayName":"admin\/test",
"email":"testmail#test.test"
},
{
"role":"req-participant",
"userType":"room",
"status":"needs-action",
"rsvp":true,
"displayName":"Test room\/Test site",
"email":"room#test.test"
}
],
"organizer": {
"displayName":"admin\/test",
"email":"testmail#test.test"
},
"x-lotus-broadcast": {
"data":"FALSE"
},
"x-lotus-notesversion": {
"data":"2"
},
"x-lotus-noticetype": {
"data":"A"
},
"x-lotus-appttype": {
"data":"3"
}
}
]
As you can see, the organizer's & chair emails were automatically updated by Lotus to testmail#test.test, and theorethically everything should work but it doesnt. In Notes, I see the event as 'Accepted: Api reservation test' and I cannot modify things like the room, or don't have the option to delete it from right click menu (I can delete it with Del keyboard button though)
The only difference is that x-lotus-noticetype get's added, and I don't even know why
Edit 2:
I got it to work! Dave pointed that I may have some configuration issue, so I re-installed the server & setup everything again (including the mail services), I used admin#test.test and the meeting was succesfully created & added to the room reservations. Server console only showed that the message was delivered.
HOWEVER! I was able to create as many identical meetings as I wanted, they weren't added to the reservations database but they were succesfully created in my calendar (with the room assigned to them) without any errors (not even in the sever console), this is obviously bad. Is there any way to check (externally, through API) if the reservation was created succesfully, and prevent it's creation if the room is busy at that moment? Notes client prompts an error when the room is busy. I could probably use FreeBusy api, however that would require another HTTP request before each reservation attempt, but if that's the only way then I'll just take it. I see that the status field of the attendeed room is set to declined, but the response from POST still contains needs-action so I'd need to do some delayed request once again to check if the status has changed to declined or not.
Also, while it works, I still don't know how I could obtain a list of reservations in a selected room? The already existing views in Reservations database don't give many details, and they need to be exclusively enabled DAS services in order to work. Is there any other way that could work properly?
Another thing is, is there any way I could get current user's email address to use for the reservations, or can I only 'hardcode' it manually? Same goes for room's email. Currently, I need to have:
User name
User password
User mail database (/mail/admin.nsf/)
User email
Room email
and if I'd want to read some data from the Reservations database directly, then I'd also need to have the path to that database. This isn't really user-friendly, I'd like to automate some things if possible. Otherwise the integration may be impossible to make.
The reservation database was designed to manage reservations either (1) directly through it's own UI, or (2) indirectly by auto-processing notifications from calendar users. By using the DAS data API, you are asserting you can manage reservations (3) programmatically -- by manipulating the low-level document items. You might get this to work, but I don't think the reservation database was designed with that in mind.
That's why I think this answer is the best option. It leverages auto-processing (#2 above) and saves you from dealing with the internal design of reservation documents. If you use this approach, you should give the DAS calendar API a list of attendees like this:
"attendees":[
{
"role":"req-participant",
"userType":"room",
"status":"needs-action",
"rsvp":true,
"email":"room#mycorp.com"
}
]
In other words, status must be "needs-action" -- not "accepted" as shown in your original post. Also, make sure you are using the correct email address for both the organizer and the target room. The above example shows an Internet-style address for the room, but administrators don't always give a room an Internet address.

Sony Soundbar HT-ZF9 API setActiveTerminal showing Error 12 ; other APi's are working

I want to control the soundbar by LAN.
I can turn on and off the soundbar with postman and the given Sony Api's.
When i Want to change the input, in Postman appears error 12.
I don't understand why, because other API's like getInformation are working fine. (network, url, port, connection, and library should be also ok)
From the Api getInformation, I could read the information with the name of the inputs.
But then I paste them to setActiveTerminal, Error 12 occurs.
Does anyone know, where is the problem??
Here, the used code:
http://169.254.75.11:10000/sony/avContent
{
"method":"setActiveTerminal",
"id":55,
"params":[
{
"active": "active",
"uri": "extInput:hdmi?port=1"
}
],
"version":"1.0"
}
The setActiveTerminal is for activating or deactivating output ports extOutput or "zone" that it is called on the STR-DN1080. Since the ZF9 don't have multi zone capabilities the use of this method is very limited.
I'm guessing you want to set the input port and that is done via setPlayContent (with out the output parameter in the json for ZF9) see
Sony Audio Control API - Can't Change Input on AV Receiver for more info.

smartREST template: custom measurement not visible as Datapoint

I created a smartREST template for measurement via "device management -> smartREST templates". I send the reading via MQTT:
s/uc/mytemplateID
777,123,stringValue
The message arrives because I can see it through the API:
{
"time":"2018-07-03T15:36:13.237+01:00",
"id":"47638",
"self":"https://myDomain.mydomain/measurement/measurements/47638",
"source":{
"id":"20018",
"self":"https://myDomain.mydomain/inventory/managedObjects/20018"
},
"type":"myType",
"myStrValue":"stringValue",
"myNumberValue":123
}
But I can not see it as a data point.
I also can not see it under: "device management -> All devices -> myDevice -> Measurements"
If the cause is that the incoming message does not have the expected format, then the question is, how can I use MQTT to send custom measurments with the expected format?
Thank you
To be able to use Cumulocity standard features on your measurements, they must adhere to a certain standard. Transform your template to create measurements like this:
{
"time":"2018-07-03T15:36:13.237+01:00",
"id":"47638",
"self":"https://myDomain.mydomain/measurement/measurements/47638",
"source":{
"id":"20018",
"self":"https://myDomain.mydomain/inventory/managedObjects/20018"
},
"type":"myType",
"myFragment":{
"mySeries":{
"value":123,
"unit":"aUnit"
},
"myOtherSeries":{
"value":321,
"unit":"anotherUnit"
}
}
}
Note that measurement values are always numeric, using string based values here may cause unwanted behavior again.
If you want to communicate string based status variables sending events or alarms is usually a better approach.
The template configuration to send such measurements should look like this:

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 ...