Browse Source

some rounding out the corners

master
boB Rudis 5 years ago
parent
commit
cb22f2e991
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 8
      DESCRIPTION
  2. 15
      NAMESPACE
  3. 6
      NEWS.md
  4. 3
      R/deere-package.R
  5. 31
      R/list-backups.R
  6. 30
      R/src_mowerplus.R
  7. 11
      R/utils-pipe.R
  8. 16
      R/utils.R
  9. 11
      README.Rmd
  10. 68
      README.md
  11. BIN
      README_files/figure-gfm/mow-1.png
  12. BIN
      README_files/figure-gfm/mow-2.png
  13. BIN
      README_files/figure-gfm/mow-3.png
  14. 20
      man/list_ios_backups.Rd
  15. 12
      man/pipe.Rd
  16. 8
      man/src_mowerplus.Rd

8
DESCRIPTION

@ -1,8 +1,8 @@
Package: deere Package: deere
Type: Package Type: Package
Title: Catchall Functions for All Things 'John Deere' Title: Catchall Functions for All Things 'John Deere'
Version: 0.1.0 Version: 0.2.0
Date: 2019-06-10 Date: 2019-06-19
Authors@R: c( Authors@R: c(
person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"),
comment = c(ORCID = "0000-0001-5670-2640")) comment = c(ORCID = "0000-0001-5670-2640"))
@ -20,8 +20,10 @@ Suggests:
Depends: Depends:
R (>= 3.2.0) R (>= 3.2.0)
Imports: Imports:
fs,
tibble, tibble,
dplyr, dplyr,
RSQLite RSQLite,
magrittr
Roxygen: list(markdown = TRUE) Roxygen: list(markdown = TRUE)
RoxygenNote: 6.1.1 RoxygenNote: 6.1.1

15
NAMESPACE

@ -1,7 +1,22 @@
# Generated by roxygen2: do not edit by hand # Generated by roxygen2: do not edit by hand
export("%>%")
export(from_coredata_ts) export(from_coredata_ts)
export(list_ios_backups)
export(platform_ios_backup_dir)
export(src_mowerplus) export(src_mowerplus)
import(tibble) import(tibble)
importFrom(dplyr,arrange)
importFrom(dplyr,desc)
importFrom(dplyr,filter)
importFrom(dplyr,mutate)
importFrom(dplyr,pull)
importFrom(dplyr,select)
importFrom(dplyr,src_sqlite) importFrom(dplyr,src_sqlite)
importFrom(dplyr,tbl) importFrom(dplyr,tbl)
importFrom(fs,dir_exists)
importFrom(fs,dir_info)
importFrom(fs,file_copy)
importFrom(fs,path_join)
importFrom(fs,path_real)
importFrom(magrittr,"%>%")

6
NEWS.md

@ -1,2 +1,8 @@
0.2.0
* Functions attempt to auto-derive the iOS backup location on macOS and legacy Windows operating systems.
* Uses the `{fs}` pacakge for all file/directory operations
* Provides a `list_ios_backups()` function so you can see all the iOS backups available
* `src_mowerplus()` defaults to using the most recent iOS backup (if it exists) if unspecified
0.1.0 0.1.0
* Initial release * Initial release

3
R/deere-package.R

@ -17,5 +17,6 @@
#' @keywords internal #' @keywords internal
#' @author Bob Rudis (bob@@rud.is) #' @author Bob Rudis (bob@@rud.is)
#' @import tibble #' @import tibble
#' @importFrom dplyr tbl src_sqlite #' @importFrom fs dir_info file_copy path_real path_join dir_info dir_exists
#' @importFrom dplyr tbl src_sqlite desc arrange filter mutate select pull
"_PACKAGE" "_PACKAGE"

31
R/list-backups.R

