Как сделать таймер в 1с

Обновлено: 07.07.2024


В Redmine есть учет времени. Вот только не всегда с ним работают. Одна из объективных причин - неудобный ввод активности. Данная обработка предлагает еще один способ автоматизировать деятельность по сбору времени.

Особенности обработки

  • Список последних задач с активностью, комментариями и почасовкой
  • Включение таймера одним кликом по задаче
  • Возможность добавить/убавить/ввести вручную нужный период
  • Быстрый просмотр данных по самой задаче и возможность перехода в redmine

Простой интерфейс, где все под рукой:


Варианты использования таймера

Таймер кроме основной функции фиксации временных затрат позволяет ответить и на другие вопросы:

На чем я остановился в прошлый раз?

Если писать в комментариях конкретику, т.е. не просто "писал отчет", а развернуто протоколировать:

наброски скд. Не идут остатки
Проконсультировался с бухгалтером, следует учесть корректировки
Учитываю корректировки

Тогда при "возвращении" к задаче можно легко при помощи этих крючков "погрузиться" в нужный контекст.

Отвлекают по другим задачам.

Как узнать сколько вы тратите на работу именно по этой задаче? Вы честно включили таймер, поработали десять минут и тут вас отвлекли. Например, подошел коллега и спросил мелочь, которая вылилась в полноценное обсуждение и отняла где-то час. Знакомо? В итоге таймер зачел время, но совсем по другой задаче.

В тот момент когда коллега подошел и задал вопрос можно переключиться на другую задачу "Консультирование коллег", которая всегда где-то в дежурных. В итоге таймер зачтет деятельность по обеим задачам.

Можно сформировать отчет по задачам для печати.

Более функциональный отчет по сравнению с Redmine для совещаний.

Настройка

Сначала получаем токен из redmine:


Указываем URL Redmine, прокси-сервер, если нужно:


А также есть некоторые функциональные и интерфейсные настройки:


Поехали

Открываем в любой конфигурации (хоть в пустой и файловой) как внешнюю обработку, или подключаем как дополнительную в безопасном режиме. При запуске таймер получает данные о последней вашей активности из redmine и заполняет соответствующие таблицы на форме.

Важно! Если по задаче активности не было - в списке последних задач ее не будет. Но если задачи нет в списке - не беда, найти ее можно через поле Поиск задачи по номеру.

После выбора задачи таймер начинает отсчет. Снизу от таймера указываем вид деятельности и комментарий.

Значение таймера можно редактировать как простое поле. Интересные кнопки рядом с таймером Зафиксировать и Сброс. Первая останавливает таймер и отправляет данные в Redmine. Вторая останавливает таймер без сброса.

Вместо сотен слов краткое видео

Базовые возможности таймера в действии (Версия 1.1):

Изменения в версиях

Версия 1.5 (30.05.2020)

  • Поддерживается работа с переадресацией запросов

Версия 1.4 (27.05.2020)

  • Добавлен "Отчет по задаче" для печати связанных задач
  • Исправлена ошибка при открытии обработки с неправильными настройками соединения

Версия 1.3 (15.03.2020)

  • Возможность быстрого переключения между задачами двумя кликам
  • Настройка выбора заполнения при старте таймера вида деятельности и комментария под себя: очищать, заполнять последними, оставить как есть
  • Интерфейс:

- Кнопка открыть текущую задачу в Redmine
- Кнопка скрыть решенные задачи (настраиваемый список статусов)
- Настройка расположения кнопок таймера
- Настройка изменения размера шрифта кнопок таймера

Версия 1.2 (12.02.2020)

  • Добавлена настройка расположение кнопок таймера под разные ширины экрана
  • Добавлены настройки поведения заполнения при старте таймера


Версия 1.0 (03.01.2020)

Совместимость

Протестировано на платформе 1С: 8.3.16.1148, 8.3.13.1644, а также в режиме совместимости с 8.3.12 на УТ 11.4.11.55
redmine: 4.1.0.stable, 3.0.4.stable

Создание конфигурации для мобильного приложения

Требуемые разрешения мобильного приложения

Таймер средствами 1С

Также на форме в процессе работы таймера будет показан индикатор, выполняться обратный отсчет и показываться текущее время и время окончания работы таймера

Создадим обработку Таймер и основную форму

Обработка Таймер

Вывод PUSH-уведомлений реализуется так:

В коде выполняется управление доступностью кнопок запуска и остановки таймера в зависимости от его состояния (запущен таймер, либо остановлен) – осталось установить первоначальную видимость этих кнопок при открытии формы:

Статистика – диаграмма

Создадим обработку Статистика и основную форму

Обработка Статистика

Полную реализацию Вы можете посмотреть во вложенном файле конфигурации. Сейчас рассмотрим программный вывод анимированной диаграммы на форму

