Skip to main content

scanservjs (Scanner Web-UI)

version: "3.8"

services:
  scanservjs:
    image: sbs20/scanservjs:v3.0.4
    container_name: scanservjs
    privileged: true
    #network_mode: host #BENOETIGT BEIM SUCHEN MIT 'airscan-discover fuer eSCL und WSD Scanner'
    ports:
      - "8098:8080"
    environment:
      #DELIMITER: '|'
      #SANED_NET_HOSTS: "10.0.100.30;10.0.100.31"
      #AIRSCAN_DEVICES: '"HWS PM1 ✳️⚫" = "http://192.168.200.18/eSCL"|"HWS PM2 ✳️⚫" = "http://192.168.200.15/eSCL"|"HWS 1.OG ✳️🎨" = "http://192.168.200.119/eSCL"'
      #AIRSCAN_DEVICES='"Canon MFD" = "http://192.168.0.10/eSCL";"EPSON MFD" = "http://192.168.0.11/eSCL"'
      #AIRSCAN_DEVICES: |
      #  "Canon MFD" = "http://192.168.0.10/eSCL";
      #  "EPSON MFD" = "http://192.168.0.11/eSCL"
      #PIXMA_HOSTS: "192.168.200.33"
      #SCANIMAGE_LIST_IGNORE: "true"
      #DEVICES: "net:10.0.100.30:plustek:libusb:001:003;net:10.0.100.31:plustek:libusb:001:003;airscan:e0:Canon TR8500 series;airscan:e1:EPSON Cool Series"
      OCR_LANG: "deu+eng"
    volumes:
      - /var/run/dbus:/var/run/dbus
      - scans:/var/lib/scanservjs/output
      - scans-backup:/var/lib/scanservjs/output-backup
      - cfg:/etc/scanservjs
      - saned:/etc/sane.d
    restart: unless-stopped

volumes:
  scans:
  scans-backup:
  cfg:
  saned:

Problem: Es werden immer nur die ersten Trennzeichen erkannt, das heißt Scanner PM2 und  1.OG fallen unter ein Device, siehe Log:

# Insert airscan devices
if [ ! -z "$AIRSCAN_DEVICES" ]; then
  devices=$(echo $AIRSCAN_DEVICES | sed "s/$DELIMITER/\n/")
  for device in $devices; do
    sed -i "/^\[devices\]/a $device" /etc/sane.d/airscan.conf
  done
fi
+ [ ! -z "HWS PM1 ✳️⚫" = "http://192.168.200.18/eSCL"|"HWS PM2 ✳️⚫" = "http://192.168.200.15/eSCL"|"HWS 1.OG ✳️🎨" = "http://192.168.200.119/eSCL" ]
+ echo "HWS PM1 ✳️⚫" = "http://192.168.200.18/eSCL"|"HWS PM2 ✳️⚫" = "http://192.168.200.15/eSCL"|"HWS 1.OG ✳️🎨" = "http://192.168.200.119/eSCL"
+ sed s/|/\n/
+ devices="HWS PM1 ✳️⚫" = "http://192.168.200.18/eSCL"
"HWS PM2 ✳️⚫" = "http://192.168.200.15/eSCL"|"HWS 1.OG ✳️🎨" = "http://192.168.200.119/eSCL"
+ sed -i /^\[devices\]/a "HWS PM1 ✳️⚫" = "http://192.168.200.18/eSCL" /etc/sane.d/airscan.conf
+ sed -i /^\[devices\]/a "HWS PM2 ✳️⚫" = "http://192.168.200.15/eSCL"|"HWS 1.OG ✳️🎨" = "http://192.168.200.119/eSCL" /etc/sane.d/airscan.conf
# Insert pixma hosts
if [ ! -z "$PIXMA_HOSTS" ]; then
  hosts=$(echo $PIXMA_HOSTS | sed "s/$DELIMITER/\n/")
  for host in $hosts; do
    echo "bjnp://$host" >> /etc/sane.d/pixma.conf

Lösung: wie oben im docker-compose, den Ordner /etc/sane.d als Volume mounten und die airscan.conf darin per Hand bearbeiten:

[devices]
"HWS PM1 ✳️⚫" = "http://192.168.200.30/eSCL"
"HWS PM1 🦑⚫" = "http://192.168.200.31:80/wsd/scanservice.cgi", wsd
"HWS PM2 ✳️⚫" = "http://192.168.200.32/eSCL"
"HWS PM3 🦑⚫" = "http://192.168.200.33:80/wsd/scanservice.cgi", wsd
"HWS 1.OG ✳️⚫🔵🔴🟡" = "http://192.168.200.34/eSCL"

image.png

image.png

Testen, ob eSCL funktioniert

URL des Druckers mit Anhang aufrufen:

http://<DRUCKER-IP>/eSCL/ScannerCapabilities

http://<DRUCKER-IP>/eSCL/ScannerStatus

zb http://10.53.1.20/eSCL/ScannerCapabilities  

WSD-Scanner suchen

In Docker Container execen und 

airscan-discover

ausfuehren.

ACHTUNG! Zum discovern eines zb Canon Pixma GM4050 bzw GM4000 series muss network_mode: host im docker-compose.yml aktiviert sein. Danach funktioniert das scannen aber auch ohne network_mode: host

[...]
    container_name: scanservjs
    privileged: true
    network_mode: host
    ports:
[...]
> airscan-discover
[devices]
  Brother DCP-L3560CDW series [b42200db2103] = http://192.168.200.34:80/eSCL/, eSCL
  Brother DCP-L3560CDW series [b42200db2103] = https://192.168.200.34:443/eSCL/, eSCL
  Brother DCP-L3560CDW series [b42200db2103] = http://192.168.200.34:80/WebServices/ScannerService, WSD
  Brother DCP-L3560CDW series [b42200db2103] = http://[FE80::7697:79FF:FEEA:4635%252]:80/WebServices/ScannerService, WSD
  Brother MFC-L2710DW series = http://192.168.200.32:80/eSCL/, eSCL
  Brother MFC-L2710DW series = http://192.168.200.32:80/WebServices/ScannerService, WSD
  Brother MFC-L2710DW series = http://[FE80::4ED5:77FF:FE6D:67EF%252]:80/WebServices/ScannerService, WSD
  Brother MFC-L2750DW series = http://192.168.200.30:80/eSCL/, eSCL
  Brother MFC-L2750DW series = http://192.168.200.30:80/WebServices/ScannerService, WSD
  Brother MFC-L2750DW series = http://[FE80::BEF4:D4FF:FE44:75D%252]:80/WebServices/ScannerService, WSD
  CANON INC. GM4000 series = http://192.168.200.33:80/wsd/scanservice.cgi, WSD
  CANON INC. GM4000 series = http://[fe80::6e3c:7cff:fe0e:c3da%252]:80/wsd/scanservice.cgi, WSD
  CANON INC. GM4000 series = http://192.168.200.31:80/wsd/scanservice.cgi, WSD
  CANON INC. GM4000 series = http://[fe80::6e3c:7cff:fe0f:db71%252]:80/wsd/scanservice.cgi, WSD

image.png

danach die sane.d/airscan.conf anpassen: 

image.png

und

scanimage -L

 eingeben:

image.png

config anpassen und in config.local.js umbenennen:

Eikes Beispiel:

[...]
  afterDevices(devices) {
    const deviceNames = {
      'airscan:e0:FBS Friedrich UG ✳️|⚫🔵🔴🟡': 'FBS Friedrich UG ✳️|⚫🔵🔴🟡',
      'airscan:e1:FBS EG-PM ✳️|⚫': 'FBS EG-PM ✳️|⚫',
      'airscan:e2:FBS Friedrich I. ✳️|⚫🔵🔴🟡': 'FBS Friedrich I. ✳️|⚫🔵🔴🟡',
      'airscan:e3:FBS Friedrich II. ✳️|⚫🔵🔴🟡': 'FBS Friedrich II. ✳️|⚫🔵🔴🟡',
      'airscan:e4:FBS Friedrich III. ✳️|⚫🔵🔴🟡': 'FBS Friedrich III. ✳️|⚫🔵🔴🟡'
    };

    devices
      .filter(d => d.id in deviceNames)
      .forEach(d => d.name = deviceNames[d.id]);

    devices
      .filter(d => d.id.includes('FBS'))
      .forEach(device => {
        device.features['--mode'].default = 'Color';
        device.features['--resolution'].default = 150;
        device.features['--resolution'].options = [75, 150, 300, 600];
        device.features['--brightness'].default = 0;
        device.features['--contrast'].default = 5;
        device.features['-x'].default = 192;
        device.features['-y'].default = 272;
        /* device.settings.pipeline.default = 'PNG'; */
        device.settings.pipeline.default = '@:pipeline.ocr | PDF (JPG | @:pipeline.high-quality)';
        /* Disable batch modes if they are not available on your printer: */
        /*device.settings.batchMode.options = ['none', 'manual']; */
    });
  },

  async afterScan(fileInfo) {
[...]

https://medium.com/@davidclaeys/scanservjs-make-your-own-scan-server-21539f64265c 

module.exports = {
  afterDevices(devices) {
 const deviceNames = {
      /*
        'device id':'device name'
      */
      'airscan:e0:Hp Envy Pro 6442': 'Hp Envy Pro 6442'
    };
 
/*
  replace the id in the filter
*/
 devices
      .filter(d => d.id == 'airscan:e0:Hp Envy Pro 6442')
      .forEach(device => {
        device.features['--resolution'].default = 400;
        device.features['--resolution'].options = [100, 150, 200, 300, 400, 600];
        /*
          Disable batch modes if they are not available on your printer
        */
         device.settings.batchMode.options = ['none', 'manual'];
         /*
         Specify the default pipeline
         */
         device.settings.pipeline.default = ['PNG'];
      });
 
  devices
      .filter(d => d.id in deviceNames)
      .forEach(d => d.name = deviceNames[d.id]);
  }
};

escl:// automatische Suche deaktivieren

escl.conf umbenennen:

image.png

Scans autom. backupen und löschen

wieWeil die Scans von jedem zugänglich sind, der die Seite aufrufen kann, sollten die Scans gelöscht und zusätzlich gebackupt werden.
Wie oben in der docker-compose.yml beschrieben, ein Volume scans-backup anlegen. Dazu dieses Skript zb unter 

/home/user/scanservjs-backup.sh

ablegenanlegen und mit chmod +x /home/user/scanservjs-backup.sh ausführbar machen:

#!/bin/bash

# Scanservjs Backup und Bereinigungsskript
# Erstellt Backups und löscht alte Dateien (älter als 60 Minuten)

# Verzeichnisse definieren
SOURCE_DIR="/var/lib/docker/volumes/scanservjs_scans"
BACKUP_DIR="/var/lib/docker/volumes/scanservjs_scans-backup"
LOG_FILE="/var/log/scanservjs-backup.log"

# Zeitstempel für Logging
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Logging-Funktion
log_message() {
    echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
}

# Skript starten
log_message "=== Backup-Skript gestartet ==="

# Prüfen ob Quellverzeichnis existiert
if [ ! -d "$SOURCE_DIR" ]; then
    log_message "FEHLER: Quellverzeichnis $SOURCE_DIR existiert nicht!"
    exit 1
fi

# Backup-Verzeichnis erstellen falls nicht vorhanden
if [ ! -d "$BACKUP_DIR" ]; then
    mkdir -p "$BACKUP_DIR"
    log_message "Backup-Verzeichnis $BACKUP_DIR wurde erstellt"
fi

# Dateien kopieren (mit rsync für effizientes Backup)
log_message "Starte Backup von $SOURCE_DIR nach $BACKUP_DIR"
rsync -av --progress "$SOURCE_DIR/" "$BACKUP_DIR/" >> "$LOG_FILE" 2>&1

if [ $? -eq 0 ]; then
    log_message "Backup erfolgreich abgeschlossen"
else
    log_message "FEHLER beim Backup!"
    exit 1
fi

# Alte Dateien löschen (älter als 60 Minuten)
log_message "Suche nach Dateien älter als 60 Minuten in $SOURCE_DIR"

# Zähler für gelöschte Dateien
DELETED_COUNT=0

# Dateien finden und löschen
while IFS= read -r -d '' file; do
    log_message "Lösche: $file"
    rm -f "$file"
    if [ $? -eq 0 ]; then
        ((DELETED_COUNT++))
    else
        log_message "FEHLER beim Löschen von: $file"
    fi
done < <(find "$SOURCE_DIR" -type f -mmin +60 -print0)

log_message "Anzahl gelöschter Dateien: $DELETED_COUNT"
log_message "=== Backup-Skript beendet ==="
echo "" >> "$LOG_FILE"

exit 0

dann mit crontab -e minütlich laufen lassen:

* * * * * /home/user/scanservjs-backup.sh