diff --git a/DESCRIPTION b/DESCRIPTION index d1500ba..bde9333 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,7 @@ Package: tcam Type: Package -Title: tcam Title Goes Here Otherwise CRAN Checks Fail +Title: Retrieve Radiometric Image Data from and Configure and Control tCam and + tCam-Mini Thermal Imaging Systems Version: 0.1.0 Date: 2021-08-19 Authors@R: c( @@ -8,17 +9,25 @@ Authors@R: c( comment = c(ORCID = "0000-0001-5670-2640")) ) Maintainer: Bob Rudis -Description: A good description goes here otherwise CRAN checks fail. +Description: The tCam and tCam-Mini () + are two cameras designed around the ESP32 chipset and provide easy access to + radiometric data from Lepton 3.5 sensors. Tools are provided to configure, control, + and receive radiometric data from tCam systems. URL: https://git.rud.is/hrbrmstr/tcam BugReports: https://git.rud.is/hrbrmstr/tcam/issues Encoding: UTF-8 -License: AGPL +License: MIT + file LICENSE Suggests: covr, tinytest Depends: R (>= 3.6.0) Imports: - httr, - jsonlite + RcppSimdJson, + openssl, + tidyr, + dplyr, + magrittr, + stringi, + utils Roxygen: list(markdown = TRUE) RoxygenNote: 7.1.1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b6e2729 --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2021 +COPYRIGHT HOLDER: tcam authors diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..f8a435d --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2021 tcam authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NAMESPACE b/NAMESPACE index 5b4b9ae..260d10b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,4 +1,15 @@ # Generated by roxygen2: do not edit by hand -import(httr) -importFrom(jsonlite,fromJSON) +export("%>%") +export(get_image) +export(get_status) +export(tcam_connect) +export(tidy_radiometric) +importFrom(RcppSimdJson,fparse) +importFrom(dplyr,mutate) +importFrom(dplyr,mutate_at) +importFrom(magrittr,"%>%") +importFrom(openssl,base64_decode) +importFrom(stringi,stri_replace_all_regex) +importFrom(tidyr,gather) +importFrom(utils,hasName) diff --git a/R/aaa.R b/R/aaa.R new file mode 100644 index 0000000..4476951 --- /dev/null +++ b/R/aaa.R @@ -0,0 +1 @@ +utils::globalVariables(c(".")) \ No newline at end of file diff --git a/R/core.R b/R/core.R new file mode 100644 index 0000000..4e8fb43 --- /dev/null +++ b/R/core.R @@ -0,0 +1,61 @@ +#' Make a socket connection to a tCam device +#' +#' @param host,port IP/hostname + port; defaults to the device defaults +#' @export +tcam_connect <- function(host = "192.168.4.1", port = 5001) { + socketConnection( + host = host, + port = port, + open = "a+b" + ) +} + +#' Returns a packet with camera status. +#' +#' @param con open socket connection from [tcam_connect()] +#' @export +get_status <- function(con) { + + writeBin( + object = c(as.raw(0x02), charToRaw('{"cmd":"get_status"}'), as.raw(0x03)), + con = con, + useBytes = TRUE + ) -> res + + Sys.sleep(0.5) + + readChar( + con = con, + nchars = 2048L, + useBytes = TRUE + ) %>% + stri_replace_all_regex("\002|\003", "") %>% + fparse() + +} + +#' Returns a packet with metadata, radiometric (or AGC) image data and Lepton telemetry objects. +#' +#' @param con open socket connection from [tcam_connect()] +#' @export +get_image <- function(con) { + + tmp <- get_status(con) + + writeBin( + object = c(as.raw(0x02), charToRaw('{"cmd":"get_image"}'), as.raw(0x03)), + con = con, + useBytes = TRUE + ) -> res + + Sys.sleep(0.5) + + readChar( + con = con, + nchars = 65536L, + useBytes = TRUE + ) %>% + stri_replace_all_regex("\002|\003", "") %>% + fparse() + +} \ No newline at end of file diff --git a/R/tcam-package.R b/R/tcam-package.R index 5b12cfa..e3b6bd2 100644 --- a/R/tcam-package.R +++ b/R/tcam-package.R @@ -1,9 +1,19 @@ -#' ... -#' +#' Retrieve Radiometric Image Data from and Configure and Control tCam and tCam-Mini +#' Thermal Imaging Systems +#' +#' The tCam and tCam-Mini () +#' are two cameras designed around the ESP32 chipset and provide easy access to +#' radiometric data from Lepton 3.5 sensors. Tools are provided to configure, control, +#' and receive radiometric data from tCam systems. +#' #' @md #' @name tcam #' @keywords internal #' @author Bob Rudis (bob@@rud.is) -#' @import httr -#' @importFrom jsonlite fromJSON +#' @importFrom RcppSimdJson fparse +#' @importFrom openssl base64_decode +#' @importFrom tidyr gather +#' @importFrom dplyr mutate mutate_at +#' @importFrom stringi stri_replace_all_regex +#' @importFrom utils hasName "_PACKAGE" diff --git a/R/utils-pipe.R b/R/utils-pipe.R new file mode 100644 index 0000000..fd0b1d1 --- /dev/null +++ b/R/utils-pipe.R @@ -0,0 +1,14 @@ +#' Pipe operator +#' +#' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. +#' +#' @name %>% +#' @rdname pipe +#' @keywords internal +#' @export +#' @importFrom magrittr %>% +#' @usage lhs \%>\% rhs +#' @param lhs A value or the magrittr placeholder. +#' @param rhs A function call using the magrittr semantics. +#' @return The result of calling `rhs(lhs)`. +NULL diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 0000000..a005251 --- /dev/null +++ b/R/utils.R @@ -0,0 +1,43 @@ +#' Return a tidy data frame of Lepton radiometric data retrieved with [get_image()] +#' +#' Converts the base64 16-bit coded Kelvin radiometric data to a tidy "XYZ" +#' data frame in Fahrenheit. +#' +#' @param img_data data structure retrieved with [get_image()] +#' @returns data frame of `x`, `y`, and `value` +#' @export +tidy_radiometric <- function(img_data) { + + if (!hasName(img_data, "radiometric")) { + stop("Data structure does not seem to be tCam radiometric image data.", call.=FALSE) + } + + openssl::base64_decode(img_data$radiometric) %>% + readBin( + what = "integer", + n = 19200, + size = 2 + ) %>% + matrix( + nrow = 120, + ncol = 160, + byrow = TRUE, + dimnames = list(120:1) + ) -> m + + as.data.frame(m) %>% + mutate(y = rownames(m)) %>% + gather(x, value, -y) %>% + mutate_at( + vars(x), + ~sub("V", "", .) + ) %>% + mutate( + x = as.integer(x), + y = as.integer(y), + value = ((value / 100) * 1.8) - 459.67 # convert to degrees F b/c I'm a brutish Murican + ) -> xdf + + xdf[,c("x", "y", "value")] + +} \ No newline at end of file diff --git a/README.Rmd b/README.Rmd index bb89576..615a405 100644 --- a/README.Rmd +++ b/README.Rmd @@ -7,7 +7,7 @@ editor_options: hrbrpkghelpr::global_opts() ``` -```{r badges, results='asis', echo=FALSE, cache=FALSE} +```{r badges, results='asis', echo=FALSE, cache=FALSE, eval=FALSE} hrbrpkghelpr::stinking_badges() ``` @@ -33,12 +33,54 @@ hrbrpkghelpr::install_block() ```{r lib-ex} library(tcam) +library(ggplot2) # for plotting # current version packageVersion("tcam") ``` +Open a connection and get the status of the tCam: + +```{r ex-01} +con <- tcam_connect() + +get_status(con) +``` + +Take a picture and plot it: + +```{r ex-02, cache=TRUE} +img <- get_image(con) + +ggplot(tidy_radiometric(img)) + + geom_tile( + aes(x, y, fill = value), + color = NA + ) + + scale_fill_viridis_c( + name = "°F", + option = "magma" + ) + + coord_fixed() + + labs( + x = NULL, y = NULL + ) + + theme_minimal() + + theme( + axis.text.x.bottom = element_blank(), + axis.text.y.left = element_blank(), + panel.grid.major = element_blank(), + panel.grid.minor = element_blank() + ) +``` + +Done, so we close the connection. + +```{r ex-99} +close(con) +``` + ## tcam Metrics ```{r cloc, echo=FALSE} diff --git a/README.md b/README.md new file mode 100644 index 0000000..19e8fd5 --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ + +# tcam + +Retrieve Radiometric Image Data from and Configure and Control tCam and +tCam-Mini Thermal Imaging Systems + +## Description + +The tCam and tCam-Mini +() are two cameras +designed around the ESP32 chipset and provide easy access to radiometric +data from Lepton 3.5 sensors. Tools are provided to configure, control, +and receive radiometric data from tCam systems. + +## What’s Inside The Tin + +The following functions are implemented: + +- `get_image`: Returns a packet with metadata, radiometric (or AGC) + image data and Lepton telemetry objects. +- `get_status`: Returns a packet with camera status. +- `tcam_connect`: Make a socket connection to a tCam device +- `tidy_radiometric`: Return a tidy data frame of Lepton radiometric + data retrieved with get_image() + +## Installation + +``` r +remotes::install_git("https://git.rud.is/hrbrmstr/tcam.git") +``` + +NOTE: To use the ‘remotes’ install options you will need to have the +[{remotes} package](https://github.com/r-lib/remotes) installed. + +## Usage + +``` r +library(tcam) +library(ggplot2) # for plotting + +# current version +packageVersion("tcam") +## [1] '0.1.0' +``` + +Open a connection and get the status of the tCam: + +``` r +con <- tcam_connect() + +get_status(con) +## $status +## $status$Camera +## [1] "tCam-Mini-B3CD" +## +## $status$Model +## [1] 2 +## +## $status$Version +## [1] "1.3" +## +## $status$Time +## [1] "2:02:48.364" +## +## $status$Date +## [1] "1/1/-30" +``` + +Take a picture and plot it: + +``` r +img <- get_image(con) + +ggplot(tidy_radiometric(img)) + + geom_tile( + aes(x, y, fill = value), + color = NA + ) + + scale_fill_viridis_c( + name = "°F", + option = "magma" + ) + + coord_fixed() + + labs( + x = NULL, y = NULL + ) + + theme_minimal() + + theme( + axis.text.x.bottom = element_blank(), + axis.text.y.left = element_blank(), + panel.grid.major = element_blank(), + panel.grid.minor = element_blank() + ) +``` + + + +Done, so we close the connection. + +``` r +close(con) +``` + +## tcam Metrics + +| Lang | # Files | (%) | LoC | (%) | Blank lines | (%) | # Lines | (%) | +|:-----|--------:|-----:|----:|-----:|------------:|-----:|--------:|-----:| +| R | 6 | 0.33 | 74 | 0.28 | 18 | 0.21 | 51 | 0.28 | +| Rmd | 1 | 0.06 | 33 | 0.13 | 23 | 0.27 | 37 | 0.21 | +| YAML | 2 | 0.11 | 23 | 0.09 | 2 | 0.02 | 2 | 0.01 | +| SUM | 9 | 0.50 | 130 | 0.50 | 43 | 0.50 | 90 | 0.50 | + +clock Package Metrics for tcam + +## Code of Conduct + +Please note that this project is released with a Contributor Code of +Conduct. By participating in this project you agree to abide by its +terms. diff --git a/man/figures/README-ex-02-1.png b/man/figures/README-ex-02-1.png new file mode 100644 index 0000000..ab03b35 Binary files /dev/null and b/man/figures/README-ex-02-1.png differ diff --git a/man/get_image.Rd b/man/get_image.Rd new file mode 100644 index 0000000..dcf8b29 --- /dev/null +++ b/man/get_image.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/core.R +\name{get_image} +\alias{get_image} +\title{Returns a packet with metadata, radiometric (or AGC) image data and Lepton telemetry objects.} +\usage{ +get_image(con) +} +\arguments{ +\item{con}{open socket connection from \code{\link[=tcam_connect]{tcam_connect()}}} +} +\description{ +Returns a packet with metadata, radiometric (or AGC) image data and Lepton telemetry objects. +} diff --git a/man/get_status.Rd b/man/get_status.Rd new file mode 100644 index 0000000..4d73e84 --- /dev/null +++ b/man/get_status.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/core.R +\name{get_status} +\alias{get_status} +\title{Returns a packet with camera status.} +\usage{ +get_status(con) +} +\arguments{ +\item{con}{open socket connection from \code{\link[=tcam_connect]{tcam_connect()}}} +} +\description{ +Returns a packet with camera status. +} diff --git a/man/pipe.Rd b/man/pipe.Rd new file mode 100644 index 0000000..a648c29 --- /dev/null +++ b/man/pipe.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils-pipe.R +\name{\%>\%} +\alias{\%>\%} +\title{Pipe operator} +\usage{ +lhs \%>\% rhs +} +\arguments{ +\item{lhs}{A value or the magrittr placeholder.} + +\item{rhs}{A function call using the magrittr semantics.} +} +\value{ +The result of calling \code{rhs(lhs)}. +} +\description{ +See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. +} +\keyword{internal} diff --git a/man/tcam.Rd b/man/tcam.Rd index 3ad54db..14e952d 100644 --- a/man/tcam.Rd +++ b/man/tcam.Rd @@ -4,9 +4,13 @@ \name{tcam} \alias{tcam} \alias{tcam-package} -\title{...} +\title{Retrieve Radiometric Image Data from and Configure and Control tCam and tCam-Mini +Thermal Imaging Systems} \description{ -A good description goes here otherwise CRAN checks fail. +The tCam and tCam-Mini (\url{https://github.com/danjulio/lepton/tree/master/ESP32}) +are two cameras designed around the ESP32 chipset and provide easy access to +radiometric data from Lepton 3.5 sensors. Tools are provided to configure, control, +and receive radiometric data from tCam systems. } \seealso{ Useful links: diff --git a/man/tcam_connect.Rd b/man/tcam_connect.Rd new file mode 100644 index 0000000..0c119c3 --- /dev/null +++ b/man/tcam_connect.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/core.R +\name{tcam_connect} +\alias{tcam_connect} +\title{Make a socket connection to a tCam device} +\usage{ +tcam_connect(host = "192.168.4.1", port = 5001) +} +\arguments{ +\item{host, port}{IP/hostname + port; defaults to the device defaults} +} +\description{ +Make a socket connection to a tCam device +} diff --git a/man/tidy_radiometric.Rd b/man/tidy_radiometric.Rd new file mode 100644 index 0000000..e517411 --- /dev/null +++ b/man/tidy_radiometric.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{tidy_radiometric} +\alias{tidy_radiometric} +\title{Return a tidy data frame of Lepton radiometric data retrieved with \code{\link[=get_image]{get_image()}}} +\usage{ +tidy_radiometric(img_data) +} +\arguments{ +\item{img_data}{data structure retrieved with \code{\link[=get_image]{get_image()}}} +} +\value{ +data frame of \code{x}, \code{y}, and \code{value} +} +\description{ +Converts the base64 16-bit coded Kelvin radiometric data to a tidy "XYZ" +data frame in Fahrenheit. +}