Управление рекламой

Управление рекламой

Включение показа рекламного баннера реализуем в Модуле управляемого приложения в процедуре ПриНачалеРаботыСистемы():

В строке ОР.SetAdBannerID("ca-app-pub-1356011826682846/4780285411") в параметре процедуры SetAdBannerID укажите Идентификатор рекламного блока, полученный в AddMod (


Начнём с того, откуда вообще микроконтроллер знает, сколько проходит времени. Ведь у него нет часов! Для работы микроконтроллера жизненно важен так называемый тактовый генератор, или кварцевый генератор, или он же кварц. Он же oscillator, он же clock. Clock по-английски это часы. Да, но не всё так просто =) Кварц расположен рядом с МК на плате (также во многих МК есть встроенный тактовый генератор), на Ардуинах обычно стоит генератор на 16 МГц, также встречаются модели на 8 МГц. Тактовый генератор выполняет очень простую вещь: он “пинает” микроконтроллер со своей тактовой частотой, то есть 16 МГц кварц пинает МК 16 миллионов раз в секунду. Микроконтроллер, в свою очередь зная частоту кварца, может прикинуть время между пинками (16 МГц = 0.0625 микросекунды), и таким образом ориентироваться во времени. Но на деле не всё так просто, потому что принимают пинки таймера так называемые таймеры-счётчики (Timer-counter). Это физически расположенные внутри МК устройства, которые занимаются подсчётом пинков тактового генератора. И вот микроконтроллер уже может обратиться к счётчику и спросить, а сколько там натикало? И счётчик ему скажет. И вот этим мы уже можем пользоваться, для этого у Ардуино есть готовые функции времени. В Arduino на базе ATmega328 имеются три счётчика, и подсчётом времени занимается таймер под номером 0. Этим может заниматься любой другой счётчик, но работая в Arduino IDE вы сразу получаете такую настройку, т.к. создавая скетч в Arduino IDE вы автоматически работаете с библиотекой Arduino.h, где и реализованы все удобные функции.

Задержки

Простейшей с точки зрения использования функцией времени является задержка, их у нас две:

  • delay(time) – “приостанавливает” выполнение кода на time миллисекунд. Дальше функции delay() выполнение кода не идёт, за исключением прерываний. Использовать рекомендуется только в самых крайних или тех случаях, когда delay не влияет на скорость работы устройства. time принимает тип данных unsigned long и может приостановить выполнение на срок от 1 мс до ~50 суток (4 294 967 295 миллисекунд) с разрешением в 1 миллисекунду. Работает на системном таймере Timer 0, поэтому не работает внутри прерывания и при отключенных прерываниях.
  • delayMicroseconds(time) – Аналог delay() , приостанавливает выполнение кода на time микросекунд. time принимает тип данных unsigned int и может приостановить выполнение на срок от 4 до 16383 мкс с разрешением 4 мкс. Важно: delayMicroseconds работает не на таймере, как остальные функции времени в Arduino, а на счёте тактов процессора. Из этого следует, что delayMicroseconds может работать в прерывании и при отключенных прерываниях.

Задержки использовать очень просто:

И вот мы можем делать какое-то действие два раза в секунду. delayMicroseconds() иногда не совсем корректно работает с переменными, нужно стараться использовать константы ( const или просто число). Для создания микросекундных задержек с переменным периодом и корректной работы в циклах лучше использовать следующую конструкцию:

А что делать, если нам нужно выполнять одно действие два раза в секунду, а другое – три? А третье – 10 раз в секунду например. Сразу привыкаем к той мысли, что задержки лучше вообще не использовать в реальном коде. Разве что delayMicroseconds() , он бывает нужен для генерации каких-то протоколов связи. Нормальным инструментом для тайм-менеджмента своего кода являются функции, которые считают время со старта МК.

Функция yield()

Разработчики Arduino позаботились о том, чтобы функция delay() не просто блокировала выполнение кода, но и позволяла выполнять другой код во время этой задержки. Данный “костыль” получил название yield() и работает следующим образом: если объявить функцию

то расположенный внутри неё код будет выполняться во время работы любой задержки delay() в программе! Это решение хоть и кажется нелепым, но в то же время позволяет быстро и без описания лишних костылей и таймеров реализовать пару параллельно выполняющихся задач. Что вполне соответствует назначению Ардуино – максимально простая и быстрая разработка прототипа. Рассмотрим например такой простой пример: стандартный мигающий светодиод, но с опросом кнопки

Подробнее о том, как работать с yield() и строить программу на её основе мы рассмотрим в одном из следующих уроков о том, как написать скетч.

Функции счёта времени

