воскресенье, 8 октября 2017 г.

Matrix has you... или малая офисная автоматизация

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



Arduino, Raspberry Pi, китайский брат ее Orange и другие прикольные штуковины зачастую используются энтузиастами в оторванных от жизни проектах. Однако иногда жизнь сама подкидывает интересные задачки, в которых их можно с успехом применить.

После переезда в новый офис на работе у руководителя команды "Карандаш и Самоделкин" встал вопрос об использовании старого олдскульного сканера, не имеющего LAN-порта. Никто не жаждал цеплять его по USB к своему компьютеру и день за днем развлекаться в стиле "Чувак, мне тут пару листочков надо отсканировать, поможешь? Кинь скан на почту?".


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

Дело за малым - нужна кнопка, лучше всего USB-шная. Arduino Micro, которая умеет притворяться USB-устройствами? Слишком жирно для такой задачи. Ее младший брат - Digispark - вот один из  самых бюджетных вариантов, которого достаточно для реализации задумки.

Плата имеет 6 портов ввода-вывода, стоит у китайцев всего 50 рублей. На борту 8 КБ памяти для программного кода, частота камня от 1 МГц до 20 МГц, питание от 1,8В до 35В (в зависимости от модификации).

Для проекта также пригодилась пара кнопок, светодиод, несколько сопротивлений, динамик от сломанных наушников и провода. В качестве корпуса - футляр от панельки еще более олдскульной кассетной автомагнитолы Nakamichi. Ребята из "Карандаша и Самоделкина" за выходные спаяли все это в кучу и вышло вот что:



Устройство подключается по USB к компьютеру со сканером. Алгоритм работы девайса следующий:
1. Человек, которому нужно отсканировать документы, нажимает красную кнопку "Начать сканирование/Следующий лист".
2. Устройство издает торжествующе-подтверждающий писк, включает светодиод и, притворившись USB-клавиатурой, посылает на компьютер комбинацию Ctrl-Shift-2. Включенный светодиод означает что сканирование не завершено.
3. На компьютере по данной комбинации запускается в фоне программа на Python (код ниже), которая, используя вызов NAPS2, сканирует лист и сохраняет во временную папку.
4. Человек может повторить п. 1-3 если хочет добавить листы в тот же PDF-документ, иначе нажимает синюю кнопку "Завершить сканирование".
5. Устройство снова пищит, выключает светодиод и посылает на компьютер комбинацию Ctrl-Shift-3.
6. На компьютере по данной комбинации запускается в фоне вторая программа на Python (код также ниже), которая объединяет все листы из временной папки в единый PDF-документ на сетевом диске, добавив в имя файла дату и время.
7. Человек идет на свое рабочее место и забирает файл с сетевого диска. Радуется, что ему не пришлось "просить сканировать".

Экономический эффект потрясающий. Если посчитать грубо, то на ручное сканирование 1 листа человеку. "хозяину-сканера", раньше требовалось затратить около 2-3 минут с учетом предварительного просмотра документа, ручного сохранения на сетевой диск или отправку по почте. В неудачный день он мог бы сканировать для приходящих полчаса, отвлекаясь от своей работы. Даже самая неточная прикидка дает срок окупаемости всего "железа" в несколько часов.

Код для Digispark у нас получился вот такой:

#include "DigiKeyboard.h"

#define MY_OUT 2 
#define MY_KEY1 0
#define MY_KEY2 1

bool trigger = false;

void setup() { 
  pinMode(MY_OUT, OUTPUT); 
  pinMode(MY_KEY1, INPUT);
  pinMode(MY_KEY2, INPUT);

  tone(MY_OUT,659,500);
}

void loop() {
  DigiKeyboard.update();

  if (digitalRead(MY_KEY1) == true  && digitalRead(MY_KEY2) == false){
    DigiKeyboard.sendKeyStroke(KEY_2, MOD_SHIFT_LEFT | MOD_CONTROL_LEFT);
    tone(MY_OUT,440);         
    DigiKeyboard.delay(500);
    noTone();
    digitalWrite(MY_OUT,true);    
    DigiKeyboard.delay(5000);
    trigger = true;
  }

  if (digitalRead(MY_KEY2) == true && digitalRead(MY_KEY1) == false && trigger){        
    DigiKeyboard.sendKeyStroke(KEY_3, MOD_SHIFT_LEFT | MOD_CONTROL_LEFT);
    tone(MY_OUT,523);
    DigiKeyboard.delay(500);
    noTone();
    digitalWrite(MY_OUT,false);    
    DigiKeyboard.delay(5000);
    trigger = false;
  }
  
  DigiKeyboard.delay(100);
}

Программа на Python, которая запускается по красной кнопке на ПК выглядит так:

# сканирование одного изображения во временную сетевую папку

import os, time
import datetime

# каталог, куда будут сохраняться отсканированные изображения
dir = r'O:\scan\tmp'
# путь к NAPS2
NAPSexe = r'C:\"Program Files (x86)"\NAPS2\NAPS2.Console.exe'
# имя временного файла
tmpPdf = "scan" # .pdf

try:
    files = os.listdir(dir)
except OSError:
    print("Сетевой путь не найден! Скорректируйте переменную dir")    
    time.sleep(60)

now_time = datetime.datetime.now()

print(now_time.strftime("%d.%m.%Y %I:%M:%S")," Идет сканирование... ")

n = 1

# смотрим сколько файлов уже отсканировано
files = os.listdir(dir)
for i in files:
    n += 1

# Сканируем одно изображение в pdf
fullNamePdf = dir + "\\"+tmpPdf+str(n)+".pdf"
os.system(NAPSexe + r' --force -o '+fullNamePdf)

print(now_time.strftime("%d.%m.%Y %I:%M:%S")," Сканирование завершено... ")

"Синяя" кнопка запускает программу на Python следующего содержания:

# сборка отсканированных страниц в многостраничный документ

import os, time
import datetime

# каталог, откуда будут забираться постранично отсканированные изображения
dirIn = r'O:\scan\tmp'
# каталог, куда будет собираться многостраничный документ
dirOut = r'O:\scan\docs'
# путь к NAPS2
NAPSexe = r'C:\"Program Files (x86)"\NAPS2\NAPS2.Console.exe'
# имя временного файла
tmpPdf = "scan" # .pdf

try:
    files = os.listdir(dirIn)
except OSError:
    print("Сетевой путь не найден! Скорректируйте переменную dirIn")    
    time.sleep(60)

try:
    files = os.listdir(dirOut)
except OSError:
    print("Сетевой путь не найден! Скорректируйте переменную dirOut")    
    time.sleep(60)

now_time = datetime.datetime.now()

print(now_time.strftime("%d.%m.%Y %I:%M:%S")," Идет сборка... ")

# Смотрим сколько страниц во временной папке
files = os.listdir(dirIn)
i = 0
cmd = ""
for scan in files:
    i += 1
    cmd += dirIn+"\\"+scan
    if i < len(files):
        cmd += ";"

fullNamePdf = dirOut + "\\scan-"+ now_time.strftime("%Y-%m-%d-%I-%M-%S") + ".pdf"
os.system(NAPSexe + r' -i ' + cmd + r' --force -n 0 -o '+fullNamePdf)

print(now_time.strftime("%d.%m.%Y %I:%M:%S")," Сборка завершена... ")
print(now_time.strftime("%d.%m.%Y %I:%M:%S")," Удяляем временные файлы... ")

for scan in files:
    os.remove(dirIn+"\\"+scan)

 Вот такая вышла малая офисная автоматизация, а цвета кнопок, напоминающий красную и синюю таблетки в всем известном фильме, дали название нашему проекту.

Комментариев нет:

Отправить комментарий

Самое популярное