Skip to contents

Functions able to directly read and validate data from .CSV files created by the data loggers built into YoctoPuce USB modules, and metadata extracted from a JSON file with the USB module settings.

Usage

read_yocto_datalog(
  file,
  settings.file = NULL,
  geocode = NULL,
  label = NULL,
  cols.pattern = NULL,
  cols.logical.names = FALSE,
  nacols.rm = TRUE,
  dec = ".",
  sep = ";",
  tz = "UTC",
  module.descriptor = NULL,
  ...
)

read_yocto_spctlog(
  file,
  settings.file = NULL,
  cols.pattern = "avg",
  cols.rename = TRUE,
  dec = ".",
  sep = ";",
  tz = "UTC",
  ...
)

Arguments

file

the name of the file which the data are to be read from. Each row of the table appears as one line of the file. If it does not contain an absolute path, the file name is relative to the current working directory, getwd(). Tilde-expansion is performed where supported. This can be a compressed file (see file).

Alternatively, file can be a readable text-mode connection (which will be opened for reading if necessary, and if so closed (and hence destroyed) at the end of the function call). (If stdin() is used, the prompts for lines may be somewhat confusing. Terminate input with a blank line or an signal, Ctrl-D on Unix and Ctrl-Z on Windows. Any pushback on stdin() will be cleared before return.)

file can also be a complete URL. (For the supported URL schemes, see the ‘URLs’ section of the help for url.)

settings.file

character Path to a JSON file containing the module settings used to acquire the data.

geocode

data.frame Containing columns lon and lat used to set attribute "where.measured".

label

character Additional text to be appended to the default value used to set attribute "comment".

cols.pattern

character A string suitable as argument for pattern in a call to grep() on column headings in the imported CSV file. NULL or characte(0) retain all data columns, while NA returns all data and time columns.

cols.logical.names

logical Use logical names from module metadata instead of column heading in CSV file. Require readable settings.file.

nacols.rm

logical If TRUE delete columns that contain only NA values.

dec

the character used in the file for decimal points.

sep

the field separator character. Values on each line of the file are separated by this character. If sep = "" (the default for read.table) the separator is ‘white space’, that is one or more spaces, tabs, newlines or carriage returns.

tz

a character string that specifies which time zone to parse the date with. The string must be a time zone that is recognized by the user's OS.

module.descriptor

list A matadata descriptor of the YocotoPuce USB module to be added as an attribute to the returned object.

...

Arguments passed on to utils::read.table

colClasses

character. A vector of classes to be assumed for the columns. If unnamed, recycled as necessary. If named, names are matched with unspecified values being taken to be NA.

Possible values are NA (the default, when type.convert is used), "NULL" (when the column is skipped), one of the atomic vector classes (logical, integer, numeric, complex, character, raw), or "factor", "Date" or "POSIXct". Otherwise there needs to be an as method (from package methods) for conversion from "character" to the specified formal class.

Note that colClasses is specified per column (not per variable) and so includes the column of row names (if any).

nrows

integer: the maximum number of rows to read in. Negative and other invalid values are ignored.

skip

integer: the number of lines of the data file to skip before beginning to read data.

check.names

logical. If TRUE then the names of the variables in the data frame are checked to ensure that they are syntactically valid variable names. If necessary they are adjusted (by make.names) so that they are, and also to ensure that there are no duplicates.

comment.char

character: a character vector of length one containing a single character or an empty string. Use "" to turn off the interpretation of comments altogether.

cols.rename

logical Flag, if TRUE use channel names from sensor IC specification as column names, and if FALSE keep the names used in the imported file.

Value

A data frame with POSIXct time stamps in column time and data in a variable number of columns containing values converted by read.csv().

Details

The dataloggers implemented in different USB modules from YoctoPuce return .CSV files with a consistent format, that varies only in the number of data columns and their names. Function read_yocto_datalog() reads any of these files preserving column names. The UTC times are converted into POSIXct values and added under column time. A subset of columns can be requested by passing a regular expression to be used in a call to grep() on the column names. If nacols.rm = TRUE is passed, columns containing only NA values are deleted, as these columns in most cases correspond to logger channels that are not in use.

Warnings are issued if something unexpected, such as dates several years into the past, unsorted or repeated time stamps are encountered in the sequence of UNIX time stamps in the file. These discrepancies can occur when the modules' or the YoctoHub clocks do not acquire a valid time at start-up. Inconsistent time steps are reported through a message, as these are the result of a stop followed by restart of logging. During such a pause it is possible that module settings could have been changed.