Данные функции возвращают время, прошедшее с момента запуска микроконтроллера, так называемый аптайм (англ. uptime). Таких функций у нас две:

  • millis() – Возвращает количество миллисекунд, прошедших с запуска. Возвращает unsigned long , от 1 до 4 294 967 295 миллисекунд (~50 суток), имеет разрешение 1 миллисекунда, после переполнения сбрасывается в 0. Работает на системном таймере Timer 0
  • micros() – Возвращает количество микросекунд, прошедших с запуска. Возвращает unsigned long , от 4 до 4 294 967 295 микросекунд (~70 минут), имеет разрешение в 4 микросекунды, после переполнения сбрасывается в 0. Работает на системном таймере Timer 0

Таймер на millis()

Вы спросите, а как время со старта МК поможет нам организовать действия по времени? Очень просто, схема вот такая:

  • Выполнили действие
  • Запомнили текущее время со старта МК (в отдельную переменную)
  • Ищем разницу между текущим временем и запомненным
  • Как только разница больше нужного нам времени “Таймера” – выполняем действие
  • “Сбрасываем” таймер
    • Тут есть два варианта, приравнивать переменную таймера к актуальному millis(), или увеличивать её на размер периода

    Тип 1

    Реализация классического “таймера на millis()” выглядит вот так:

    Данная конструкция “уходит” с периода, если в коде есть задержки и прочие блокирующие участки, во время выполнения которых millis() успевает увеличиться на большее чем период время, и в перспективе период будет немного “уходить”! Это может быть критично например для счёта времени и других похожих ситуаций, когда период срабатывания таймера не должен “смещаться” относительно текущего времени. В то же время, если заблокировать выполнение кода на время, большее чем один период – таймер скорректирует эту разницу, так как мы его сбрасываем актуальным значением millis() .

    Тип 2

    Второй вариант сброса таймера будет записан вот так:

    Эта конструкция жёстко отрабатывает период, то есть не “уходит” со временем, если в коде присутствует малая задержка, потому что время следующего срабатывания всегда кратно периоду. Минусом здесь является то, что если таймер пропустит период – он “сработает” несколько раз при следующей проверке! Но из этой неприятной ситуации есть выход.

    Тип 3

    Можно посчитать, на сколько периодов нужно “обновить” переменную таймера. Например так:

    Здесь я заранее считаю прошедшее после последнего срабатывания время и записываю в переменную timeLeft , потому что оно нам ещё понадобится. К переменной таймера мы прибавляем период, умноженный на количество переполнений. Если вызов таймера не был пропущен – то умножать мы будем на 1. Целочисленное деление (timeLeft / period) позволяет получить целое количество переполнений, поэтому скобки стоят именно так. Данная конструкция таймера позволяет жёстко соблюдать период выполнения и не боится пропущенных вызовов, но требует нескольких дополнительных вычислений, в том числе “дорогое” деление, не забывайте об этом.

    Переполнение

    Напомню, что uint32_t это второе название типа данных unsigned long , просто оно короче в записи. Почему переменная должна быть именно такого типа? Потому что функция millis() возвращает именно этот тип данных, т.е. если мы сделаем нашу переменную например типа int , то она переполнится через 32.7 секунды. Но миллис тоже ограничен числом 4 294 967 295, и при переполнении тоже сбросится в 0. Сделает он это через 4 294 967 295 / 1000 / 60 / 60 / 24 = 49.7 суток. Значит ли это, что наш таймер “сломается” через 50 суток? Нет, рассмотренные выше конструкции таймеров спокойно переживают переход через 0 и работает дальше, не верьте диванным экспертам, проверьте =)

    Почему эта конструкция работает и не ломается? Потому что мы используем беззнаковый тип данных, который при переполнении начинает считать с нуля. Подробнее об этом читайте в уроке про вычисления. Таким образом когда миллис становится равен нулю и растёт, а мы вычитаем из него огромное число – получаем не отрицательное, а вполне корректное значение, которое является временем с предыдущего сброса таймера. Поэтому конструкция не то что продолжает работать через ~50 суток, но и проходит момент “переполнения” без потери периода!

    Вернёмся к вопросу многозадачности: хотим выполнять одно действие два раза в секунду, второе – три, и третье – 10. Нам понадобится 3 переменные таймера и 3 конструкции с условием:

    И вот так мы можем например 10 раз в секунду опросить датчик, фильтровать значения, и два раза в секунду выводить показания на дисплей. И три раза в секунду мигать лампочкой. Почему нет? Рассмотрим ещё несколько алгоритмов.

    Варианты использования millis()

    В классическом варианте таймера нам приходится создавать отдельную 32-х битную переменную под каждый таймер. Весьма расточительно! Давайте рассмотрим другие варианты организации периодических действий на базе счётчика аптайма millis() :

    В интернете часто можно встретить вот такую конструкцию: условие выполняется, когда остаток от деления millis() на период равен нулю.

    Казалось бы, очень крутой и простой алгоритм… но использовать его нельзя по целому ряду причин:

    • Операция “остаток от деления” довольно тяжёлая и медленная, размещение нескольких таких “таймеров” в основном цикле программы сильно увеличит время его выполнения и замедлит работу всей программы в целом!
    • В реальной программе может создаться задержка продолжительностью дольше 1 мс (например вывод на матрицу адресных светодиодов занимает ~30 мс) и существует довольно высокий риск пропуска такого “таймера”!
    • В то же время условие срабатывания таймера будет верно целую миллисекунду (что целая вечность для микроконтроллера) и действие по таймеру может выполниться несколько раз подряд, что недопустимо в большинстве случаев!

    Вывод: ни в коем случае не используйте данную конструкцию.

    Данный макрос заменяет “таймер на миллис” одной строчкой, без использования библиотек и создания классов!

    Либо вот такой вариант, он не уходит в отличие от предыдущего (разбирали разницу в главе “Таймер на millis()”). Разница напомню в способе сброса таймера.

    Пользоваться очень просто: добавьте указанный выше макрос в самое начало кода и вызывайте его как функцию

    Единственное ограничение: нельзя вызывать макрос больше одного раза в одном и том же блоке кода, это приведёт к ошибке =) То есть вот так нельзя:

    Если очень нужна такая конструкция – помещаем каждый вызов в свой блок кода:

    Либо используем блоки кода по условиям или как отдельную функцию, которая “оборачивает” макрос:

    Таймер, который после срабатывания переключает период на другой, например включаем реле на 10 секунд каждые 60 минут

    Таймер обратного отсчёта на чистом JavaScript

    В этой статье рассмотрим таймер обратного отсчета, построенный на чистом CSS и JavaScript. Он написан с использованием минимального количества кода без использования jQuery и каких-либо других сторонних библиотек.

    Таймеры обратного отсчёта могут использоваться на сайтах для различных целей. Но в большинстве случаев они применяются для отображения времени, которое осталось до наступления какого-то крупного события: запуска нового продукта, рекламной акции, начала распродажи и т.д.

    Демо таймера обратного отсчёта

    Простой таймер обратного отсчета с днями, часами, минутами и секундами. Очень легко настраивается. Создан на чистом CSS и Javascript (без зависимостей).

    Простой таймер обратного отсчета с днями, часами, минутами и секундами на чистом CSS и JavaScript

    Подключение и настройка таймера

    1. Вставить в нужное место страницы html-разметку таймера:

    Таймер обратного отсчета отображает четыре числа: дни, часы, минуты и секунды. Каждое число находится в элементе

    . Первый класс ( timer__item ) используется для стилизации элемента, а второй - для таргетинга в JavaScript.

    2. Добавить стили (базовое оформление):

    Стилизовать таймер обратного отсчета можно так как вы этого хотите.

    3. Добавить JavaScript:

    4. Установить дату окончания. Например, до 1 июля 2021:

    Структура кода JavaScript

    Основную часть кода занимает функция countdownTimer :

    Эта функция выполняет расчёт оставшегося времени и обновляет содержимое элементов .timer__item на странице.

    Расчёт оставшегося времени осуществляется посредством вычитания текущей даты из конечной:

    Вычисление оставшегося количества дней, часов, минут и секунд выполняется следующим образом:

    Встроенная функция Math.floor используется для округления числа до ближайшего целого (посредством отбрасывания дробной части).

    Вывод оставшегося времени на страницу:

    Переменные $days , $hours , $minutes , $seconds содержат элементы (таргеты), в которые выводятся компоненты времени.

    Получение элементов (выполняется с помощью querySelector ):

    Функция declensionNum используется для склонения числительных:

    Для постоянного вычисления оставшегося времени и вывода его на страницу используется setInterval .

    Хранение идентификатора таймера осуществляется в переменной timerId :

    Использование setInterval для запуска функции countdownTimer каждую секунду:

    Остановка таймера по истечении времени выполняется в функции countdownTimer :

    Скрипт для создания нескольких таймеров отчета на странице

    Скрипт, написанный с использованием классов, который можно использовать для создания нескольких таймеров отчета на странице:

    Пример использования класса CountdownTimer() для создания таймера на странице:

    В new CountdownTimer() необходимо передать следующие аргументы:

    • конечную дату в формате Date;
    • функцию, которую нужно выполнять каждую секунду (её, например, можно использовать для обновления содержимого элементов, которые используются для отображения оставшегося времени);
    • при необходимости функцию, которую нужно выполнить после завершения таймера.

    HTML код первого таймера:

    Инициализация остальных таймеров на странице с помощью new CountdownTimer() выполняется аналогично.

    Пример страницы, на которой имеется несколько таймеров обратного отсчёта:

    Читайте также: