iOS CMStepCounter & CMMotionActivityManager - ios

I am using CMStepCounter and CMMotionActivityManager.
What I would like to do is work out my total walking time throughout the day, and from this, my average speed.
However, looking at the data in CMMotionActivityManager, it is clear than a number of steps throughout the day are actually logged during periods that are of 'unknown activity' and not walking or running. This does make sense, as you need to do a handful of steps for iOS to know you are walking. However, these add up over the course of any given day.
Querying CMMotionActivity, it is possible to get the timestamp of every event. However, whilst it is clear to me that every step must be timestamped in CMStepCounter, I can only see a method to return the total number of steps between two points in time. What would be great is if I could return an array of every step with its time stamp, and if so, how?
Many thanks.

With the current Core Motion API, you can't get an array of every step with its time stamp directly.
But you can use queryActivityStartingFromDate:toDate:toQueue:withHandler: to get an array of CMMotionActivity objects. Then use the time stamps to calculate the number of steps by calling queryStepCountStartingFrom:to:toQueue:withHandler:.
I don't think the M7 processor stores every step with its own time stamp. If you pass 1 as stepCounts to the method startStepCountingUpdatesToQueue:updateOn:withHandler:, you'll notice the handler is not executed on every step. Like the document says: The handler block is executed on a best effort basis each time the step count threshold is exceeded.

Related

What is the format of the time field in this cypher?

Heading ##CALL ga.timetree.single({time: 1463659567468, create: true})
https://github.com/graphaware/neo4j-timetree
https://graphaware.com/neo4j/2014/08/20/graphaware-neo4j-timetree.html
The above link says that time is in long format YYYYMMDDHHmmss. But the time parameter doesn't make any sense and random nodes are getting generated in neo4j. enter image description here
What does the time parameter hold and what is the meaning of it?
The time parameter is a millisecond timestamp, or milliseconds elapsed since the UNIX epoch, which is an extremely common means of storing time-related data, you can find this in use in nearly every digital system.
The timestamp cited here represents "2016-05-19 12:06:07". The timetree built starts from a root (this is a modeling convenience), and then its child is the year (2016) followed by the month (5), then the date of the month (19). Looks like it didn't automatically create any nodes for time resolutions beyond that.
Keep in mind that now that Neo4j has native temporal values that you can use in Cypher and store as properties (as well as index), time trees are going to be less useful, as you can always do index lookups on indexed temporal properties.
There are still some cases where time trees can still be very useful, however, such as when you're searching for events that happened within some unit of time that disregards its parent units...such as finding events that happened on Mondays regardless of month, or on Januaries regardless of year, and so forth.

How to calculate the number of consecutive days from Core Data data?

I have some payments(income and expense) which are added to Core Data and every day I calculate the total and also I show how many consecutive days the payments total was positive.
How I am doing right now is always get the total for previous day and increase a counter if its positive. This counter is saved using UserDefaults.
My issue is when lets say the app is deleted and reinstall, the counter is lost, so I am trying to find a way calculate it dynamically every time, but I don't think reading all payments for all days is a good idea in terms of memory.
Another solution is maybe save it using Keychain ?
Is there any other more elegant method? I don't really like the idea of saving this counter.
As an answer
Assuming you reset the counter if the balance goes negative, you just need to load the balance in reverse date order, and count until you go negative?
Depending on how many records you have it may not be performant to read it all in one go. If that's the case read in batches of a manageable size (50 days, perhaps) and only get more data if you are still recording positive balances.
At some point, of course, you may just return "more than 100 days" as a valid response :-)

How to add Data to Firebase?

My goal is to add +1 every day to a global variable in Firebase to track how many days have passed. I'm building an app that give new facts every day, and at the 19:00 UTC time marker, I want the case statement number (the day global day variable) to increment by +1.
Some have suggested that I compare two dates and get the days that have passed that way. If I were to do that, I could hard code the initial time when I first want the app to start at 19:00 some day. Then when the function reached1900UTC() is called everyday thereafter, compare it to a Firebase timestamp of that current time which should be 19:00. In theory, it should show that 1 day or more day has passed.
This is the best solution so far, thanks to #DavidSeek and #Jay, but I would still like to figure it out with concurrent writes if anyone has a solution in that front. Until then, I'm marking David's answer as the correct one.
How would I make it so it can't increase more than +1 if multiple people call this? Because my fear is that, when say, 100 people calls this function, it increases by + 1 for every person that has called it.
My app works on a global time, and this function is called every day at 19:00 UTC. So when that function is called I want the day count to increase by one.
You should use transactions to handle concurrent writes:
https://firebase.google.com/docs/database/ios/read-and-write#save_data_as_transactions
You may know this but Firebase doesn't have a way to auto-increment a counter as there's no server side logic, so having a counter increment at 19:00 UTC isn't going to be possible without interaction from a client that happens to be logged on at that time.
That being said, it's fairly straightforward to have the first user that logs in increment that counter - then any other clients logging in after that would not increment it and would have access to that day's new content.
Take a look at Zapier.com - that's a service that can fire time based triggers for your app which may do the trick.
As of this writing, Zapier and Firebase don't play nice together, however, there are a number of other trigger options that Zapier can do with your app while continuing to use Firebase for storage.
One other thought...
Instead of dealing with counters and counting days, why not just have each day's content stored within a node for each day and when each user logs on, the app get's that days content:
2016-10-10
fact: "The Earth is an Oblate Spheroid"
2016-10-11
fact: "Milli Vanilli is neither a Milli or a Vanilli. Discuss."
2016-10-12
fact: "George Washington did not have a middle name"
This would eliminate a number of issues such as counters, updates, concurrent writing to Firebase, triggers etc.
It's also dynamic and expandable and a user could easily see that day's facts or the fact for any prior day(s)
I'm trying to split your question into different sections.
1) If you want to use a global variable to count the days from, let's say, today. Then I would set a timestamp hardcoded into the App that sets the NSDate.
Then In my App, when I need to know the days that have been passed by, I would call a function counting the days from the timestamp to NSDate().
2) If you have a function in your App that counts a +1 into a Firebase, then your fear is correct. It would count +1 for every person that uses the App.
3) If you want every User to have a variable count since when they use their App, then I would handle User registration. So I have a "UserID" and then I would set a Firebase tree like that:
UserID
------->
FirstOpen
-------> Date
That way you could handle each User's first open.
Then you are able to set a timestamp AND call +1 for every user independently. Because then you set the +1 for every user into their UserID .child

iOS CoreMotion API -- Is there a way to keep track of how many times someone goes walking over a period of time?

I'm trying to write a simple app that will allow me to keep track of my average walking time over a set number of days using CoreMotion API. The CMPedometer API gives access to startDate and endDate of your last session. I was thinking that an easy way to do this would be to keep a 'tally' of sessions in user defaults (i.e everytime the pedometer tracks your walking the tally increases by 1) and also keeping a sum of endDate - startDate time differences. Then, I would just divide the total time Differences by the tally to get an average walking time.
I'm not sure how I'd do this. Is there a way to collect this data every single time that the pedometer tracks walking?
CMPedometer API gives access to startDate and endDate of your last session.
Which API does that? The CMPedometer docs only specify the following method:
- queryPedometerDataFromDate:toDate:withHandler:
Use this method to retrieve historical pedestrian data between the specified dates. This method runs asynchronously and delivers the data to the block you provide. Only the past seven days worth of data is stored and available for you to retrieve. Specifying a start date that is more than seven days in the past returns only the available data.
I think you are looking for CMMotionActivityManager. According to the docs, getting activities from CMMotionActivityManager is pretty straightforward:
- queryActivityStartingFromDate:toDate:toQueue:withHandler:
That query will give you an array of CMMotionActivity objects. Filter by "walking = YES" and you've got your list of walking sessions for the specified time period (only works for last 7 days).
I cannot say how accurate it is or whether or not you need to do some of your own data scrubbing/filtering.

How can I measure the total time a user spends online with InfluxDB?

I'm measuring how long users are logged into a service. Every minute, for each user, their new total online time is sent to InfluxDB. I'd like to graph, in Grafana, the cumulative online time for all users.
What kind of query would I need to do that? I initially thought that I'd want sum(onlineTime) and group by time(1m), but I realized that's summing the values within that timeframe, not summing the totals of all users, so when a user wasn't logged in, the total would drop, because there were not data points for them.
I'm a bit confused about what I'm doing now. If I'm sending the wrong data, I can change that too.
So this depends on the time data you send back to InfluxDB
The time data is equal to the total time spent till that instant of time
In this case you would have to take the "last" value and add it up for all the users
The time is equal to the small increments
In this case you would have to add this multiple incremental value for a period of time.

Resources