CBPeripheral name in iOS6 - core-bluetooth

I'm using Apple's BLTE Tansfer to simulate a heart rate monitor.
Also I have an app that receives the simulated data.
I have question a the use of CBPeripheral:
I want to control the peripheral's name.
First I've tried to add the GAP Service and name characteristic using:
[CBUUID UUIDWithString:CBUUIDGenericAccessProfileString]
[CBUUID UUIDWithString:CBUUIDDeviceNameString]
but Xcode tells me it is not recommended.
It also seems that the service is already included (when watching didDiscoverServices on the receiver side).
How can I access the name property (I want to transmit it to the receiver)?

You don't need to add new services just set up the advertisement in the following way:
NSDictionary *advData =
#{CBAdvertisementDataLocalNameKey:#"<your desired name>",
CBAdvertisementDataServiceUUIDsKey:#[[CBUUID UUIDWithString:#"180D"]]};
[peripheralManager startAdvertising:advData];

Related

YoutubeLive API: custom slate image for a scheduled video

I'm working on a desktop live streaming software and I'd like to add my custom thumbnail/image for a scheduled live video (it's known as "slateImage" in youtube's api - https://developers.google.com/youtube/v3/live/getting-started).
I found in Broadcast.insert liveBroadcasts#resource
contains a parameter called snippet.thumbnails.(key)
However it doesn't work for me, the video is with same default slateImage and yes, I remember to enable contentDetails.startWithSlate = true there.
Have anybody faced with same?
if you check the documentation livebroadcasts.insert
Provide a liveBroadcast resource in the request body. For that resource:
You must specify a value for these properties:
snippet.title
snippet.scheduledStartTime
status.privacyStatus
You can set values for these properties:
snippet.title
snippet.description
snippet.scheduledStartTime
snippet.scheduledEndTime
status.privacyStatus
contentDetails.monitorStream.enableMonitorStream
contentDetails.monitorStream.broadcastStreamDelayMs
contentDetails.enableDvr
contentDetails.enableContentEncryption
contentDetails.enableEmbed
contentDetails.recordFromStart
contentDetails.startWithSlate
contentDetails.enableClosedCaptions
The same is stated under livebroadcast.update I would say that the snippet.thumbnails.key is read only. You are not allowed to write to it though the api.
contentDetails.startWithSlate
This setting indicates whether the broadcast should automatically begin with an in-stream slate when you update the broadcast's status to live. After updating the status, you then need to send a liveCuepoints.insert request that sets the cuepoint's eventState to end to remove the slate and make your broadcast stream visible to viewers. When you update a broadcast, this property must be set if your API request includes the contentDetails part in the part parameter value. However, when you insert a broadcast, the property is optional and has a default value of false.
Note: This property cannot be updated once the broadcast is in the testing or live state.

Android Beacon Library Reference Application Help (didEnterRegion function)

My region is:
Region region = new Region("backgroundRegion", Identifier.parse("24DDF411-8CF1-440C87CD-E368DAF9C93E"), null, null);
When I start the program I get this message:
06-26 18:03:21.061 7394-7394/? D/BeaconReferenceApp: setting up background monitoring for beacons and power saving
But it doesn't enter in any didEnterRegion function
So, I removed this line: backgroundPowerSaver = new BackgroundPowerSaver(this);
And change scanning times, as it follows:
beaconManager.setBackgroundScanPeriod(1100l);
beaconManager.setBackgroundBetweenScanPeriod(10000l-1100l);
I checked my Beacon UUID and they are 24DDF411-8CF1-440C87CD-E368DAF9C93E
So what is wrong? Why the app doesn't go to the didEnterRegion function?
I already made it work to work with other than AltBeacons... (ranging function works ok!)
My final goal is to get current time when a beacon is discovered...
A few possibilities:
If you are already in the beacon region, you won't get a second callback until the beacon disappears (turn it off for 30 seconds or so, then turn it back on while the app is running.) Alternatively, you can look for a call do didDetermineStateForRegion which is always called when your app starts up, with a flag that tells you if you are inside or outside.
Make sure you have granted runtime permissions to location.
Make sure location is turned on for your phone in settings.
Make sure the beacon is transmitting that identifier using the Locate app https://play.google.com/store/apps/details?id=com.radiusnetworks.locate&hl=en
Make sure you have the proper BeaconParser configured. The question is tagged Eddystone, but shows an iBeacon or AltBeacon-style UUID as the first identifier. Do you have a custom beacon parser configured? What beacon type are you trying to detect?

Epicor 10 - Changing the plant for the current session

We are starting to use Epicor 10 and we are wanting to leverage the DLLs/Services to talk to Epicor. That way we can add/update info from a custom app. So far things are going fine but we ran into an issue when we wanted to, lets say, add a job for a specific plant. It seems to always want to save to the plant the user last logged into via the client app.
So for example -- Lets say the user's last plant was plant "A". I want my custom app to log into Epicor (creating a session) and create a job for plant "B". I can add the job fine, but it will put it under plant "A" and not "B", even though I logged into plant "B" when I created the session.
We are calling SetPlant and passing in the right plant we want, but Epicor seems to always override what plant to save it as. Has anyone else run into this case? We are also having this issue with the Company. SetCompany doesnt seem to work at all.
More info: - We are using the net.tcp:///ERP/ICE/Lib/SessionMod.svc service. - We can login fine with Login() and get a SessionId back - Even calling GetValues() on the Session object says we are logged into plant "B" even though Epicor will still use plant "A".
The only work around we can come up with, which we do not want to do, is to have an app user by company and by plant so we can guarantee which company and plant the data gets saved to. This will work but it isnt ideal.
Anyone have any suggestions on how to get the system to take the new Company or Plant?
As user463132 points out, you can wrap your service connection with the temporary session context:
using (CallContext.Current.TemporarySessionCreator.SetCompanyID("YourCompanyHere").SetPlantID("B").Create())
{
}
Haso Keric Article Reference
I'll also add that if you are using the UI adapters, you can simply grab the session from the oTrans object instance and set the properties here which governs how oTrans interacts with your data.
Ice.Core.Session s1 = (Ice.Core.Session)this.oTrans.Session;
s1.CompanyID = "YourCompanyHere";
s1.PlantID = "B";
The plantID can be updated in the session using the SetPlant() method. It must be called after the SetCompany():
sessionModImpl = NetTcp_Helper.ClassAttributHelper.CreateBusObj<SessionModImpl>(Guid.Empty, SessionModImpl.UriPath, Settings);
sessionId = sessionModImpl.Login();
sessionModImpl.SessionID = sessionId;
sessionModImpl.SetCompany(epicorCompanyID, out companyName, out plantID, out plantName, out workstationID, out workstationDescription, out employeeID,
out countryGroupCode, out countryCode, out tenantID);
sessionModImpl.SetPlant(newSiteID, out plantName);
The first thing to understand is that a Server Session is not a single
instance but rather a .NET Stack of Session Instances. The
‘CallContext.Current.Session’ variable is just a pointer to the top of
the Stack. In most cases, there is just a single Session instance in
the CallContext stack. But when you need to iterate over Companies to
process something the Session Stack get pushed and popped around.
That’s where ‘TemporarySessions’ comes in.
Read about it at:
https://www.linkedin.com/pulse/snippet-epicor-change-companyplantuser-bpm-haso-keric/

Time scheduling algorithm based on history

I have been trying for some time solve a scheduling problem for an App that I used to work at. This problem is as follows...
Example Scenario:
ContactA is running Our App in the background. He just got into his car for his commute home. So, he is in #Evening Commute status.
His Valet settings state that he only wants to be notified to make Phone Calls when in #Evening Commute status (no text or email reminders).
Once Our app sees ContactA is in #Evening Commute status, and that he is available to make Phone Calls, the app will scan ALL his contacts to find any contacts that he has specified as preferred to Call.
Th algorithm identifies 3 potential matches for ContactA in his Agent list:
ContactX
ContactY
ContactZ
How does it decide which one to prompt ContactA to connect with during his #Evening Commute?
First, it should look to see if any of those three are using The app too. For example, it identifies that ContactX and ContactY are both using The app, but ContactZ is not.
So, it will then look further at ContactX and ContactY to see if either of them are currently in a Valet status that is accepting Phone Calls.
If both are, it will look to see if either is a Favorite. If so, that person takes priority.
If neither are, it can look back at history to see which is the oldest in terms of last contacted to choose which one to contact first.
If both ContactX and ContactY are showing as “unavailable” right now, based on their App Valet settings, the app could choose to prompt me to call ContactZ.
Thanks in advance
Pseudocode (you did not ask for any specific language, but this is a simple implementation of your algorithm in code). contactsSpecified would be an array of all contacts "specified as preferred to Call".
var contactsToCall[];
//Add all contacts that are using the app and are available
foreach(contact in contactsSepcified) {
if(contact.isUsingApp() && contact.isAvailable()) {
contactsToCall.add(contact);
}
}
//Add all contacts not using the app if none of the app users have been added
if(contactsToCall.size() == 0) {
foreach(contact in contactsSepcified) {
if(!contact.isUsingApp()) {
contactsToCall.add(contact);
}
}
}
foreach(contact in conctactsToCall) {
if(conctact.isFavorite()) {
call(contact);
return;
}
}
suggestContacts(contactsToCall);

OS X Today Widget - How to detect in NCWidgetProviding.widgetPerformUpdateWithCompletionHandler if content has changed?

widgetPerformUpdateWithCompletionHandler() gives us the possibility to let the Notification Center know if the content of a Today Extension has changed. For example:
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
// Refresh the widget's contents in preparation for a snapshot.
// Call the completion handler block after the widget's contents have been
// refreshed. Pass NCUpdateResultNoData to indicate that nothing has changed
// or NCUpdateResultNewData to indicate that there is new data since the
// last invocation of this method.
if(has_new_data()) { // There was an update
completionHandler(.NewData)
}
else { // nothing changed!
completionHandler(.NoData)
}
}
But how would we know if the content has changed? On every snapshot the widget is instantiated from scratch. It is a complete new process with new PID. So you can not store any property in your instance. How would one compare the current widget content with the content of the previous snapshot?
I used Core Data to store the current content for later comparison. This is obvious and works. But then another problem crashes in: What if there is no previous snapshot? Let's say the user removed the widget just to re-add it again. Or the user rebooted. There might be more reasons why there is no previous snapshot that I can not think of now. Either way - there still is content stored in Core Data. If the comparison between this old content and the current content detects there are no changes and I return .NoData the widget would end up empty because the Notification Center would not redraw the content.
You might wonder why It is so important to me to call the completionHandler with a correct state and not simply always return .NewData. That's because I am experiencing a little flicker when there is no change and still return .NewData. I have some images in my widget and when redrawing the widget the whole content gets invisible for a millisecond - long enough to notice.
Is there something I am missing? It seems strange to me that Apple provides a way to give us the option to respond with different states but then makes it impossible to detect which state we should respond.
In theory you would use this to check whether there was any new content since the last call, and pass back the appropriate value. I suppose in theory it might be the same instance of the view controller on more than one call, but that's clearly not how things work right now. Checking whether content has changed depends on the nature of the app and the extension. Since you're using a shared Core Data store to share data, you might do something like:
Any time the app changes data, save the current date in shared user defaults.
Any time the today extension reads data, save the current date in shared user defaults.
When widgetPerformUpdateWithCompletionHandler is called, look up both of those dates. If the data has changed more recently than the last time the extension read that data, return NCUpdateResultNewData. If not, return NCUpdateResultNoData.
You could also save these dates in the metadata on the persistent store instead of in shared user defaults. If it was the same view controller each time, you might keep the value from step 2 in memory instead of saving it to a file. But again that's not how it works now, and it's not clear when or if that will change.
Apps that save data in some other way might need to use different checks, the details of which would depend on how their app and extension worked.
In practice with iOS 8.2 it really doesn't matter because the extension environment doesn't seem to care what value you send back. I tried returning NCUpdateResultNewData and compared it to returning NCUpdateResultNoData every time. There was absolutely no effect on the life cycle of the today extension view controller or its views.
As an aside, it's not always a different process. I tried putting this line in the today extension's viewDidLoad:
NSLog(#"viewDidLoad pid=%d self=%#", getpid(), self);
Then I ran the today extension, scrolled up and down in the notification center a couple of times, closed the notification center, reopened it, and got the following:
2015-03-17 15:19:01.203 DemoToday[3484:903442] viewDidLoad pid=3484 self=<TodayViewController: 0x12d508cc0>
2015-03-17 15:19:14.441 DemoToday[3484:903442] viewDidLoad pid=3484 self=<TodayViewController: 0x12d50ade0>
2015-03-17 15:19:23.784 DemoToday[3484:903442] viewDidLoad pid=3484 self=<TodayViewController: 0x12d619c40>
2015-03-17 15:19:29.015 DemoToday[3484:903442] viewDidLoad pid=3484 self=<TodayViewController: 0x12d50abe0>
Although it's a different instance of the view controller each time, it's the same pid in each of these cases.
You can use any storage API ( Core Data, NSCoding, SQLite ) as long as you enable data sharing with your host app.
https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html
Even if the user removes the widget or reboots the device, the data will be stored on your shared container. Whenever iOS launches your widget, you will be able to read and write the same shared container that you have previously used.
Be aware that your host app and your widget may read or write concurrently so you have to coordinate any reading and writing operation.
The simplest way to do this is to cache your current widgets state in user defaults. Then when the widget loads (in viewDidLoad) fetch your cached data from user defaults and set it as a property on your widget view controller.
Then when widgetPerformUpdateWithCompletionHandler is called you have your previous updated and you can decide if you need to do a network request of if your data is fresh enough. If you do a web request you can then compare it to your cache to determine if you have new data or no update.
No need to persist any data in UserDefaults or even Core Storage. Keep it simple: Just declare the variable(s) you use to store any calculated contents or data you use to check whether something changed to be static. Since the widget runs in the same process (as shown here) the static data will be available the next time your widget is activated.
static NSDate *lastDate;
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
NSDate * currentDate = [NSDate date];
if (!lastDate ||
[[NSCalendar currentCalendar]compareDate:lastDate toDate:currentDate toUnitGranularity:NSCalendarUnitDay] != NSOrderedSame) {
// Date changed
lastDate = currentDate;
... do whatever needs to be done ...
completionHandler(NCUpdateResultNewData);
} else {
completionHandler(NCUpdateResultNoData);
}
}

Resources