@ -0,0 +1,31 @@
#' List iOS backups available on this system
#'
#' @param dir backup dir (will attempt to be auto-derived)
#' @export
#' @examples
#' list_ios_backups()
list_ios_backups <- function(dir = platform_ios_backup_dir()) {
fs::dir_info(platform_ios_backup_dir(), type = "directory") %>%
mutate(path = basename(path)) %>%
arrange(desc(modification_time)) %>%
select(path, modification_time, size)
}
#' @rdname list_ios_backups
#' @export
platform_ios_backup_dir <- function() {
os <- detect_os()
switch(
os,
windows = "~/AppData/Roaming/Apple Computer/MobileSync/Backup",
macos = "~/Library/Application Support/MobileSync/Backup"
)
}

30
R/src_mowerplus.R

@ -3,8 +3,10 @@
#' @md #' @md
#' @note You may need to [setup permissions](https://rud.is/b/2019/06/02/trawling-through-ios-backups-for-treasure-a-k-a-how-to-fish-for-target-files-in-ios-backups-with-r/) #' @note You may need to [setup permissions](https://rud.is/b/2019/06/02/trawling-through-ios-backups-for-treasure-a-k-a-how-to-fish-for-target-files-in-ios-backups-with-r/)
#' to be able to use this method depending on which macOS version you're on. #' to be able to use this method depending on which macOS version you're on.
#' @param backup_id the giant hex string of a folder name #' @param backup_id the giant hex string of a folder name; if unspecified will use the most
#' recent backup (if found).
#' @param data_loc where `mowtrack.sqlite` will be sync'd #' @param data_loc where `mowtrack.sqlite` will be sync'd
#' @param ios_backup_dir where to look for iOS backups (tries to auto-derive the value)
#' @param overwrite nuke ^^ if present (def: `TRUE`) #' @param overwrite nuke ^^ if present (def: `TRUE`)
#' @export #' @export
#' @examples \dontrun{ #' @examples \dontrun{
@ -17,22 +19,28 @@
#' glimpse(tbl(mow_db, "ZACTIVITY")) #' glimpse(tbl(mow_db, "ZACTIVITY"))
#' #'
#' } #' }
src_mowerplus <- function(backup_id, data_loc = "~/Data", overwrite = TRUE) { src_mowerplus <- function(backup_id, data_loc = "~/Data",
ios_backup_dir = platform_ios_backup_dir(),
overwrite = TRUE) {
if (missing(backup_id)) {
backup_id <- list_ios_backups(dir = ios_backup_dir)[["path"]][[1]]
}
# root of mobile backup dir for `backup_id` # root of mobile backup dir for `backup_id`
mb <- path.expand(file.path("~/Library/Application Support/MobileSync/Backup", backup_id)) mb <- fs::path_real(fs::path_join(c(ios_backup_dir, backup_id)))
stopifnot(dir.exists(mb)) stopifnot(fs::dir_exists(mb))
data_loc <- path.expand(data_loc) data_loc <- fs::path_real(data_loc)
stopifnot(dir.exists(data_loc)) stopifnot(fs::dir_exists(data_loc))
tf <- tempfile(fileext = ".sqlite") tf <- tempfile(fileext = ".sqlite")
on.exit(unlink(tf), add=TRUE) on.exit(unlink(tf), add=TRUE)
# path to the extracted sqlite file # path to the extracted sqlite file
out_db <- file.path(data_loc, "mowtrack.sqlite") out_db <- fs::path_join(c(data_loc, "mowtrack.sqlite"))
file.copy(file.path(mb, "Manifest.db"), tf, overwrite = TRUE) fs::file_copy(fs::path_join(c(mb, "Manifest.db")), tf, overwrite = TRUE)
manifest_db <- src_sqlite(tf) manifest_db <- src_sqlite(tf)
@ -41,9 +49,9 @@ src_mowerplus <- function(backup_id, data_loc = "~/Data", overwrite = TRUE) {
filter(fils, relativePath == "Library/Application Support/MowTracking.sqlite") %>% filter(fils, relativePath == "Library/Application Support/MowTracking.sqlite") %>%
pull(fileID) -> mowtrackdb_loc pull(fileID) -> mowtrackdb_loc
file.copy( fs::file_copy(
file.path(mb, sprintf("%s/%s", substr(mowtrackdb_loc, 1, 2), mowtrackdb_loc)), fs::path_join(c(mb, sprintf("%s/%s", substr(mowtrackdb_loc, 1, 2), mowtrackdb_loc))),
file.path(data_loc, "mowtrack.sqlite"), fs::path_join(c(data_loc, "mowtrack.sqlite")),
overwrite = overwrite overwrite = overwrite
) )

11
R/utils-pipe.R

@ -0,0 +1,11 @@
#' Pipe operator
#'
#' See \code{magrittr::\link[magrittr]{\%>\%}} for details.
#'
#' @name %>%
#' @rdname pipe
#' @keywords internal
#' @export
#' @importFrom magrittr %>%
#' @usage lhs \%>\% rhs
NULL

16
R/utils.R

@ -12,3 +12,19 @@ from_coredata_ts <- function(x, tz = NULL) {
), tz = tz) ), tz = tz)
} }
os_type <- function() {
.Platform$OS.type
}
detect_os <- function() {
ostype <- os_type()
sysname <- Sys.info()["sysname"]
if (ostype == "windows") {
"windows"
} else if (sysname == "Darwin") {
"macos"
} else {
stop("You will need to manually specify the backup location on this platform.", call.=FALSE)
}
}