If the name of a JSON file as saved from the YoctoPuce module is passed as an argument to parameter settings.file its contents parsed into an R list are saved to attribute "yocto.module.settings" in the returned data frame. The metadata also make it possible to set column names to the logical names set in the module. The logical name of the module and the units are also extracted if available, formatted and saved in the "how.measured" attribute.

A comment attribute is always set with information about the imported file(s) and the import time and package.

Function read_yocto_spctlog() is a wrapper on read_yocto_datalog() that renames columns using the names used in the data sheet for the AS7343 sensor.

In modules with multiple channels, the user can enable and disable logging on a channel by channel basis. Thus, the number of data columns can vary, making it necessary to match columns by name when replacing some of the default names by shorter or more informative ones.

Warning!

The units and basis of expression, and in several cases even the physical quantity measured cannot be decoded from the CSV files. The values in the returned data frame are those read from the file, and the read values have to be interpreted based on the module settings which, scripts used during data acquisition by the USB module. These settings if available in a JSON file downloaded from the module, can be stored in attribute "yocto.module.settings" of the data frame returned.

I have access to several different USB modules from YoctoPuce, but not to all of them. There are currently some modules that are not fully supported, and a few others that "should" work but have not been yet tested.

References

Documentation for each YocotoPuce USB module is available at https://www.yoctopuce.com/.

Examples

library(photobiology)
#> Loading required package: SunCalcMeeus
#> Documentation at https://docs.r4photobiology.info/
# Yocto-Meteo module

yocto_meteo.file <-
  system.file("extdata", "yocto-meteo-snm.csv",
              package = "rYoctoPuceInOut", mustWork = TRUE)
yocto_meteo_json.file <-
  system.file("extdata", "METEOMK2-19A230.json",
              package = "rYoctoPuceInOut", mustWork = TRUE)

meteo1.df <- read_yocto_datalog(yocto_meteo.file)
#> Period: 2025-08-07 19:32:05 to 2025-08-07 22:50:00
#> Found gaps, time steps range from 55s to 60s (~1 minutes)
head(meteo1.df, n = 5)
#>                  time humidity.min humidity.avg humidity.max pressure.min
#> 1 2025-08-07 16:32:05       53.310       53.310       53.310     1012.712
#> 2 2025-08-07 16:33:05       53.043       53.352       53.715     1012.472
#> 3 2025-08-07 16:34:05       53.188       53.269       53.394     1012.398
#> 4 2025-08-07 16:35:05       53.219       53.482       53.684     1012.426
#> 5 2025-08-07 16:36:05       53.631       53.794       54.005     1012.413
#>   pressure.avg pressure.max temperature.min temperature.avg temperature.max
#> 1     1012.716     1012.717          23.495          23.495          23.495
#> 2     1012.548     1012.712          23.495          23.503          23.506
#> 3     1012.434     1012.477          23.495          23.501          23.506
#> 4     1012.467     1012.525          23.495          23.502          23.506
#> 5     1012.468     1012.525          23.506          23.510          23.517
cat(comment(meteo1.df))
#> Data logged by a YoctoPuce USB module.
#> Data file "yocto-meteo-snm.csv" created on 2026-02-08 16:52:24.
#> Imported on 2026-02-08 19:08:33 using TZ = "UTC" with 'rYoctoPuceInOut' (== 0.0.1.9001).
cat(how_measured(meteo1.df))
#> YoctoPuce USB module type 'unknown'.

read_yocto_datalog(yocto_meteo.file, cols.pattern = "avg") |>
  head(n = 5)
#> Period: 2025-08-07 19:32:05 to 2025-08-07 22:50:00
#> Found gaps, time steps range from 55s to 60s (~1 minutes)
#>                  time humidity.avg pressure.avg temperature.avg
#> 1 2025-08-07 16:32:05       53.310     1012.716          23.495
#> 2 2025-08-07 16:33:05       53.352     1012.548          23.503
#> 3 2025-08-07 16:34:05       53.269     1012.434          23.501
#> 4 2025-08-07 16:35:05       53.482     1012.467          23.502
#> 5 2025-08-07 16:36:05       53.794     1012.468          23.510
read_yocto_datalog(yocto_meteo.file, cols.pattern = "min|max") |>
  head(n = 5)
