Skip to content

Writing Scripts

Scripts work by looping through the data coming from the sensors. Each iteration you gather the data of that timestamp using a provided funtion, and then do something with that data. Each script uses this core concept.

Limitations

Scripts run in realtime, this means that each loop must complete within the update rate of the sensors. The realtime data would otherwise get out of sync.

Testing Scripts

Scripts can be tested locally using the test-script utility. To test a script first clone and install the project as described in Getting Started, enter the src/next directory, run the command npm run test-script --. The script requires 2 options, the script to test and a CSV file with sensor data.

$ npm run test-script --                                                                                             

> team-nl-iot@0.1.0 test-script
> node utils/test-script.mjs

Usage: test-script -- -s <script> -c <csv> [options]

Test scripts locally before uploading

Options:
  -V, --version               output the version number
  -s, --script <script>       path to the script to test
  -c, --csv <csv>             path to CSV file containing data
  -l, --language <extension>  script language (script extension by default) [py, r]
  -h, --help                  display help for command

Read the documentation: https://iot.dev.hihva.nl/2022-2023-sep-jan/group-project/team-nl-beachvolley-data-collection/features/writing-scripts/

Example

$ npm run test-script -- -s my_script.R -c my_csv.csv

Progress [==============--------------------------] 34% | 821/2376 Rows | ETA: 10s

Python Scripts

The main function of a Python script should take three parameters:

  • raw_data - The “raw” data coming from the sensors
  • parse_data(<raw_data>) - A function to parse the raw data, returns a data objects
  • save_value(<value>, <timestamp>) - A function to save a value to the database, this will create a point in the output you select when uploading the script

In the main function create a for loop looping through the items of raw_data, for each iteration retrieve the parsed data using the parse_data function.

Examples

Line Chart - Heartbeat every 5 seconds

# script entrypoint
def main(raw_data, parse_data, save_value):
    UPDATE_RATE = 5000
    last_timestamp = 0

    # loop through the data coming from the sensors
    for i in raw_data:
        # retrieve the parsed data
        data = parse_data(i)

        # do something with the data
        if data['timestamp'] - last_timestamp > UPDATE_RATE:
            save_value(data['heartbeat'], data['timestamp'])
            last_timestamp = data['timestamp']

R Scripts

The main function of an R script should take two parameters:

  • get_data() - A function to get the the next set of data from the sensors, returns a list()
  • save_value(<value>, <timestamp>) - A function to save a value to the database, this will create a point in the output you select when uploading the script

In the main function create an infinite loop. For each loop retrieve the sensor data at that moment using the get_data() function.

To use libraries, create a global variable named packages with i’s value being a vector of library names as strings.

Examples

Bar Chart - Jump heights

# define libraries
packages <- c("pracma", "dplyr")

# script entrypoint
main <- function(get_data, save_value) {
    UPDATE_RATE = 3000
    last_timestamp <- 0
    first <- TRUE
    x <- c()
    y <- c()

    # start an infinite loop
    while (TRUE) {
        # retrieve the sensor data
        data <- get_data()

        if (is.null(data$timestamp)) {
            next
        }

        if (first) {
            last_timestamp <- data$timestamp
            first <- FALSE
        }

        x <- append(x, data$timestamp)
        y <- append(y, data$gy)

        if (data$timestamp > last_timestamp + UPDATE_RATE) {
            last_timestamp <- data$timestamp

            # time in seconds
            x <- (lag(x) - x)
            x [is.na(x)] <- 0
            x <- cumsum(x)/1000

            # flip
            x <- abs(-x)
            y <- -y

            # Create a new smooth-data df
            xy_df <- data.frame(x,y)

            # find peaks
            peaks <- findpeaks(xy_df$y,  threshold = 5)

            if (is.null(peaks)) {
                # no peaks founds, abort
                next
            }

            #edit data to match with x-coordinates
            peaks <- as.data.frame(peaks)
            peaks <- as.data.frame(peaks$V1)

            colnames(peaks)[1] <- "y"
            peaks <- merge(xy_df,peaks)

            peaks <- peaks[!(peaks$y < -5),]

            time_x <- 0.3
            peaks <- peaks[order(peaks$x),]
            jumps_df <- peaks %>%  mutate(time_diff = (x - lag(x)))
            jumps_df$time_diff [is.na(jumps_df$time_diff)] <- time_x + 2
            jumps_df <- jumps_df[!(jumps_df$time_diff < time_x),]
            jumps_df <- jumps_df[!lag(jumps_df$time_diff < 1.0) & (jumps_df$time_diff >0.2),]

            min_time <- 0.1
            max_time <- 1

            #calculating jump height
            jumps_height_df <- subset(jumps_df, time_diff >= min_time & time_diff <= max_time)
            jumps_height_df <- jumps_height_df %>%  mutate(height = (0.5*9.81*(time_diff/2)^2))


            for (height in jumps_height_df$height) {
                save_value(height, data$timestamp)
            }

            x <- c()
            y <- c()
        }
    }
}

Last update: January 29, 2023