11
README.Rmd

@ -29,6 +29,11 @@ Ref:
The following functions are implemented: The following functions are implemented:
- `from_coredata_ts`: Convert timestampes from Apple "CoreData" format to something usable
- `list_ios_backups`: List iOS backups available on this system
- `platform_ios_backup_dir`: List iOS backups available on this system
- `src_mowerplus`: Find and sync a copy of the latest MowerPlus database file from an iOS backup
## Installation ## Installation
```{r install-ex, eval=FALSE} ```{r install-ex, eval=FALSE}
@ -55,10 +60,12 @@ packageVersion("deere")
``` ```
### Sample from a recent mow ### Sample from the latest mow
```{r mow, cache=TRUE} ```{r mow, cache=TRUE}
mow_db <- src_mowerplus("28500cd31b9580aaf5815c695ebd3ea5f7455628") list_ios_backups()
mow_db <- src_mowerplus()
mow_db mow_db

68
README.md

@ -24,6 +24,13 @@ Ref:
The following functions are implemented: The following functions are implemented:
- `from_coredata_ts`: Convert timestampes from Apple “CoreData” format
to something usable
- `list_ios_backups`: List iOS backups available on this system
- `platform_ios_backup_dir`: List iOS backups available on this system
- `src_mowerplus`: Find and sync a copy of the latest MowerPlus
database file from an iOS backup
## Installation ## Installation
``` r ``` r
@ -47,13 +54,20 @@ library(tidyverse)
# current version # current version
packageVersion("deere") packageVersion("deere")
## [1] '0.1.0' ## [1] '0.2.0'
``` ```
### Sample from a recent mow ### Sample from the latest mow
``` r ``` r
mow_db <- src_mowerplus("28500cd31b9580aaf5815c695ebd3ea5f7455628") list_ios_backups()
## # A tibble: 2 x 3
## path modification_time size
## <chr> <dttm> <fs::bytes>
## 1 28500cd31b9580aaf5815c695ebd3ea5f7455628 2019-06-19 14:31:41 8.19K
## 2 28500cd31b9580aaf5815c695ebd3ea5f7455628-20190601 2019-06-01 17:23:05 8.22K
mow_db <- src_mowerplus()
mow_db mow_db
## src: sqlite 3.22.0 [/Users/hrbrmstr/Data/mowtrack.sqlite] ## src: sqlite 3.22.0 [/Users/hrbrmstr/Data/mowtrack.sqlite]
@ -66,14 +80,14 @@ glimpse(tbl(mow_db, "ZMOWER"))
## Database: sqlite 3.22.0 [/Users/hrbrmstr/Data/mowtrack.sqlite] ## Database: sqlite 3.22.0 [/Users/hrbrmstr/Data/mowtrack.sqlite]
## $ Z_PK <int> 1 ## $ Z_PK <int> 1
## $ Z_ENT <int> 7 ## $ Z_ENT <int> 7
## $ Z_OPT <int> 11 ## $ Z_OPT <int> 15
## $ ZDECKSIZEINCHES <int> 48 ## $ ZDECKSIZEINCHES <int> 48
## $ ZDISMISSEDFULLSERVICETASK <int> 0 ## $ ZDISMISSEDFULLSERVICETASK <int> 0
## $ ZDISMISSEDPERIODICTASK <int> 0 ## $ ZDISMISSEDPERIODICTASK <int> 0
## $ ZSMARTCONNECTOR <int> NA ## $ ZSMARTCONNECTOR <int> NA
## $ ZUSER <int> 1 ## $ ZUSER <int> 1
## $ ZBATTERYCHARGE <dbl> NA ## $ ZBATTERYCHARGE <dbl> NA
## $ ZENGINEHOURS <dbl> 3.474705 ## $ ZENGINEHOURS <dbl> 4.854714
## $ ZFULLSERVICEPERFORMED <dbl> NA ## $ ZFULLSERVICEPERFORMED <dbl> NA
## $ ZHMCLASTSEEN <dbl> NA ## $ ZHMCLASTSEEN <dbl> NA
## $ ZHMCOFFSET <dbl> 0 ## $ ZHMCOFFSET <dbl> 0
@ -92,26 +106,26 @@ glimpse(tbl(mow_db, "ZACTIVITY"))
## Observations: ?? ## Observations: ??
## Variables: 20 ## Variables: 20
## Database: sqlite 3.22.0 [/Users/hrbrmstr/Data/mowtrack.sqlite] ## Database: sqlite 3.22.0 [/Users/hrbrmstr/Data/mowtrack.sqlite]
## $ Z_PK <int> 1, 2 ## $ Z_PK <int> 1, 2, 3, 4
## $ Z_ENT <int> 3, 3 ## $ Z_ENT <int> 3, 3, 3, 3
## $ Z_OPT <int> 124, 93 ## $ Z_OPT <int> 124, 93, 52, 36
## $ ZMONTH <int> 6, 6 ## $ ZMONTH <int> 6, 6, 6, 6
## $ ZYEAR <int> 2019, 2019 ## $ ZYEAR <int> 2019, 2019, 2019, 2019
## $ ZMOWER <int> 1, 1 ## $ ZMOWER <int> 1, 1, 1, 1
## $ ZUSER <int> 1, 1 ## $ ZUSER <int> 1, 1, 1, 1
## $ ZISCOMPLETE <int> 1, 1 ## $ ZISCOMPLETE <int> 1, 1, 1, 1
## $ ZISMISSEDMOW <int> 0, 0 ## $ ZISMISSEDMOW <int> 0, 0, 0, 0
## $ ZLASTLOCATION <int> 7016, 12548 ## $ ZLASTLOCATION <int> 7016, 12548, 15500, 17514
## $ ZCREATEDAT <dbl> 581100260, 581778616 ## $ ZCREATEDAT <dbl> 581100260, 581778616, 582506930, 582659215
## $ ZENGINEHOURS <dbl> NA, NA ## $ ZENGINEHOURS <dbl> NA, NA, NA, NA
## $ ZAREACOVERED <dbl> 3.761875, 2.286811 ## $ ZAREACOVERED <dbl> 3.761875, 2.286811, 1.292296, 1.078715
## $ ZAVERAGESPEED <dbl> 3.727754, 2.894269 ## $ ZAVERAGESPEED <dbl> 3.727754, 2.894269, 3.011241, 3.650042
## $ ZDISTANCEMOWED <dbl> 7.758894, 4.716564 ## $ ZDISTANCEMOWED <dbl> 7.758894, 4.716564, 2.665370, 2.224857
## $ ZMOWINGTIME <dbl> 6960.000, 5548.939 ## $ ZMOWINGTIME <dbl> 6960.000, 5548.939, 2933.049, 2034.981
## $ ZNOTES <chr> "First mow!", NA ## $ ZNOTES <chr> "First mow!", NA, NA, NA
## $ ZINTERVALNAME <chr> NA, NA ## $ ZINTERVALNAME <chr> NA, NA, NA, NA
## $ ZTYPE <chr> NA, NA ## $ ZTYPE <chr> NA, NA, NA, NA
## $ ZUUID <blob> blob[238 B], blob[238 B] ## $ ZUUID <blob> blob[238 B], blob[238 B], blob[238 B], blob[238 B]
tbl(mow_db, "ZACTIVITY")%>% tbl(mow_db, "ZACTIVITY")%>%
collect() -> activity collect() -> activity
@ -195,8 +209,8 @@ arrange(sessions, ts) %>%
| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) |
| :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | | :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: |
| Rmd | 1 | 0.17 | 74 | 0.69 | 31 | 0.69 | 39 | 0.45 | | Rmd | 1 | 0.12 | 75 | 0.53 | 33 | 0.56 | 43 | 0.38 |
| R | 5 | 0.83 | 33 | 0.31 | 14 | 0.31 | 48 | 0.55 | | R | 7 | 0.88 | 67 | 0.47 | 26 | 0.44 | 69 | 0.62 |
## Code of Conduct ## Code of Conduct