#> Period: 2025-08-07 19:32:05 to 2025-08-07 22:50:00
#> Found gaps, time steps range from 55s to 60s (~1 minutes)
#>                  time humidity.min humidity.max pressure.min pressure.max
#> 1 2025-08-07 16:32:05       53.310       53.310     1012.712     1012.717
#> 2 2025-08-07 16:33:05       53.043       53.715     1012.472     1012.712
#> 3 2025-08-07 16:34:05       53.188       53.394     1012.398     1012.477
#> 4 2025-08-07 16:35:05       53.219       53.684     1012.426     1012.525
#> 5 2025-08-07 16:36:05       53.631       54.005     1012.413     1012.525
#>   temperature.min temperature.max
#> 1          23.495          23.495
#> 2          23.495          23.506
#> 3          23.495          23.506
#> 4          23.495          23.506
#> 5          23.506          23.517
read_yocto_datalog(yocto_meteo.file, cols.pattern = "temperature") |>
  head(n = 5)
#> Period: 2025-08-07 19:32:05 to 2025-08-07 22:50:00
#> Found gaps, time steps range from 55s to 60s (~1 minutes)
#>                  time temperature.min temperature.avg temperature.max
#> 1 2025-08-07 16:32:05          23.495          23.495          23.495
#> 2 2025-08-07 16:33:05          23.495          23.503          23.506
#> 3 2025-08-07 16:34:05          23.495          23.501          23.506
#> 4 2025-08-07 16:35:05          23.495          23.502          23.506
#> 5 2025-08-07 16:36:05          23.506          23.510          23.517
read_yocto_datalog(yocto_meteo.file, nrows = 4L)
#> Period: 2025-08-07 19:32:05 to 2025-08-07 19:35:05
#>                  time humidity.min humidity.avg humidity.max pressure.min
#> 1 2025-08-07 16:32:05       53.310       53.310       53.310     1012.712
#> 2 2025-08-07 16:33:05       53.043       53.352       53.715     1012.472
#> 3 2025-08-07 16:34:05       53.188       53.269       53.394     1012.398
#> 4 2025-08-07 16:35:05       53.219       53.482       53.684     1012.426
#>   pressure.avg pressure.max temperature.min temperature.avg temperature.max
#> 1     1012.716     1012.717          23.495          23.495          23.495
#> 2     1012.548     1012.712          23.495          23.503          23.506
#> 3     1012.434     1012.477          23.495          23.501          23.506
#> 4     1012.467     1012.525          23.495          23.502          23.506

# metadata from JSON file
meteo2.df <- read_yocto_datalog(yocto_meteo.file, yocto_meteo_json.file)
#> Period: 2025-08-07 19:32:05 to 2025-08-07 22:50:00
#> Found gaps, time steps range from 55s to 60s (~1 minutes)
head(meteo2.df, n = 5)
#>                  time humidity.min humidity.avg humidity.max pressure.min
#> 1 2025-08-07 16:32:05       53.310       53.310       53.310     1012.712
#> 2 2025-08-07 16:33:05       53.043       53.352       53.715     1012.472
#> 3 2025-08-07 16:34:05       53.188       53.269       53.394     1012.398
#> 4 2025-08-07 16:35:05       53.219       53.482       53.684     1012.426
#> 5 2025-08-07 16:36:05       53.631       53.794       54.005     1012.413
#>   pressure.avg pressure.max temperature.min temperature.avg temperature.max
#> 1     1012.716     1012.717          23.495          23.495          23.495
#> 2     1012.548     1012.712          23.495          23.503          23.506
#> 3     1012.434     1012.477          23.495          23.501          23.506
#> 4     1012.467     1012.525          23.495          23.502          23.506
#> 5     1012.468     1012.525          23.506          23.510          23.517
cat(comment(meteo2.df))
#> Data logged by a YoctoPuce USB module.
#> Data file "yocto-meteo-snm.csv" created on 2026-02-08 16:52:24.
#> Metadata file "METEOMK2-19A230.json" created on 2026-02-08 16:52:24.
#> Imported on 2026-02-08 19:08:33 using TZ = "UTC" with 'rYoctoPuceInOut' (== 0.0.1.9001).
cat(how_measured(meteo2.df))
#> YoctoPuce USB module named 'C2-Meteo' type 'Yocto-Meteo-V2',
#> s.n. 'METEOMK2-19A230' with firmware '69970'.
#> Units: humidity: % RH, pressure: mbar, temperature: °C.

