# How AtomCam Recording Schedules Work with Weekday and Time Range Selection

> Learn how AtomCam recording schedules work by converting user selections into cron strings which are then used to trigger recordings at precise intervals.

- Repository: [Mitsuru Nakada/atomcam_tools](https://github.com/mnakada/atomcam_tools)
- Tags: how-to-guide
- Published: 2026-03-07

---

**AtomCam converts user-selected weekdays and time ranges into cron-style strings that are stored in [`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini) and later transformed into system crontab entries by [`set_crontab.sh`](https://github.com/mnakada/atomcam_tools/blob/main/set_crontab.sh) to trigger recording scripts at precise intervals.**

The `mnakada/atomcam_tools` repository provides a Vue-based web interface and shell scripts that manage periodic and alarm-based recording schedules. Understanding how recording schedules work with weekday and time range selection requires examining the data pipeline from the UI components through configuration storage to the final cron execution.

## UI Components for Weekday and Time Selection

The schedule editor interface is defined in **[`web/source/vue/SettingSchedule.vue`](https://github.com/mnakada/atomcam_tools/blob/main/web/source/vue/SettingSchedule.vue)**. This component renders the weekday checkboxes, time range pickers, and "All day" toggle that users interact with.

### Weekday Selection Interface

Weekday selection uses an array of numbers (`0-6`) bound to `innerValue.dayOfWeekSelect`, where Monday equals `0` and Sunday equals `6`. The component renders these as checkbox buttons using Element UI's checkbox group.

```vue
<!-- web/source/vue/SettingSchedule.vue -->
<ElCheckboxGroup v-model="innerValue.dayOfWeekSelect" @input="TimeSet">
  <ElCheckboxButton 
    v-for="(day, i) of $t('schedule.weekDays')" 
    :label="i" 
    :key="i">
    {{ day }}
  </ElCheckboxButton>
</ElCheckboxGroup>

```

When users select specific days, the component emits the updated array via the `TimeSet()` method to the parent component.

### Time Range Controls and "All Day" Toggle

The time range selection uses two `ElTimePicker` components for start and end times. When the "All day" switch is enabled, the component automatically sets `startTime = "00:00"` and `endTime = "23:59"`.

```vue
<!-- Time range picker with all-day toggle -->
<ElSwitch v-model="allDay" @input="TimeSet" />
<ElTimePicker v-model="innerValue.startTime" />
<ElTimePicker v-model="innerValue.endTime" />

```

Each interaction triggers `TimeSet()`, which emits the complete schedule object containing the weekday array and time strings to the parent [`Setting.vue`](https://github.com/mnakada/atomcam_tools/blob/main/Setting.vue) component.

## Converting UI Data to Cron-Style Configuration

The parent component **[`web/source/vue/Setting.vue`](https://github.com/mnakada/atomcam_tools/blob/main/web/source/vue/Setting.vue)** (specifically around lines 735-770) receives schedule objects and converts them into the cron-style format required by the camera firmware. This conversion happens when users click the Save button.

### The Data Transformation Logic

The conversion uses JavaScript's `reduce()` method to build a string where each schedule entry becomes a cron line. The code performs three critical transformations:

1. **Time parsing**: Splits the `HH:MM` format into separate minute and hour fields
2. **Weekday mapping**: Converts the internal Monday-based index (0) to cron's Sunday-based index (0) using `((d + 1) % 7)`
3. **Delimiter conversion**: Joins multiple weekdays with colons (`:`) for storage

```javascript
// web/source/vue/Setting.vue (lines ~735-770)
this.config.PERIODICREC_SCHEDULE = this.periodicRecSchedule.reduce((str, schedule) => {
  // Extract minutes and hours from time string
  str += parseInt(schedule.startTime.slice(-2)) + ' ' + 
         parseInt(schedule.startTime.slice(0, 2)) + ' * * ' +
         // Convert Monday=0 to Sunday=0 cron format
         schedule.dayOfWeekSelect.sort((a, b) => a - b)
                 .reduce((v, d) => v + (v.length ? ':' : '') + ((d + 1) % 7).toString(), '') +
         ' /scripts/periodic_rec.sh start;';
  return str;
}, '');

```

This produces entries where weekdays like Monday through Friday (`0:1:2:3:4` internally) become `1:2:3:4:5` in the cron format (representing Monday through Friday in cron terms).

## Storing Schedules in hack.ini

The generated strings are saved to the camera's **[`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini)** configuration file under specific keys: `PERIODICREC_SCHEDULE`, `ALARMREC_SCHEDULE`, or `TIMELAPSE_SCHEDULE`. These entries follow a semi-colon separated format where each segment represents one cron job.

```

# Example hack.ini entry for daily recording at 04:00

PERIODICREC_SCHEDULE=0 4 * * 0:1:2:3:4:5:6 /scripts/periodic_rec.sh start;

```

**Field breakdown:**
- **Minute**: `0` (from startTime)
- **Hour**: `4` (from startTime)  
- **Day-of-month**: `*` (any day)
- **Month**: `*` (any month)
- **Day-of-week**: `0:1:2:3:4:5:6` (Sunday through Saturday, colon-separated)
- **Command**: Path to the recording script

The colon-separated weekday format is an intermediate representation that the system later converts to comma-separated values for the actual crontab.

## Generating the System Crontab

The script **[`overlay_rootfs/scripts/set_crontab.sh`](https://github.com/mnakada/atomcam_tools/blob/main/overlay_rootfs/scripts/set_crontab.sh)** runs during boot or when settings change. It reads the `*_SCHEDULE` entries from [`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini) and transforms them into valid cron syntax.

### The AWK Parsing Logic

The script uses AWK to process each schedule line, splitting entries by semicolons and converting the weekday delimiters from colons to commas:

```bash

# overlay_rootfs/scripts/set_crontab.sh

/^TIMELAPSE_SCHEDULE *=/ {
  split($2, schedule, ";");
  for(i in schedule) {
    if(schedule[i] == "") continue;
    gsub(/:/,",", schedule[i]);      # Convert "0:1:2" to "0,1,2"

    printf("%s %d\n", schedule[i], i);  # Append job index

  }
}

```

After processing, the output is piped to `crontab -`, installing entries like:

```cron
0 4 * * 0,1,2,3,4,5,6 /scripts/periodic_rec.sh start 1

```

The trailing number (`1`) represents the schedule index, allowing the script to handle multiple schedule entries for the same recording type.

## Complete Data Flow from UI to Execution

The pipeline follows five distinct stages:

1. **User Input**: Selections in [`SettingSchedule.vue`](https://github.com/mnakada/atomcam_tools/blob/main/SettingSchedule.vue) emit objects containing `dayOfWeekSelect` arrays and time strings
2. **String Construction**: [`Setting.vue`](https://github.com/mnakada/atomcam_tools/blob/main/Setting.vue) reduces these objects into semi-colon separated cron-style strings with Monday-to-Sunday offset correction
3. **Configuration Storage**: Strings are written to [`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini) under keys like `PERIODICREC_SCHEDULE`
4. **Crontab Generation**: [`set_crontab.sh`](https://github.com/mnakada/atomcam_tools/blob/main/set_crontab.sh) parses [`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini), expands weekday lists, and installs entries to the system cron
5. **Execution**: The Linux cron daemon triggers [`/scripts/periodic_rec.sh`](https://github.com/mnakada/atomcam_tools/blob/main//scripts/periodic_rec.sh) (or equivalent) at the specified minutes, hours, and weekdays

## Summary

- **SettingSchedule.vue** provides the UI for weekday checkboxes (Monday=0 to Sunday=6) and time range selection with an "All day" shortcut.
- **Setting.vue** converts UI data to cron strings, mapping Monday-based indices to cron's Sunday-based format using modulo arithmetic.
- Schedule strings are stored in [`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini) with colon-separated weekdays and semi-colon separated entries.
- **set_crontab.sh** transforms these strings into valid crontab entries by converting colons to commas and appending job indices.
- The system supports three schedule types: `PERIODICREC_SCHEDULE`, `ALARMREC_SCHEDULE`, and `TIMELAPSE_SCHEDULE`.

## Frequently Asked Questions

### Why does the AtomCam schedule use Monday=0 instead of standard cron Sunday=0?

The Vue component [`SettingSchedule.vue`](https://github.com/mnakada/atomcam_tools/blob/main/SettingSchedule.vue) uses Monday=`0` through Sunday=`6` to match common international ISO standards for weekday numbering. The conversion logic in [`Setting.vue`](https://github.com/mnakada/atomcam_tools/blob/main/Setting.vue) applies `((d + 1) % 7)` to transform these values into cron's Sunday=`0` format before writing to [`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini). This ensures the UI remains intuitive while maintaining compatibility with Linux cron syntax.

### How does the "All day" toggle affect the time range configuration?

When the "All day" switch is enabled in [`SettingSchedule.vue`](https://github.com/mnakada/atomcam_tools/blob/main/SettingSchedule.vue), the component automatically forces `startTime` to `"00:00"` and `endTime` to `"23:59"` before emitting the schedule object. This ensures continuous recording throughout the entire 24-hour period without requiring manual time entry.

### Can multiple recording schedules be active simultaneously?

Yes. The configuration system supports multiple entries by separating them with semicolons in the [`hack.ini`](https://github.com/mnakada/atomcam_tools/blob/main/hack.ini) values. Each entry generates a distinct cron line with a unique index number appended. For example, two periodic schedules would create two lines in the crontab, each ending with `1` and `2` respectively, allowing [`/scripts/periodic_rec.sh`](https://github.com/mnakada/atomcam_tools/blob/main//scripts/periodic_rec.sh) to identify which schedule triggered the execution.

### What happens if no weekdays are selected in the schedule?

The [`set_crontab.sh`](https://github.com/mnakada/atomcam_tools/blob/main/set_crontab.sh) script filters out empty schedule entries using the condition `if(schedule[i] == "") continue`. If no weekdays are selected, the resulting empty string is skipped during crontab generation, effectively disabling that schedule entry without causing syntax errors in the cron configuration.