BIN
README_files/figure-gfm/mow-1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 61 KiB

BIN
README_files/figure-gfm/mow-2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

After

Width:  |  Height:  |  Size: 317 KiB

BIN
README_files/figure-gfm/mow-3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 KiB

After

Width:  |  Height:  |  Size: 287 KiB

20
man/list_ios_backups.Rd

@ -0,0 +1,20 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/list-backups.R
\name{list_ios_backups}
\alias{list_ios_backups}
\alias{platform_ios_backup_dir}
\title{List iOS backups available on this system}
\usage{
list_ios_backups(dir = platform_ios_backup_dir())
platform_ios_backup_dir()
}
\arguments{
\item{dir}{backup dir (will attempt to be auto-derived)}
}
\description{
List iOS backups available on this system
}
\examples{
list_ios_backups()
}

12
man/pipe.Rd

@ -0,0 +1,12 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils-pipe.R
\name{\%>\%}
\alias{\%>\%}
\title{Pipe operator}
\usage{
lhs \%>\% rhs
}
\description{
See \code{magrittr::\link[magrittr]{\%>\%}} for details.
}
\keyword{internal}

8
man/src_mowerplus.Rd

@ -4,13 +4,17 @@
\alias{src_mowerplus} \alias{src_mowerplus}
\title{Find and sync a copy of the latest MowerPlus database file from an iOS backup} \title{Find and sync a copy of the latest MowerPlus database file from an iOS backup}
\usage{ \usage{
src_mowerplus(backup_id, data_loc = "~/Data", overwrite = TRUE) src_mowerplus(backup_id, data_loc = "~/Data",
ios_backup_dir = platform_ios_backup_dir(), overwrite = TRUE)
} }
\arguments{ \arguments{
\item{backup_id}{the giant hex string of a folder name} \item{backup_id}{the giant hex string of a folder name; if unspecified will use the most
recent backup (if found).}
\item{data_loc}{where \code{mowtrack.sqlite} will be sync'd} \item{data_loc}{where \code{mowtrack.sqlite} will be sync'd}
\item{ios_backup_dir}{where to look for iOS backups (tries to auto-derive the value)}
\item{overwrite}{nuke ^^ if present (def: \code{TRUE})} \item{overwrite}{nuke ^^ if present (def: \code{TRUE})}
} }
\description{ \description{

Loading…
Cancel
Save