meteo3.df <- read_yocto_datalog(yocto_meteo.file,
                                   yocto_meteo_json.file,
                                   cols.logical.names = TRUE)
#> Period: 2025-08-07 19:32:05 to 2025-08-07 22:50:00
#> Found gaps, time steps range from 55s to 60s (~1 minutes)
head(meteo3.df, n = 5)
#>                  time C2_humidity.min C2_humidity.avg C2_humidity.max
#> 1 2025-08-07 16:32:05          53.310          53.310          53.310
#> 2 2025-08-07 16:33:05          53.043          53.352          53.715
#> 3 2025-08-07 16:34:05          53.188          53.269          53.394
#> 4 2025-08-07 16:35:05          53.219          53.482          53.684
#> 5 2025-08-07 16:36:05          53.631          53.794          54.005
#>   C2_pressure.min C2_pressure.avg C2_pressure.max C2_temperature.min
#> 1        1012.712        1012.716        1012.717             23.495
#> 2        1012.472        1012.548        1012.712             23.495
#> 3        1012.398        1012.434        1012.477             23.495
#> 4        1012.426        1012.467        1012.525             23.495
#> 5        1012.413        1012.468        1012.525             23.506
#>   C2_temperature.avg C2_temperature.max
#> 1             23.495             23.495
#> 2             23.503             23.506
#> 3             23.501             23.506
#> 4             23.502             23.506
#> 5             23.510             23.517
cat(comment(meteo3.df))
#> Data logged by a YoctoPuce USB module.
#> Data file "yocto-meteo-snm.csv" created on 2026-02-08 16:52:24.
#> Metadata file "METEOMK2-19A230.json" created on 2026-02-08 16:52:24.
#> Imported on 2026-02-08 19:08:33 using TZ = "UTC" with 'rYoctoPuceInOut' (== 0.0.1.9001).
cat(how_measured(meteo3.df))
#> YoctoPuce USB module named 'C2-Meteo' type 'Yocto-Meteo-V2',
#> s.n. 'METEOMK2-19A230' with firmware '69970'.
#> Units: C2_humidity: % RH, C2_pressure: mbar, C2_temperature: °C.
str(attr(meteo3.df, "yocto.module.settings"), max.level = 2)
#> List of 3
#>  $ api   :List of 5
#>   ..$ module     :List of 13
#>   ..$ humidity   :List of 15
#>   ..$ pressure   :List of 13
#>   ..$ temperature:List of 17
#>   ..$ dataLogger :List of 9
#>  $ extras: list()
#>  $ files : list()

# Yocto-Spectral module

yocto_spectral.file <-
  system.file("extdata", "yocto-spectral-LED.csv",
              package = "rYoctoPuceInOut", mustWork = TRUE)
yocto_spectral_json.file <-
  system.file("extdata", "SPECTRL1-2CF3B6.json",
              package = "rYoctoPuceInOut", mustWork = TRUE)

read_yocto_spctlog(yocto_spectral.file) |> head(n = 5)
#> Period: 2025-12-03 21:54:00 to 2025-12-03 22:52:14
#> Found gaps, time steps range from 10s to 60s (~1 minutes)
#>                  time      F1.avg      F2.avg      FZ.avg      F3.avg
#> 1 2025-12-03 19:54:00  0.00000000  0.00000000  0.01923449  0.00000000
#> 2 2025-12-03 19:55:00 14.81709593 13.26026119 10.70854803 14.03453598
#> 3 2025-12-03 19:56:00  0.20996641  0.62779851  1.43448786  1.28698813
#> 4 2025-12-03 19:57:00  0.01586413  0.01212687  0.01720980  0.01690788
#> 5 2025-12-03 19:58:00  0.01586413  0.01212687  0.01619746  0.01690788
#>        F4.avg      FY.avg      F5.avg     FXL.avg      F6.avg      F7.avg
#> 1  0.01892148  0.08539738  0.00000000  0.09671708  0.08235444  0.06817170
#> 2 14.68704875 14.28618803 17.99289470 19.16909935 17.43903218 68.53901431
#> 3  1.30558184  0.45975569  0.24968026  0.66015027  1.58963228 59.34804452
#> 4  0.01593387  0.01985986  0.01890010  0.02136773  0.02010981  0.02340223
#> 5  0.01493801  0.01787387  0.01691062  0.01799387  0.01436415  0.01933227
#>        F8.avg     NIR.avg     VIS.avg
#> 1  0.00000000 0.000000000  0.08138610
#> 2 69.80591451 3.403664712 37.22971629
#> 3 57.34681909 0.720682303 50.17541353
#> 4  0.02057654 0.003291578  0.02034652
#> 5  0.01943340 0.003464819  0.01592337
read_yocto_spctlog(yocto_spectral.file, cols.pattern = "Channel1\\.") |>
  head(n = 5)
