永栄コードのマージ開始
This commit is contained in:
20
rogaining_autoprint/Dockerfile
Normal file
20
rogaining_autoprint/Dockerfile
Normal file
@ -0,0 +1,20 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
# CUPSとその他必要なパッケージのインストール
|
||||
RUN apt-get update && apt-get install -y \
|
||||
cups \
|
||||
cups-client \
|
||||
gcc \
|
||||
libcups2-dev \
|
||||
python3-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY ./app .
|
||||
|
||||
CMD ["python", "main.py"]
|
||||
|
||||
144
rogaining_autoprint/README
Normal file
144
rogaining_autoprint/README
Normal file
@ -0,0 +1,144 @@
|
||||
システム管理
|
||||
|
||||
1. 環境変数の設定
|
||||
|
||||
必要な環境変数:
|
||||
envCopyAWS_ACCESS_KEY_ID=your_access_key
|
||||
AWS_SECRET_ACCESS_KEY=your_secret_key
|
||||
AWS_REGION=us-west-2
|
||||
S3_BUCKET_NAME=sumasenrogaining
|
||||
LOCATION=美濃加茂
|
||||
PRINTER_NAME=Brother_HL_L3240CDW_series
|
||||
|
||||
|
||||
2.プリンター設定
|
||||
|
||||
3.1 CUPSの設定
|
||||
|
||||
# CUPSの状態確認
|
||||
systemctl status cups
|
||||
|
||||
# CUPSが動いていない場合は起動
|
||||
sudo systemctl start cups
|
||||
sudo systemctl enable cups
|
||||
|
||||
# プリンター一覧の確認
|
||||
lpstat -p -d
|
||||
|
||||
3.2 プリンターの権限設定
|
||||
|
||||
# プリンターデバイスの確認
|
||||
ls -l /dev/usb/lp*
|
||||
|
||||
# プリンターデバイスの権限設定
|
||||
sudo chmod 666 /dev/usb/lp0
|
||||
|
||||
3.3 ネットワークプリンターの場合
|
||||
|
||||
config.yamlのprinterセクションを以下のように設定:
|
||||
yamlCopyprinter:
|
||||
name: ipp://192.168.1.100:631/ipp/port1
|
||||
|
||||
4. Dockerイメージのビルドと起動
|
||||
4.1 イメージのビルド
|
||||
bashCopy# イメージのビルド
|
||||
docker-compose build
|
||||
4.2 コンテナの起動
|
||||
bashCopy# コンテナの起動(バックグラウンド)
|
||||
docker-compose up -d
|
||||
|
||||
# ログの確認
|
||||
docker-compose logs -f
|
||||
5. 動作確認
|
||||
5.1 ログの確認
|
||||
bashCopy# アプリケーションログの確認
|
||||
tail -f logs/app.log
|
||||
|
||||
# エラーログの確認
|
||||
tail -f logs/error.log
|
||||
5.2 テスト印刷
|
||||
bashCopy# テスト用PDFファイルをS3にアップロード
|
||||
aws s3 cp test.pdf s3://sumasenrogaining/美濃加茂/scoreboard/test.pdf
|
||||
5.3 プロセスの確認
|
||||
bashCopy# コンテナの状態確認
|
||||
docker-compose ps
|
||||
|
||||
# コンテナ内のプロセス確認
|
||||
docker-compose exec printer ps aux
|
||||
6. トラブルシューティング
|
||||
6.1 印刷できない場合
|
||||
|
||||
CUPSの状態確認
|
||||
|
||||
bashCopydocker-compose exec printer lpstat -t
|
||||
|
||||
プリンターの権限確認
|
||||
|
||||
bashCopydocker-compose exec printer ls -l /dev/usb/lp0
|
||||
|
||||
プリンター接続の確認
|
||||
|
||||
bashCopydocker-compose exec printer lpinfo -v
|
||||
6.2 S3接続エラーの場合
|
||||
|
||||
認証情報の確認
|
||||
|
||||
bashCopydocker-compose exec printer env | grep AWS
|
||||
|
||||
S3バケットへのアクセス確認
|
||||
|
||||
bashCopydocker-compose exec printer python3 -c "
|
||||
import boto3
|
||||
s3 = boto3.client('s3')
|
||||
response = s3.list_objects_v2(Bucket='sumasenrogaining')
|
||||
print(response)
|
||||
"
|
||||
6.3 ログの確認方法
|
||||
bashCopy# 直近のエラーログ
|
||||
docker-compose exec printer tail -f /logs/error.log
|
||||
|
||||
# アプリケーションログ
|
||||
docker-compose exec printer tail -f /logs/app.log
|
||||
7. 運用とメンテナンス
|
||||
7.1 定期的なメンテナンス
|
||||
bashCopy# ログローテーション確認
|
||||
ls -l logs/
|
||||
|
||||
# ディスク使用量確認
|
||||
du -sh data/ logs/
|
||||
|
||||
# 古いPDFファイルの削除
|
||||
find data/files -name "*.pdf" -mtime +30 -delete
|
||||
7.2 バックアップ
|
||||
bashCopy# 設定ファイルのバックアップ
|
||||
tar czf config-backup-$(date +%Y%m%d).tar.gz .env config.yaml
|
||||
|
||||
# 処理済みファイルログのバックアップ
|
||||
cp data/${LOCATION}.filelog data/${LOCATION}.filelog.bak
|
||||
7.3 アップデート手順
|
||||
bashCopy# コンテナの停止
|
||||
docker-compose down
|
||||
|
||||
# 新しいイメージのビルド
|
||||
docker-compose build --no-cache
|
||||
|
||||
# コンテナの再起動
|
||||
docker-compose up -d
|
||||
8. セキュリティ考慮事項
|
||||
8.1 認証情報の管理
|
||||
|
||||
.envファイルのパーミッションを600に設定
|
||||
AWSアクセスキーは定期的にローテーション
|
||||
本番環境では.envファイルをgitにコミットしない
|
||||
|
||||
8.2 ネットワークセキュリティ
|
||||
|
||||
コンテナネットワークは必要最小限の公開
|
||||
プリンターアクセスは内部ネットワークに制限
|
||||
AWS S3へのアクセスは特定のIPに制限
|
||||
|
||||
8.3 モニタリング
|
||||
|
||||
CloudWatchなどでS3アクセスログを監視
|
||||
印刷ジョブの異常を検知して通知
|
||||
エラーログの定期チェック
|
||||
174
rogaining_autoprint/app/main.py
Normal file
174
rogaining_autoprint/app/main.py
Normal file
@ -0,0 +1,174 @@
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
import boto3
|
||||
import cups
|
||||
import yaml
|
||||
from dotenv import load_dotenv
|
||||
from loguru import logger
|
||||
|
||||
class Config:
|
||||
def __init__(self):
|
||||
load_dotenv()
|
||||
with open('config.yaml', 'r') as f:
|
||||
self.config = yaml.safe_load(f)
|
||||
|
||||
# 環境変数で設定値を上書き
|
||||
self.config['s3']['bucket'] = os.getenv('S3_BUCKET_NAME', self.config['s3']['bucket'])
|
||||
self.config['s3']['prefix'] = self.config['s3']['prefix'].replace('${LOCATION}', os.getenv('LOCATION', ''))
|
||||
self.config['printer']['name'] = os.getenv('PRINTER_NAME', self.config['printer']['name'])
|
||||
|
||||
class S3Manager:
|
||||
def __init__(self, config: Config):
|
||||
self.config = config
|
||||
self.s3_client = boto3.client('s3')
|
||||
|
||||
def list_files(self) -> List[str]:
|
||||
"""S3バケットのファイル一覧を取得"""
|
||||
try:
|
||||
files = []
|
||||
paginator = self.s3_client.get_paginator('list_objects_v2')
|
||||
for page in paginator.paginate(
|
||||
Bucket=self.config.config['s3']['bucket'],
|
||||
Prefix=self.config.config['s3']['prefix']
|
||||
):
|
||||
if 'Contents' in page:
|
||||
files.extend([obj['Key'] for obj in page['Contents']])
|
||||
return files
|
||||
except Exception as e:
|
||||
logger.error(f"S3ファイル一覧の取得に失敗: {e}")
|
||||
return []
|
||||
|
||||
def download_file(self, key: str, local_path: str) -> bool:
|
||||
"""S3からファイルをダウンロード"""
|
||||
try:
|
||||
self.s3_client.download_file(
|
||||
self.config.config['s3']['bucket'],
|
||||
key,
|
||||
local_path
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"ファイルのダウンロードに失敗 {key}: {e}")
|
||||
return False
|
||||
|
||||
class PrinterManager:
|
||||
def __init__(self, config: Config):
|
||||
self.config = config
|
||||
self.conn = cups.Connection()
|
||||
|
||||
def print_file(self, filepath: str) -> bool:
|
||||
"""ファイルを印刷"""
|
||||
printer_config = self.config.config['printer']
|
||||
max_attempts = printer_config['retry']['max_attempts']
|
||||
delay = printer_config['retry']['delay_seconds']
|
||||
|
||||
for attempt in range(max_attempts):
|
||||
try:
|
||||
job_id = self.conn.printFile(
|
||||
printer_config['name'],
|
||||
filepath,
|
||||
"Rogaining Score",
|
||||
printer_config['options']
|
||||
)
|
||||
logger.info(f"印刷ジョブを送信: {filepath} (Job ID: {job_id})")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"印刷に失敗 (試行 {attempt + 1}/{max_attempts}): {e}")
|
||||
if attempt < max_attempts - 1:
|
||||
time.sleep(delay)
|
||||
else:
|
||||
return False
|
||||
|
||||
class FileManager:
|
||||
def __init__(self, config: Config):
|
||||
self.config = config
|
||||
self.file_log_path = Path(self.config.config['app']['save_path']) / self.config.config['app']['file_log']
|
||||
self.processed_files = self._load_processed_files()
|
||||
|
||||
def _load_processed_files(self) -> List[str]:
|
||||
"""処理済みファイルの一覧を読み込み"""
|
||||
try:
|
||||
if self.file_log_path.exists():
|
||||
with open(self.file_log_path, 'r') as f:
|
||||
return json.load(f)
|
||||
return []
|
||||
except Exception as e:
|
||||
logger.error(f"処理済みファイル一覧の読み込みに失敗: {e}")
|
||||
return []
|
||||
|
||||
def save_processed_files(self):
|
||||
"""処理済みファイルの一覧を保存"""
|
||||
try:
|
||||
self.file_log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(self.file_log_path, 'w') as f:
|
||||
json.dump(self.processed_files, f)
|
||||
except Exception as e:
|
||||
logger.error(f"処理済みファイル一覧の保存に失敗: {e}")
|
||||
|
||||
def get_new_files(self, current_files: List[str]) -> List[str]:
|
||||
"""新規ファイルを特定"""
|
||||
return list(set(current_files) - set(self.processed_files))
|
||||
|
||||
def setup_logging(config: Config):
|
||||
"""ロギングの設定"""
|
||||
log_path = Path(config.config['app']['log_path'])
|
||||
log_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
logger.add(
|
||||
log_path / "app.log",
|
||||
rotation="1 day",
|
||||
retention="30 days",
|
||||
level="INFO"
|
||||
)
|
||||
logger.add(
|
||||
log_path / config.config['app']['error_log'],
|
||||
level="ERROR"
|
||||
)
|
||||
|
||||
def main():
|
||||
config = Config()
|
||||
setup_logging(config)
|
||||
|
||||
s3_manager = S3Manager(config)
|
||||
printer_manager = PrinterManager(config)
|
||||
file_manager = FileManager(config)
|
||||
|
||||
logger.info("スコアボード監視システムを開始")
|
||||
|
||||
while True:
|
||||
try:
|
||||
# S3のファイル一覧を取得
|
||||
current_files = s3_manager.list_files()
|
||||
|
||||
# 新規ファイルを特定
|
||||
new_files = file_manager.get_new_files(current_files)
|
||||
|
||||
for file_key in new_files:
|
||||
if not file_key.endswith('.pdf'):
|
||||
file_manager.processed_files.append(file_key)
|
||||
continue
|
||||
|
||||
# 保存先パスの設定
|
||||
local_path = Path(config.config['app']['save_path']) / Path(file_key).name
|
||||
local_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# ファイルのダウンロードと印刷
|
||||
if s3_manager.download_file(file_key, str(local_path)):
|
||||
if printer_manager.print_file(str(local_path)):
|
||||
file_manager.processed_files.append(file_key)
|
||||
file_manager.save_processed_files()
|
||||
|
||||
time.sleep(10) # ポーリング間隔
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"予期せぬエラーが発生: {e}")
|
||||
time.sleep(30) # エラー時は長めの待機
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
19
rogaining_autoprint/config.yaml
Normal file
19
rogaining_autoprint/config.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
app:
|
||||
save_path: /data/files
|
||||
log_path: /logs
|
||||
file_log: ${LOCATION}.filelog
|
||||
error_log: error.log
|
||||
|
||||
s3:
|
||||
bucket: ${S3_BUCKET_NAME}
|
||||
prefix: ${LOCATION}/scoreboard/
|
||||
|
||||
printer:
|
||||
name: ${PRINTER_NAME}
|
||||
options:
|
||||
PageSize: A4
|
||||
orientation: landscape
|
||||
sides: two-sided-long-edge
|
||||
retry:
|
||||
max_attempts: 3
|
||||
delay_seconds: 5
|
||||
20
rogaining_autoprint/docker-compose.yaml
Normal file
20
rogaining_autoprint/docker-compose.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
printer:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ./app:/app
|
||||
- ./data:/data
|
||||
- ./logs:/logs
|
||||
environment:
|
||||
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
|
||||
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
|
||||
- AWS_DEFAULT_REGION=${AWS_REGION}
|
||||
restart: always
|
||||
devices:
|
||||
- "/dev/usb/lp0:/dev/usb/lp0"
|
||||
privileged: true # プリンターアクセスに必要
|
||||
|
||||
5
rogaining_autoprint/requirements.txt
Normal file
5
rogaining_autoprint/requirements.txt
Normal file
@ -0,0 +1,5 @@
|
||||
boto3==1.34.11
|
||||
python-dotenv==1.0.0
|
||||
pycups==2.0.1
|
||||
PyYAML==6.0.1
|
||||
loguru==0.7.2
|
||||
Reference in New Issue
Block a user