#> Period: 2025-12-03 21:54:00 to 2025-12-03 22:52:14
#> Found gaps, time steps range from 10s to 60s (~1 minutes)
#>                  time      F1.min      F1.avg       F1.max
#> 1 2025-12-03 19:54:00 0.000000000  0.00000000   0.00000000
#> 2 2025-12-03 19:55:00 0.000000000 14.81709593 138.04031355
#> 3 2025-12-03 19:56:00 0.000000000  0.20996641   1.31112355
#> 4 2025-12-03 19:57:00 0.006532288  0.01586413   0.02053005
#> 5 2025-12-03 19:58:00 0.006532288  0.01586413   0.02053005
read_yocto_spctlog(yocto_spectral.file, cols.rename = FALSE) |>
  head(n = 5)
#> Period: 2025-12-03 21:54:00 to 2025-12-03 22:52:14
#> Found gaps, time steps range from 10s to 60s (~1 minutes)
#>                  time spectralChannel1.avg spectralChannel2.avg
#> 1 2025-12-03 19:54:00           0.00000000           0.00000000
#> 2 2025-12-03 19:55:00          14.81709593          13.26026119
#> 3 2025-12-03 19:56:00           0.20996641           0.62779851
#> 4 2025-12-03 19:57:00           0.01586413           0.01212687
#> 5 2025-12-03 19:58:00           0.01586413           0.01212687
#>   spectralChannel3.avg spectralChannel4.avg spectralChannel5.avg
#> 1           0.01923449           0.00000000           0.01892148
#> 2          10.70854803          14.03453598          14.68704875
#> 3           1.43448786           1.28698813           1.30558184
#> 4           0.01720980           0.01690788           0.01593387
#> 5           0.01619746           0.01690788           0.01493801
#>   spectralChannel6.avg spectralChannel7.avg spectralChannel8.avg
#> 1           0.08539738           0.00000000           0.09671708
#> 2          14.28618803          17.99289470          19.16909935
#> 3           0.45975569           0.24968026           0.66015027
#> 4           0.01985986           0.01890010           0.02136773
#> 5           0.01787387           0.01691062           0.01799387
#>   spectralChannel9.avg spectralChannel10.avg spectralChannel11.avg
#> 1           0.08235444            0.06817170            0.00000000
#> 2          17.43903218           68.53901431           69.80591451
#> 3           1.58963228           59.34804452           57.34681909
#> 4           0.02010981            0.02340223            0.02057654
#> 5           0.01436415            0.01933227            0.01943340
#>   spectralChannel12.avg spectralChannel13.avg
#> 1           0.000000000            0.08138610
#> 2           3.403664712           37.22971629
#> 3           0.720682303           50.17541353
#> 4           0.003291578            0.02034652
#> 5           0.003464819            0.01592337

# metadata from JSON file
spectral.df <-
  read_yocto_spctlog(yocto_spectral.file,
                          yocto_spectral_json.file)
#> Period: 2025-12-03 21:54:00 to 2025-12-03 22:52:14
#> Found gaps, time steps range from 10s to 60s (~1 minutes)
cat(how_measured(spectral.df))
#> YoctoPuce USB module named 'spectrl-01' type 'Yocto-Spectral',
#> s.n. 'SPECTRL1-2CF3B6' with firmware '69970'.
#> Units: not available.
cat(comment(spectral.df))
#> Data logged by a YoctoPuce USB module.
#> Data file "yocto-spectral-LED.csv" created on 2026-02-08 16:52:24.
#> Metadata file "SPECTRL1-2CF3B6.json" created on 2026-02-08 16:52:24.
#> Imported on 2026-02-08 19:08:33 using TZ = "UTC" with 'rYoctoPuceInOut' (== 0.0.1.9001).