백업 디렉토리에 /카메라기종/YYYY/YYYY-MM-DD 로 파일이 복사됨.

카메라기종을 Metadata에서 추출 못 하면 /YYYY/YYYY-MM-DD 로 파일이 복사됨.

시놀로지에서 장시간 작업이라 /제어판/작업 스케쥴러 에 등록해서 사용

 

common_utils.py

import os, datetime, sys
import exifread
import exiftool
import hashlib
import json

def json_default(value):
    if isinstance(value, datetime.date):
        return value.strftime('%Y:%m:%d')

    raise TypeError('not JSON serializable')


# exiftool 사용 함수
def get_exif_info(file_path):

    #print("FILE LOCATION : " + file_path)

    create_date    = ""
    metadata       = ""
    format_str1    = '%Y:%m:%d %H:%M:%S'
    format_str2    = '%d/%m/%Y %H:%M'
    exif_date_str = ""
    file_date_str = ""
    hash_str      = ""
    file_size     = 0
    exif_model    = ""

    #with open(file_path, 'rb') as f:
    with exiftool.ExifToolHelper() as et:
        #metadata = exifread.process_file(f)
        array = et.get_metadata(file_path)

        metadata = json.dumps(array[0])
        exif_str = json.loads(metadata)
        if len(metadata) > 0: 

            #print(metadata)

            # DB등록시 오류나는 항목 삭제
            # if 'EXIF:UserComment' in metadata:
            #     del metadata['EXIF:UserComment']
            # if 'QuickTime:CompressorName' in metadata:
            #     del metadata['QuickTime:CompressorName']
            # if 'ExifTool:Warning' in metadata:
            #     del metadata['ExifTool:Warning']
            # if 'MakerNotes:AFPointsInFocus1D'  in metadata:
            #     del metadata['MakerNotes:AFPointsInFocus1D']
            # if 'JPEGThumbnail'  in metadata:
            #     del metadata['JPEGThumbnail']

            # for tag in metadata:
            #     #print("Key: %s, value %s" % (tag, metadata[tag]))
            #     if tag['EXIF:DateTimeOriginal']: # 사진 촬영할 일자
            #         print("Key: %s, value %s" % (tag, metadata[0]))
            #         exif_date_str = str(metadata[tag])
            #     if tag['QuickTime:CreateDate']:  # 동영상 촬영 일자
            #         #print("Key: %s, value %s" % (tag, metadata[tag]))
            #         exif_date_str = str(metadata[tag])
            #     if tag['File:FileModifyDate']: # 카톡 등으로 받은 사진들
            #         #print("Key: %s, value %s" % (tag, metadata[tag]))
            #         file_date_str = str(metadata[tag])
            #     if tag['File:FileSize']:
            #         file_size = metadata[tag]
            #     if tag['EXIF:Model']:
            #         exif_model = str(metadata[tag])

            if "EXIF:DateTimeOriginal" in exif_str:                     # 사진 촬영할 일자
                #print(exif_str["EXIF:DateTimeOriginal"])
                exif_date_str = exif_str["EXIF:DateTimeOriginal"]
            if "QuickTime:CreateDate" in exif_str:                      # 동영상 촬영할 일자
                #print(exif_str["QuickTime:CreateDate"])
                exif_date_str = exif_str["QuickTime:CreateDate"]
            if "File:FileModifyDate" in exif_str:                       # 파일 수정 일자
                #print(exif_str["File:FileModifyDate"])
                file_date_str = exif_str["File:FileModifyDate"]
            if "File:FileSize" in exif_str:                             # 파일 사이즈
                #print(exif_str["File:FileSize"])
                file_size = exif_str["File:FileSize"]
            if "EXIF:Model" in exif_str:                                # 사진 촬영 기종
                #print(exif_str["EXIF:Model"])
                exif_model = exif_str["EXIF:Model"]
            if "QuickTime:Model" in exif_str:                           # 동영상 촬영할 일자
                #print(exif_str["QuickTime:Model"])
                exif_model = exif_str["QuickTime:Model"]

            if (exif_date_str == '') and (file_date_str == ''):
                print(exif_str)
            else:
                #print("exif_date_str" + exif_date_str)
                if ((exif_date_str == '') or (exif_date_str == '0000:00:00 00:00:00')) and (file_date_str != ''):
                    exif_date_str = file_date_str[0:19]

                try:
                    exif_date = datetime.datetime.strptime(exif_date_str, format_str1)
                    file_date = datetime.datetime.strptime(file_date_str[0:19], format_str1)

                    if (exif_date < file_date):
                        create_date = exif_date.strftime('%Y-%m-%d')
                    else :
                        create_date = file_date.strftime('%Y-%m-%d')
                    #print(create_date)
                except ValueError as ve:
                    exif_date = datetime.datetime.strptime(exif_date_str, format_str2)
                    file_date = datetime.datetime.strptime(file_date_str[0:19], format_str1)

                    if (exif_date < file_date):
                        create_date = exif_date.strftime('%Y-%m-%d')
                    else :
                        create_date = file_date.strftime('%Y-%m-%d')
            # Dictionary -> JSON

        # 중복제거용으로(사이즈 큰 파일을 읽으면 수행속도저하)
        if (file_size <= 1024000000):
            f = open(file_path, 'rb')
            data = f.read()
            f.close

            hash_str = hashlib.sha256(data).hexdigest()

        exif_str = json.dumps(metadata, indent="\t", default=json_default)

    return create_date, exif_str, hash_str, exif_model

 

photo_copy_by_camera_date.py

###############################################################################
## PHOTO COPY BY META DATA
## PARAM1 : SKIP COUNT (오류시 재작업할 경우 처리된 건수 제외용)
## PARAM2 : 사진을 정리할 디렉토리
## 
###############################################################################

import os, datetime, shutil, pymysql, sys
import exiftool
import common_utils as ut
from logging.config import dictConfig
import logging

## 정리할 사진, 동영상 디렉토리
dir_path = ''

# 정리된 파일을 모을 디렉토리
go_path          = "/volume2/backup_photo/" # 복사할 디렉토리
dest_path        = ''
target_date      = ''
target_file_name = ''
ext_list         = (".JPG", ".JPEG", ".PNG", ".NEF", ".HEIC", ".3GP", ".MOV", ".MP4", ".DNG", ".TIF", ".TIFF", ".CR2", ".CRW", ".RW2")
skip_count       = 0

conn = pymysql.connect(host='db호스트명', user='db유저명', password='db비밀번호', db='db명', charset='utf8', port=db포트)


c = conn.cursor()
iCnt = 0

## 제외처리할 카운드 (오류났을때 건너띄기용)
if (sys.argv[1] != ''):
    skip_count = int(sys.argv[1])

## 정리할 사진, 동영상 디렉토리 없을 경우 파라미터로 지정
if (dir_path == ''):
    dir_path = sys.argv[2]

print("#######################################")
print(" Source Directory : " + dir_path        )
print(" Target Directory : " + go_path         )
print(" Skip Count       : %d" % skip_count    )
print("#######################################")

dictConfig({
    'version': 1,
    'formatters': {
        'default': {
            'format': '[%(asctime)s] %(message)s',
        }
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': 'debug.log',
            'formatter': 'default',
        },
    },
    'root': {
        'level': 'DEBUG',
        'handlers': ['file']
    }
})


try:
    # 디렉토리 구조 돌면서 처리
    for (root, directories, files) in os.walk(dir_path) :
        for d in directories :
            d_path = os.path.join(root, d)
            #print(d_path)

        for file in files :
            file_path = os.path.join(root, file)
            #print(file_path)

            file_size = 0

            if "@eaDir" not in file_path:
                file_dir, file_name = os.path.split(file_path)
                file_dir, file_ext  = os.path.splitext(file_path)
                file_size           = os.path.getsize(file_path)
                target_file_name    = file_name.upper()

                #print("FILE LOCATION [ %d ]: %s"  % (iCnt, file_path))
                #print("FILE     SIZE [ %d ]: %d " % (iCnt, file_size))

                if (skip_count > iCnt):
                    skip_yn = 'Y'
                    iCnt = iCnt + 1
                else:
                    skip_yn = 'N'

                if (skip_yn == 'N'):
                    sql = "SELECT idx, file_loc, file_name, copy_yn, copy_loc, reg_date, mod_date FROM photo WHERE file_loc = '%s';" % (file_path)
                    #print(sql)
                    c.execute(sql)

                    data1 = c.fetchone()

                    copy_yn = 'N'
                    copy_str = 'N'

                    #print(data1)

                    if (data1 == None):
                        copy_yn = 'N'

                    elif (data1[3] == 'Y'):
                        update_sql = "UPDATE photo SET mod_date = NOW() WHERE idx = '%s';" % data1[0]
                        #print(update_sql)
                        c.execute(update_sql)
                        conn.commit

                        copy_yn = 'Y'
                        print(file_path + " Already Done!")
                    elif (data1[3] == 'N'):
                        copy_yn = 'U'

                    target_date = ''
                    exif_str    = ''
                    hash_str    = ''
                    dest_path   = ''
                    exif_model  = ''

                    # 파일 복사 대상이면 처리
                    if (copy_yn != 'Y'):
                        # 정리할 파일 확장자 정의
                        if (file_ext.upper() in ext_list):
                            #target_date = get_exif_info(file_path)
                            target_date, exif_str, hash_str, exif_model = ut.get_exif_info(file_path)

                            #print(exif_str)

                            if (len(target_date) == 10):
                                if (len(exif_model) > 0):
                                    dest_path = go_path + "/" + exif_model + "/" + target_date[0:4] + "/" + target_date+  "/"
                                else:
                                    dest_path = go_path + "/" + target_date[0:4] + "/" + target_date+  "/"
                                
                                #print(dest_path + " : " + str(len(target_date)))
                                if (os.path.isdir(dest_path) == False):
                                    os.makedirs(dest_path)

                                # 복사할 파일이 존재할 경우
                                if (os.path.exists(dest_path + target_file_name)):

                                    target_size = os.path.getsize(dest_path + target_file_name)

                                    if (target_size == file_size):
                                        #print("### 동일한 파일이 존재하므로 SKIP!! :" + file_path)
                                        copy_str = 'S'
                                    elif (target_size > file_size):
                                        #print("### 사이즈 큰 파일이 존재하므로 존재하므로 SKIP!! :" + file_path)
                                        copy_str = 'O'
                                    else:
                                        shutil.copy2(file_path, dest_path + target_file_name)
                                        copy_str = 'Y'
                                else:
                                    shutil.copy2(file_path, dest_path + target_file_name)
                                    copy_str = 'Y'
                            else:
                                dest_path = go_path + "/ERROR/"

                                if (os.path.isdir(dest_path) == False):
                                    os.makedirs(dest_path)

                                shutil.copy2(file_path, dest_path + target_file_name)
                                copy_str = ''
                        else:
                            dest_path = go_path + "/ERROR/"

                            if (os.path.isdir(dest_path) == False):
                                os.makedirs(dest_path)

                            shutil.copy2(file_path, dest_path + target_file_name)
                            copy_str = 'N'

                        now = datetime.datetime.now()
                        nowStr = now.strftime('%Y-%m-%d %H:%M:%S')

                        param2 = (file_path, target_file_name, copy_str, dest_path + target_file_name, file_size, hash_str, exif_str.replace("'", ""))
                        insert_sql = "INSERT INTO photo (file_loc, file_name, copy_yn, copy_loc, file_size, hash, exif) VALUES ('%s', '%s', '%s', '%s', %s, '%s', '%s');" % param2
                        #print(insert_sql)
                        c.execute(insert_sql)

                    #print("FILE LOCATION : " + file_path + " / " + dest_path + " / " + str(file_size))
                    logging.debug("FILE LOCATION : " + file_path + " / " + dest_path + " / " + str(file_size))

                    iCnt = iCnt + 1

                    if (iCnt % 10) == 0:
                        conn.commit()
                        print("#######################################")
                        print(" %d : Commit!!!" % iCnt)
                        print("#######################################")

    conn.commit()

    print("#######################################")
    print(" %d : Commit!!!" % iCnt)
    print("#######################################")

except Exception as inst:
    print(insert_sql)
    logging.debug(inst)
    logging.debug("exif_str : " + exif_str)
    logging.debug("insert_sql : " + insert_sql)
finally:

    conn.close()

 

테이블 생성 SQL

CREATE TABLE `photo` (
  `IDX` int(10) NOT NULL,
  `FILE_LOC` varchar(300) DEFAULT NULL,
  `FILE_NAME` varchar(100) DEFAULT NULL,
  `COPY_YN` varchar(1) DEFAULT NULL,
  `COPY_LOC` varchar(300) DEFAULT NULL,
  `FILE_SIZE` bigint(20) DEFAULT NULL,
  `hash` varchar(100) DEFAULT NULL,
  `exif` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
  `REG_DATE` datetime DEFAULT current_timestamp(),
  `MOD_DATE` datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Posted by 파파울프™
,

친구들이랑 발헤임을 하다가 데디케이트 서버가 있으면 편할꺼 같아 알아보기 시작

Docker 가 Container Manager로 바뀌어서 어색하지만

valheim으로 검색하면 가장 높은 별을 받은 이미지가 있습니다.

https://hub.docker.com/r/lloesche/valheim-server

 

Docker

 

hub.docker.com

도커 허브에서 해당 이미지 문서를 보면

링크가 깨져있는데

실제 해당 문서는 github에 올라와 있습니다.

https://github.com/lloesche/valheim-server-docker

 

GitHub - lloesche/valheim-server-docker: Valheim dedicated gameserver with automatic update, World backup, BepInEx and ValheimPl

Valheim dedicated gameserver with automatic update, World backup, BepInEx and ValheimPlus mod support - GitHub - lloesche/valheim-server-docker: Valheim dedicated gameserver with automatic update, ...

github.com

문서대로 다음 다음 하다가 서버변수 세팅에서

이거 세팅 안하면 XBOX와 Steam간의 접속이 안되더군요. 제일 중요...

저 변수만 추가하면 steamcmd로 valhei m dedicate server app을 받아서 세팅까지 해줍니다.

  서버 월드 세이브는 \docker\valheim\config\worlds_local 안에 있습니다.

공유기 포트포워딩은

만 열어주면 됩니다.

Posted by 파파울프™
,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'글타래 > 취미&일상다반사' 카테고리의 다른 글

HG 뉴건담 구매  (0) 2023.05.13
MG 제타 건담 Ver.Ka 구매  (0) 2023.05.13
아카데미 1/48 K1A1 유선 조종 전차  (0) 2016.08.20
Posted by 파파울프™
,

 

 

 

 

 

 

 

 

 

 

같이 줄 서서 고생한 둘째 조공용...

여름방학에 조립 예정(?)

'글타래 > 취미&일상다반사' 카테고리의 다른 글

MG 즈고크 설명서  (0) 2023.05.27
MG 제타 건담 Ver.Ka 구매  (0) 2023.05.13
아카데미 1/48 K1A1 유선 조종 전차  (0) 2016.08.20
Posted by 파파울프™
,

 

 

 

 

 

조립은 언젠가 시간 날때...

 

 

'글타래 > 취미&일상다반사' 카테고리의 다른 글

HG 뉴건담 구매  (0) 2023.05.13
아카데미 1/48 K1A1 유선 조종 전차  (0) 2016.08.20
오랫만에 조이스틱 수리  (0) 2012.08.26
Posted by 파파울프™
,

암복호화 개발을 하던 중 상대 기관에서 보내온 개인키 파일이 der...

ASN.1 파싱

DERSequence로 읽어서 [1] , [3] 를 DERInteger로 개인키를 생성해도 됨.
PEM 파일로 변환

끗...

der 개인키 구조체 pkcs#1

RSAPrivateKey ::= SEQUENCE {
      version   Version,
      modulus   INTEGER,  -- n
      publicExponentINTEGER,  -- e
      privateExponent   INTEGER,  -- d
      prime1INTEGER,  -- p
      prime2INTEGER,  -- q
      exponent1 INTEGER,  -- d mod (p-1)
      exponent2 INTEGER,  -- d mod (q-1)
      coefficient   INTEGER,  -- (inverse of q) mod p
      otherPrimeInfos   OtherPrimeInfos OPTIONAL
    }

Posted by 파파울프™
,
// Thrustmaster Cougar TQS USB Project

#include "Joystick.h"
#include <Wire.h>
#include <Adafruit_ADS1X15.h>
#include <EEPROM.h>

// Create Joystick
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 
  JOYSTICK_TYPE_JOYSTICK, 12, 0,
  true, true, false, true, true, false,
  false, true, false, false, false);

// Set to true to test "Auto Send" mode or false to test "Manual Send" mode.
Adafruit_ADS1115 ads1115;  /* Use this for the 16-bit version */

struct strCalibrationData {
  // 각종 축 MIN 값
  unsigned int minX;
  unsigned int minY;
  unsigned int minAnt;
  unsigned int minRng;
  unsigned int minThtl;
  
  // 각종 축 MAX 값
  unsigned int maxX;
  unsigned int maxY;
  unsigned int maxAnt;
  unsigned int maxRng;
  unsigned int maxThtl;
  
  // 각종 축 Center 값 (미사용)
  unsigned int centerX;
  unsigned int centerY;
  unsigned int centerAnt;
  unsigned int centerRng;
  unsigned int centerThtl;
};

// analog 측정값
unsigned int xAxis           = 0;    // 미니스틱X축
unsigned int yAxis           = 0;    // 미니스틱Y축
unsigned int antAxis         = 0;    // Ant. Elevation 축
unsigned int rngAxis         = 0;    // Range 축
unsigned int throttleAxis    = 0;    // 스로틀축

// 각종 축 Mapping 값
unsigned int mapXAxis        = 0;
unsigned int mapYAxis        = 0;
unsigned int mapAntAxis      = 0;
unsigned int mapRngAxis      = 0;
unsigned int mapThrottleAxis = 0;

// 아두이노 ADC 핀번호
int xPin            = A3;
int yPin            = 10;
int antPin          = A1;
int rngPin          = A0;
int throttlePin     = A2;

// 아두이노 버튼 핀번호
int  btnX1          = 4;
int  btnX2          = 5;
int  btnX3          = 6;
int  btnX4          = 7;

// 아두이노 Pulldown 출력 핀번호
int btnY1           = 8;
int btnY2           = 9;
int btnY3           = 14;

// 필터용 변수
float EMA_ax         = 0.6;
int   EMA_sx         = 0;

float EMA_ay         = 0.6;
int   EMA_sy         = 0;

float EMA_aAnt       = 0.6;
int   EMA_sAnt       = 0;

float EMA_aRng       = 0.6;
int   EMA_sRng       = 0;

float EMA_at         = 0.6;
int   EMA_st         = 0;

// 버튼 현재 값
int currButtonStateX[10] = {0,0,0,0,0,0,0,0,0,0};

// EEPROM 번지수
int addr            = 0;

// 시간측정용
unsigned long currentTime = 0;
boolean  isPressed        = false;
boolean  isSetupEnded     = false;
boolean  Startup          = true;
  
strCalibrationData caliData = {
  // 각종 축 MIN 값
  //142, 131, 0, 0, 137, 696, 664, 749, 749, 681, 0, 0, 0, 0, 0
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

 
void setup() {
  Joystick.begin();

  if (!ads1115.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }

  // Set Range Values
  Joystick.setXAxisRange(0, 32767);
  Joystick.setYAxisRange(0, 32767);
  Joystick.setRxAxisRange(0, 32767);
  Joystick.setRyAxisRange(0, 32767);
  Joystick.setThrottleRange(0, 32767);

  //ads1115.setGain(GAIN_TWOTHIRDS);
  ads1115.setGain(GAIN_ONE);
  ads1115.setDataRate(RATE_ADS1115_860SPS); // 860 samples per second

  EMA_sx    = analogRead(xPin);
  EMA_sy    = analogRead(yPin);
  EMA_sAnt  = analogRead(antPin);
  EMA_sRng  = analogRead(rngPin);
  EMA_st    = analogRead(throttlePin);

  // Initialize Button Pins
  pinMode(btnX1, INPUT);
  pinMode(btnX2, INPUT);
  pinMode(btnX3, INPUT);
  pinMode(btnX4, INPUT);
  pinMode(btnY1, OUTPUT);
  pinMode(btnY2, OUTPUT);
  pinMode(btnY3, OUTPUT);

  Serial.begin(9600);

  EEPROM.get(0, caliData);

  Serial.print(caliData.minX);
  Serial.print(" : ");
  Serial.print(caliData.centerX);
  Serial.print(" : ");
  Serial.print(caliData.maxX);
  Serial.print(" / ");
  Serial.print(caliData.minY);
  Serial.print(" : ");
  Serial.print(caliData.centerY);
  Serial.print(" : ");
  Serial.print(caliData.maxY);
  Serial.print(" / ");
  Serial.print(caliData.minAnt);
  Serial.print(" : ");
  Serial.print(caliData.maxAnt);
  Serial.print(" / ");
  Serial.print(caliData.minRng);
  Serial.print(" : ");
  Serial.print(caliData.maxRng);
  Serial.print(" / ");
  Serial.print(caliData.minThtl);
  Serial.print(" : ");
  Serial.print(caliData.maxThtl);
  Serial.println(" / ");
}

void loop() {

  // Analog축 처리
  analogAxisProcess();

  // 버튼 처리
  buttonMatrixProcess();

  // T6, T3 버튼 5초 입력시 캘리브레이션 시작
  if (currButtonStateX[8] == 0 && currButtonStateX[1] == 0)
  {
    if (isPressed == false)
    {
      isPressed = true;
      currentTime = millis();

      Serial.println(currentTime);
    }

    if (millis() - currentTime > 5000)
    {
      if (isSetupEnded == false)
      {
        Serial.println("SETUP");
        Calibration();
      }
    }
  }
  else if (currButtonStateX[8] == 0 && currButtonStateX[0] == 0)
  {
    if (isPressed == false)
    {
      isPressed = true;
      currentTime = millis();

      Serial.println(currentTime);
    }

    if (millis() - currentTime > 5000)
    {
      if (isSetupEnded == false)
      {
        Serial.println("RESET");
        Reset();
      }
    }
  }
  else
  {
    isPressed    = false;
    isSetupEnded = false;
    currentTime = millis();
  }

  //delay(100);
}

void Calibration()
{
  delay(100);
  Serial.println("--- START SAVE Cougar TQS Calibration DATA ---");

  // Serial.println(EEPROM.length());
  addr = 0;

  Serial.print(caliData.minX);
  Serial.print(" : ");
  Serial.print(caliData.maxX);
  Serial.print(" / ");
  Serial.print(caliData.minY);
  Serial.print(" : ");
  Serial.print(caliData.maxY);
  Serial.print(" / ");
  Serial.print(caliData.minAnt);
  Serial.print(" : ");
  Serial.print(caliData.maxAnt);
  Serial.print(" / ");
  Serial.print(caliData.minRng);
  Serial.print(" : ");
  Serial.print(caliData.maxRng);
  Serial.print(" / ");
  Serial.print(caliData.minThtl);
  Serial.print(" : ");
  Serial.print(caliData.maxThtl);
  Serial.println(" / ");

  EEPROM.put(addr, caliData);
  
//  EEPROM.write( 0, (byte) minX>>8);
//  EEPROM.write( 1, (byte) minX);
//  EEPROM.write( 2, (byte) maxX>>8);
//  EEPROM.write( 3, (byte) maxX);
//  EEPROM.write( 4, (byte) minY>>8);
//  EEPROM.write( 5, (byte) minY);
//  EEPROM.write( 6, (byte) maxY>>8);
//  EEPROM.write( 7, (byte) maxY);
//  EEPROM.write( 8, (byte) minAnt>>8);
//  EEPROM.write( 9, (byte) minAnt);
//  EEPROM.write(10, (byte) maxAnt>>8);
//  EEPROM.write(11, (byte) maxAnt);
//  EEPROM.write(12, (byte) minRng>>8);
//  EEPROM.write(13, (byte) minRng);
//  EEPROM.write(14, (byte) maxRng>>8);
//  EEPROM.write(15, (byte) maxRng);
//  EEPROM.write(16, (byte) minThtl>>8);
//  EEPROM.write(17, (byte) minThtl);
//  EEPROM.write(18, (byte) maxThtl>>8);
//  EEPROM.write(19, (byte) maxThtl);

  //while (addr < EEPROM.length())
//  while (addr < 40)
//  {
//    Serial.print(addr);
//    Serial.print("\t");
//    Serial.print(EEPROM.read(addr));
//    Serial.println();
//    addr++;
//  }
  
  isSetupEnded    = true;
  
  Serial.println("--- END SAVE Cougar TQS Calibration DATA ---");
}

void Reset()
{
  delay(100);
  Serial.println("--- START SAVE Cougar TQS Initial DATA ---");

  // Serial.println(EEPROM.length());
  addr = 0;

  caliData.minX    += 4000;
  caliData.maxX    -= 4000;
  caliData.minY    += 4000;
  caliData.maxY    -= 4000;
  caliData.minAnt  += 4000;
  caliData.maxAnt  -= 4000;
  caliData.minRng  += 400;
  caliData.maxRng  -= 400;
  caliData.minThtl += 4000;
  caliData.maxThtl -= 4000;

  Serial.print(caliData.minX);
  Serial.print(" : ");
  Serial.print(caliData.maxX);
  Serial.print(" / ");
  Serial.print(caliData.minY);
  Serial.print(" : ");
  Serial.print(caliData.maxY);
  Serial.print(" / ");
  Serial.print(caliData.minAnt);
  Serial.print(" : ");
  Serial.print(caliData.maxAnt);
  Serial.print(" / ");
  Serial.print(caliData.minRng);
  Serial.print(" : ");
  Serial.print(caliData.maxRng);
  Serial.print(" / ");
  Serial.print(caliData.minThtl);
  Serial.print(" : ");
  Serial.print(caliData.maxThtl);
  Serial.println(" / ");

  EEPROM.put(addr, caliData);
  
//  EEPROM.write( 0, (byte) minX>>8);
//  EEPROM.write( 1, (byte) minX);
//  EEPROM.write( 2, (byte) maxX>>8);
//  EEPROM.write( 3, (byte) maxX);
//  EEPROM.write( 4, (byte) minY>>8);
//  EEPROM.write( 5, (byte) minY);
//  EEPROM.write( 6, (byte) maxY>>8);
//  EEPROM.write( 7, (byte) maxY);
//  EEPROM.write( 8, (byte) minAnt>>8);
//  EEPROM.write( 9, (byte) minAnt);
//  EEPROM.write(10, (byte) maxAnt>>8);
//  EEPROM.write(11, (byte) maxAnt);
//  EEPROM.write(12, (byte) minRng>>8);
//  EEPROM.write(13, (byte) minRng);
//  EEPROM.write(14, (byte) maxRng>>8);
//  EEPROM.write(15, (byte) maxRng);
//  EEPROM.write(16, (byte) minThtl>>8);
//  EEPROM.write(17, (byte) minThtl);
//  EEPROM.write(18, (byte) maxThtl>>8);
//  EEPROM.write(19, (byte) maxThtl);

  //while (addr < EEPROM.length())
//  while (addr < 40)
//  {
//    Serial.print(addr);
//    Serial.print("\t");
//    Serial.print(EEPROM.read(addr));
//    Serial.println();
//    addr++;
//  }
  
  isSetupEnded    = true;
  
  Serial.println("--- END SAVE Cougar TQS Initial DATA ---");
}

void analogAxisProcess()
{
  //xAxis           = analogRead(xPin);
  //yAxis           = analogRead(yPin);
  //antAxis         = analogRead(antPin);
  rngAxis         = analogRead(rngPin);
  //throttleAxis    = analogRead(throttlePin);

  // Use ADS1115 
  throttleAxis    = ads1115.readADC_SingleEnded(0);
  xAxis           = ads1115.readADC_SingleEnded(2);
  yAxis           = ads1115.readADC_SingleEnded(1);
  //antAxis         = ads1115.readADC_SingleEnded(3);
  antAxis = twosComplement(ads1115.readADC_SingleEnded(3));
  
//  Serial.print("X:");
//  Serial.print(xAxis);
//  Serial.print("  Y:");
//  Serial.print(yAxis);
//  Serial.print("  ANT:");
//  Serial.print(antAxis);
//  Serial.print("  RNG:");
//  Serial.print(mapRngAxis);
//  Serial.print("  Throttle:");
//  Serial.print(throttleAxis);
//  Serial.println();

  if (caliData.minX    > xAxis)        caliData.minX    = xAxis;        caliData.centerX = caliData.minX + ((caliData.maxX - caliData.minX) / 2);
  if (caliData.minY    > yAxis)        caliData.minY    = yAxis;        caliData.centerY = caliData.minY + ((caliData.maxY - caliData.minY) / 2);
  if (caliData.minAnt  > antAxis)      caliData.minAnt  = antAxis;
  if (caliData.minRng  > rngAxis)      caliData.minRng  = rngAxis;
  if (caliData.minThtl > throttleAxis) caliData.minThtl = throttleAxis;
  
  if (caliData.maxX    < xAxis)        caliData.maxX    = xAxis;
  if (caliData.maxY    < yAxis)        caliData.maxY    = yAxis;
  if (caliData.maxAnt  < antAxis)      caliData.maxAnt  = antAxis;
  if (caliData.maxRng  < rngAxis)      caliData.maxRng  = rngAxis;
  if (caliData.maxThtl < throttleAxis) caliData.maxThtl = throttleAxis;

  EMA_sx   = (EMA_ax   * xAxis)        + ((1 - EMA_ax  ) * EMA_sx  );
  EMA_sy   = (EMA_ay   * yAxis)        + ((1 - EMA_ay  ) * EMA_sy  );
  EMA_sAnt = (EMA_aAnt * antAxis)      + ((1 - EMA_aAnt) * EMA_sAnt);
  EMA_sRng = (EMA_aRng * rngAxis)      + ((1 - EMA_aRng) * EMA_sRng);
  EMA_st   = (EMA_at   * throttleAxis) + ((1 - EMA_at  ) * EMA_st  );
  
  mapXAxis        = map(EMA_sx  , caliData.minX  ,  caliData.maxX  ,    32767, 0);
  mapYAxis        = map(EMA_sy  , caliData.minY  ,  caliData.maxY  ,    32767, 0);
  mapAntAxis      = map(EMA_sAnt, caliData.minAnt,  caliData.maxAnt,    0, 32767);
  mapRngAxis      = map(EMA_sRng, caliData.minRng,  caliData.maxRng,    0, 32767);
  mapThrottleAxis = map(EMA_st  , caliData.minThtl, caliData.maxThtl,   0, 32767);

  Joystick.setXAxis(mapXAxis);
  Joystick.setYAxis(mapYAxis);
  Joystick.setRxAxis(mapAntAxis);
  Joystick.setRyAxis(mapRngAxis);
  Joystick.setThrottle(mapThrottleAxis);

//  Serial.print("X:");
//  Serial.print(mapXAxis);
//  Serial.print("  Y:");
//  Serial.println(yAxis);
//  Serial.print("  ANT:");
//  Serial.print(mapAntAxis);
//  Serial.print("  RNG:");
//  Serial.print(mapRngAxis);
//  Serial.print("  Throttle:");
//  Serial.print(mapThrottleAxis);
//  Serial.print(" ||| ");
//  Serial.print(caliData.minX);
//  Serial.print(" : ");
//  Serial.print(caliData.maxX);
//  Serial.print(" / ");
//  Serial.print(caliData.minY);
//  Serial.print(" : ");
//  Serial.print(caliData.maxY);
//  Serial.print(" / ");
//  Serial.print(caliData.minAnt);
//  Serial.print(" : ");
//  Serial.print(caliData.maxAnt);
//  Serial.print(" / ");
//  Serial.print(caliData.minRng);
//  Serial.print(" : ");
//  Serial.print(caliData.maxRng);
//  Serial.print(" / ");
//  Serial.print(caliData.minThtl);
//  Serial.print(" : ");
//  Serial.print(caliData.maxThtl);
//  Serial.println(" / ");
}

void buttonMatrixProcess()
{
  digitalWrite(btnY1, LOW);
  delay(1);
  currButtonStateX[0] = digitalRead(btnX1);
  currButtonStateX[1] = digitalRead(btnX2);
  currButtonStateX[2] = digitalRead(btnX3);
  currButtonStateX[3] = digitalRead(btnX4);
  digitalWrite(btnY1, HIGH);

  digitalWrite(btnY2, LOW);
  delay(1);
  currButtonStateX[4] = digitalRead(btnX1);
  currButtonStateX[5] = digitalRead(btnX2);
  currButtonStateX[6] = digitalRead(btnX3);
  currButtonStateX[7] = digitalRead(btnX4);
  digitalWrite(btnY2, HIGH);

  digitalWrite(btnY3, LOW);
  delay(1);
  currButtonStateX[8] = digitalRead(btnX1);
  currButtonStateX[9] = digitalRead(btnX2);
  digitalWrite(btnY3, HIGH);

  // T1 CURSOR ENABLE
  if (currButtonStateX[9] == 0)
  {
    Joystick.setButton(0, true);
  }
  else
  {
    Joystick.setButton(0, false);
  }
  
  // T2 UP VHF
  if (currButtonStateX[1] == 0)
  {
    Joystick.setButton(1, true);
  }
  else
  {
    Joystick.setButton(1, false);
  }

  // T3 DOWN UHF
  if (currButtonStateX[0] == 0)
  {
    Joystick.setButton(2, true);
  }
  else
  {
    Joystick.setButton(2, false);
  }

  // T4 RIGHT IFF OUT
  if (currButtonStateX[3] == 0)
  {
    Joystick.setButton(3, true);
  }
  else
  {
    Joystick.setButton(3, false);
  }

  // T5 LEFT IFF IN
  if (currButtonStateX[2] == 0)
  {
    Joystick.setButton(4, true);
  }
  else
  {
    Joystick.setButton(4, false);
  }

  // T6 UNCAGE
  if (currButtonStateX[8] == 0)
  {
    Joystick.setButton(5, true);
  }
  else
  {
    Joystick.setButton(5, false);
  }

  // T7 DIGFIGHT OVERRIDE
  if (currButtonStateX[4] == 0)
  {
    Joystick.setButton(6, true);
  }
  else
  {
    Joystick.setButton(6, false);
  }

  // T8 MRM OVERRIDE
  if (currButtonStateX[5] == 0)
  {
    Joystick.setButton(7, true);
  }
  else
  {
    Joystick.setButton(7, false);
  }

  // T9 OPEN AIRBRAKE
  if (currButtonStateX[6] == 0)
  {
    Joystick.setButton(8, true);
  }
  else
  {
    Joystick.setButton(8, false);
  }

  // T10 CLOSE AIRBRAKE
  if (currButtonStateX[7] == 0)
  {
    Joystick.setButton(9, true);
  }
  else
  {
    Joystick.setButton(9, false);
  }

  // T11 NAV MODE
  if ((currButtonStateX[4] == 1) && (currButtonStateX[5] == 1))
  {
    Joystick.setButton(10, true);
  }
  else
  {
    Joystick.setButton(10, false);
  }

  // T12 MID AIRBRAKE
  if ((currButtonStateX[6] == 1) && (currButtonStateX[7] == 1))
  {
    Joystick.setButton(11, true);
  }
  else
  {
    Joystick.setButton(11, false);
  }

//  Serial.print("BTN : ");
//  Serial.print(currButtonStateX[0]);
//  Serial.print(currButtonStateX[1]);
//  Serial.print(currButtonStateX[2]);
//  Serial.print(currButtonStateX[3]);
//  Serial.print(currButtonStateX[4]);
//  Serial.print(currButtonStateX[5]);
//  Serial.print(currButtonStateX[6]);
//  Serial.print(currButtonStateX[7]);
//  Serial.print(currButtonStateX[8]);
//  Serial.print(currButtonStateX[9]);
//  Serial.println(" ");
}

unsigned int twosComplement(unsigned int value)
{
  if (value >= 0x8000){
    //Serial.println("OVER");

    value = 0;
  }
  return value;
}
Posted by 파파울프™
,

사진정리 sqlite3에서 mariaDB로 변경

ExifTool 설치 참고 블로그 : https://devst.tistory.com/108

 

common_utils.py

import os, datetime, sys
import exiftool
import hashlib
import json


# exiftool 사용 함수
def get_exif_info(file_path):

    #print("FILE LOCATION : " + file_path)
    create_date    = ""
    metadata       = {}
    format_str1    = '%Y:%m:%d %H:%M:%S'
    format_str2    = '%d/%m/%Y %H:%M'
    exif_date_str = ""
    file_date_str = ""
    hash_str      = ""
    file_size     = 0

    with exiftool.ExifTool() as et:
        metadata = et.get_metadata(file_path)

        #print(len(metadata))

        if len(metadata) > 0: 

            #print(metadata)

            # DB등록시 오류나는 항목 삭제 (특수기호, 깨지는 한글 등등)
            if 'EXIF:UserComment' in metadata:
                del metadata['EXIF:UserComment']
            if 'QuickTime:CompressorName' in metadata:
                del metadata['QuickTime:CompressorName']
            if 'ExifTool:Warning' in metadata:
                del metadata['ExifTool:Warning']
            if 'MakerNotes:AFPointsInFocus1D'  in metadata:
                del metadata['MakerNotes:AFPointsInFocus1D']

            for tag in metadata.keys():
                #print("Key: %s, value %s" % (tag, metadata[tag]))
                if tag in ('EXIF:DateTimeOriginal'): # 사진 촬영할 일자
                    #print("Key: %s, value %s" % (tag, metadata[tag]))
                    exif_date_str = str(metadata[tag])
                if tag in ('QuickTime:CreateDate'):  # 동영상 촬영 일자
                    #print("Key: %s, value %s" % (tag, metadata[tag]))
                    exif_date_str = str(metadata[tag])
                if tag in ('File:FileModifyDate'): # 카톡 등으로 받은 사진들
                    #print("Key: %s, value %s" % (tag, metadata[tag]))
                    file_date_str = str(metadata[tag])
                if tag in ('File:FileSize'):
                    file_size = metadata[tag]

            if (exif_date_str == '') and (file_date_str == ''):
                for tag in metadata.keys():
                    print("Key: %s, value %s" % (tag, metadata[tag]))
            else:
                #print("exif_date_str" + exif_date_str)
                #print("exif_date_str" + exif_date_str)
                if ((exif_date_str == '') or (exif_date_str == '0000:00:00 00:00:00')) and (file_date_str != ''):
                    exif_date_str = file_date_str[0:19]

                try:
                    exif_date = datetime.datetime.strptime(exif_date_str, format_str1)
                    file_date = datetime.datetime.strptime(file_date_str[0:19], format_str1)

                    if (exif_date < file_date):
                        create_date = exif_date.strftime('%Y-%m-%d')
                    else :
                        create_date = file_date.strftime('%Y-%m-%d')
                    #print(create_date)
                except ValueError as ve:
                    exif_date = datetime.datetime.strptime(exif_date_str, format_str2)
                    file_date = datetime.datetime.strptime(file_date_str[0:19], format_str1)

                    if (exif_date < file_date):
                        create_date = exif_date.strftime('%Y-%m-%d')
                    else :
                        create_date = file_date.strftime('%Y-%m-%d')
            # Dictionary -> JSON
            exif_str = json.dumps(metadata)

        if (file_size <= 1024000000):
            f = open(file_path, 'rb')
            data = f.read()
            f.close

            hash_str = hashlib.sha256(data).hexdigest()

    return create_date, exif_str, hash_str

 

photo_exif_copy.py

import os, datetime, shutil, pymysql, sys
import exiftool
import common_utils as ut
from logging.config import dictConfig
import logging

## 정리할 사진, 동영상 디렉토리
dir_path = '' 

# 정리된 파일을 모을 디렉토리
go_path     = "/volume2/백업할디렉토리/"   ## 하위에 yyyy / yyyy-mm-dd 순으로 백업됨
dest_path   = ''
target_date = ''
ext_list    = (".JPG", ".JPEG", ".PNG", ".NEF", ".HEIC", ".3GP", ".MOV", ".MP4", ".DNG", ".TIF", ".TIFF", ".CR2", ".CRW", ".RW2")

conn = pymysql.connect(host='localhost', user='유저명', password='비밀번호', db='디비명', charset='utf8', port=3307)

c = conn.cursor()
iCnt = 0

## 정리할 사진, 동영상 디렉토리 없을 경우 파라미터로 지정
if (dir_path == ''):
    dir_path = sys.argv[1]

dictConfig({
    'version': 1,
    'formatters': {
        'default': {
            'format': '[%(asctime)s] %(message)s',
        }
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': 'debug.log',
            'formatter': 'default',
        },
    },
    'root': {
        'level': 'DEBUG',
        'handlers': ['file']
    }
})


try:
    # 디렉토리 구조 돌면서 처리
    for (root, directories, files) in os.walk(dir_path) :
        for d in directories :
            d_path = os.path.join(root, d)
        #print(d_path)

        for file in files :
            file_path = os.path.join(root, file)
            #print(file_path)

            file_size = 0

            if "@eaDir" not in file_path:
                file_dir, file_name = os.path.split(file_path)
                file_dir, file_ext  = os.path.splitext(file_path)
                file_size = os.path.getsize(file_path)

                #print("FILE LOCATION : " + file_path)

                sql = "SELECT idx, file_loc, file_name, copy_yn, copy_loc, reg_date, mod_date FROM photo WHERE file_loc = '%s';" % (file_path)
                #print(sql)
                c.execute(sql)

                data1 = c.fetchone()

                copy_yn = 'N'
                copy_str = 'N'

                #print(data1)
                if (data1 == None):
                    copy_yn = 'N'

                elif (data1[3] == 'Y'):
                    update_sql = "UPDATE photo SET mod_date = NOW() WHERE idx = '%s';" % data1[0]
                    print(update_sql)
                    c.execute(update_sql)
                    conn.commit

                    copy_yn = 'Y'
                    print(file_path + " Already Done!")
                elif (data1[3] == 'N'):
                    copy_yn = 'U'

                target_date = ''
                exif_str    = {}
                hash_str    = ''
                dest_path   = ''

                # 파일 복사 대상이면 처리
                if (copy_yn != 'Y'):
                    # 정리할 파일 확장자 정의
                    if (file_ext.upper() in ext_list):
                        #target_date = get_exif_info(file_path)
                        target_date, exif_str, hash_str = ut.get_exif_info(file_path)

                        #print(exif_str)

                        if (len(target_date) == 10):
                            dest_path = go_path + "/" + target_date[0:4] + "/" + target_date+  "/"
                            #print(dest_path + " : " + str(len(target_date)))
                            if (os.path.isdir(dest_path) == False):
                                os.makedirs(dest_path)
                            shutil.copy2(file_path, dest_path + file_name)

                            copy_str = 'Y'
                        else:
                            dest_path = go_path + "/ERROR/"

                            if (os.path.isdir(dest_path) == False):
                                os.makedirs(dest_path)

                            shutil.copy2(file_path, dest_path + file_name)
                            copy_str = ''
                    else:
                        dest_path = go_path + "/ERROR/"

                        if (os.path.isdir(dest_path) == False):
                            os.makedirs(dest_path)

                        shutil.copy2(file_path, dest_path + file_name)
                        copy_str = 'N'

                    now = datetime.datetime.now()
                    nowStr = now.strftime('%Y-%m-%d %H:%M:%S')

                    param2 = (file_path, file_name, copy_str, dest_path + file_name, file_size, hash_str, exif_str)
                    insert_sql = "INSERT INTO photo (file_loc, file_name, copy_yn, copy_loc, file_size, hash, exif) VALUES ('%s', '%s', '%s', '%s', %s, '%s', '%s');" % param2
                    #print(insert_sql)
                    c.execute(insert_sql)

                #print("FILE LOCATION : " + file_path + " / " + dest_path + " / " + str(file_size))
                logging.debug("FILE LOCATION : " + file_path + " / " + dest_path + " / " + str(file_size))

                iCnt = iCnt + 1

                if (iCnt % 10) == 0:
                    conn.commit()
                    print("#######################################")
                    print(" %d : Commit!!!" % iCnt)
                    print("#######################################")

    conn.commit()

    print("#######################################")
    print(" %d : Commit!!!" % iCnt)
    print("#######################################")

except Exception as inst:
    print(insert_sql)
    logging.debug(inst)
    logging.debug("exif_str : " + exif_str)
    logging.debug("insert_sql : " + insert_sql)
finally:

    conn.close()

 

테이블 생성 SQL

CREATE TABLE `photo` (
  `IDX` int(10) NOT NULL,
  `FILE_LOC` varchar(300) DEFAULT NULL,
  `FILE_NAME` varchar(100) DEFAULT NULL,
  `COPY_YN` varchar(1) DEFAULT NULL,
  `COPY_LOC` varchar(300) DEFAULT NULL,
  `FILE_SIZE` bigint(20) DEFAULT NULL,
  `hash` varchar(100) DEFAULT NULL,
  `exif` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
  `REG_DATE` datetime DEFAULT current_timestamp(),
  `MOD_DATE` datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Posted by 파파울프™
,

시놀로지 기본 포토 + 기기별 백업의 혼돈의 상황이라

exif에서 촬영일자 or 파일생성일자를 뽑아서 YYYY + YYYYMMDD 별 폴더로 정리하려고 시작함.

파이썬 exifread 라이브러리를 써보다 동영상의 exif 가 읽혀지지 않아 

ExifTool로 변경함

설치 및 참고 : https://devst.tistory.com/108

 

PyExifTool 을 이용해서 Python 으로 사진과 동영상의 Exif 읽기

날씨도 쌀쌀해지고 어느 덧 가을.. 문득 그러고 싶을 때가 있다. 사진과 동영상의 Exif Meta Data 를 읽고 싶다는 생각이 들때가 있다. 그럴 때는 이렇게 하면 좋다. 먼저 ExifTool 의 설치 sudo apt-get inst

devst.tistory.com

 

#!/usr/bin/env python3

import os, datetime, exifread, shutil
import exiftool
import sqlite3
import json

from site import venv
from pickle import FALSE

from PIL import Image
from PIL.ExifTags import TAGS


## 정리할 사진, 동영상 디렉토리
dir_path = "/volume1/photo"

# 정리된 파일을 모을 디렉토리
go_path  = "/volume2/backup_photo/Test"

target_date = ''


# exifread 사용 함수
def get_exif_info(file_path):

    print(file_path)
    tags          = {}
    format_str1   = '%Y:%m:%d %H:%M:%S'
    format_str2   = '%d/%m/%Y %H:%M'
    exif_date_str = ''
    create_date   = ''

    with open(file_path, 'rb') as f:
        tags = exifread.process_file(f)
       
        if len(tags) > 0:

            for tag in tags.keys():
                if tag in ('Image DateTime'):
                    #print("Key: %s, value %s" % (tag, tags[tag]))
                    exif_date_str = str(tags[tag])

            if (exif_date_str == ''):
                for tag in tags.keys():
                    print("Key: %s, value %s" % (tag, tags[tag]))
            else:
                try:
                    exix_date = datetime.datetime.strptime(exif_date_str, format_str1)
                    create_date = exix_date.strftime('%Y-%m-%d')
                except ValueError as ve:
                    exix_date = datetime.datetime.strptime(exif_date_str, format_str2)
                    create_date = exix_date.strftime('%Y-%m-%d')
                else:
                    create_date = ""

    return create_date
           
# exiftool 사용 함수
def get_exif_info2(file_path):

    #print("FILE LOCATION : " + file_path)
    create_date    = ""
    metadata       = {}
    format_str1    = '%Y:%m:%d %H:%M:%S'
    format_str2    = '%d/%m/%Y %H:%M'
    exif_date_str = ""
    file_date_str = ""

    with exiftool.ExifTool() as et:
        metadata = et.get_metadata(file_path)

        #print(metadata)
        #print(len(metadata))

        if len(metadata) > 0:

            for tag in metadata.keys():
                #print("Key: %s, value %s" % (tag, metadata[tag]))
                if tag in ('EXIF:DateTimeOriginal'): # 사진 촬영할 일자
                    #print("Key: %s, value %s" % (tag, metadata[tag]))
                    exif_date_str = str(metadata[tag])
                if tag in ('QuickTime:CreateDate'):  # 동영상 촬영 일자
                    #print("Key: %s, value %s" % (tag, metadata[tag]))
                    exif_date_str = str(metadata[tag])
                if tag in ('File:FileModifyDate'): # 카톡 등으로 받은 사진들
                    #print("Key: %s, value %s" % (tag, metadata[tag]))
                    file_date_str = str(metadata[tag])


            if (exif_date_str == '') and (file_date_str == ''):
                for tag in metadata.keys():
                    print("Key: %s, value %s" % (tag, metadata[tag]))
            else:
                #print("exif_date_str" + exif_date_str)
                #print("exif_date_str" + exif_date_str)
                if ((exif_date_str == '') or (exif_date_str == '0000:00:00 00:00:00')) and (file_date_str != ''):
                    exif_date_str = file_date_str[0:19]
                    #print("exif_date_str : " + exif_date_str)

                try:
                    exix_date = datetime.datetime.strptime(exif_date_str, format_str1)
                    create_date = exix_date.strftime('%Y-%m-%d')
                    #print(create_date)
                except ValueError as ve:
                    exix_date = datetime.datetime.strptime(exif_date_str, format_str2)
                    create_date = exix_date.strftime('%Y-%m-%d')
                    #print(create_date)
                #else:
                    #create_date = ""

    return create_date

conn = sqlite3.connect("all_photos.db", isolation_level=None)

c = conn.cursor()

# 디렉토리 구조 돌면서 처리
for (root, directories, files) in os.walk(dir_path) :
    for d in directories :
        d_path = os.path.join(root, d)
       #print(d_path)

    for file in files :
        file_path = os.path.join(root, file)
        #print(file_path)

        if "@eaDir" not in file_path:
            file_dir, file_name = os.path.split(file_path)
            file_dir, file_ext  = os.path.splitext(file_path)

            print("FILE LOCATION : " + file_path)

            param1 = (file_path,)
            c.execute("SELECT idx, file_loc, file_name, copy_yn, copy_loc, reg_date, mod_date FROM photo WHERE file_loc = ?", param1)
            data1 = c.fetchone()

            copy_yn = 'N'

            #print(data1)
            if (data1 == None):
                now = datetime.datetime.now()
                nowStr = now.strftime('%Y-%m-%d %H:%M:%S')

                param2 = (file_path, file_name, 'N', '', nowStr, nowStr)
                c.execute("INSERT INTO photo (file_loc, file_name, copy_yn, copy_loc, reg_date, mod_date) VALUES (?, ?, ?, ?, ?, ?)", param2)
                copy_yn = 'N'

            elif (data1[3] == 'Y'):
                now = datetime.datetime.now()
                nowStr = now.strftime('%Y-%m-%d %H:%M:%S')
                param3 = (nowStr, file_path,)
                c.execute("UPDATE photo SET mod_date = ? WHERE file_loc = ?", param3)

                copy_yn = 'Y'
                print(file_path + " Already Done!")
            elif (data1[3] == 'N'):
                copy_yn = 'N'

            # 파일 복사 대상이면 처리
            if (copy_yn == 'N'):
                # 정리할 파일 확장자 정의
                if (file_ext.upper() in (".JPG", ".PNG", ".NEF", ".HEIC", ".MOV", ".MP4", ".DNG")):
                    target_date = ''
                    #target_date = get_exif_info(file_path)
                    target_date = get_exif_info2(file_path)

                    #print("CREATE DATE : " + target_date)

                    if (len(target_date) == 10):
                        dest_path = go_path + "/" + target_date[0:4] + "/" + target_date+  "/"
                        print(dest_path + " : " + str(len(target_date)))
                        if (os.path.isdir(dest_path) == False):
                            os.makedirs(dest_path)
                        shutil.copy2(file_path, dest_path + file_name)

                        now = datetime.datetime.now()
                        nowStr = now.strftime('%Y-%m-%d %H:%M:%S')
                        param4 = (dest_path + file_name, nowStr, file_path)
                        c.execute("UPDATE photo SET copy_yn = 'Y', copy_loc = ?, mod_date = ? WHERE file_loc = ?", param4)


conn.close
SQLite3 테이블 생성 DDL
 
CREATE TABLE "photo" (
"IDX" INTEGER NOT NULL UNIQUE,
"FILE_LOC" TEXT,
"FILE_NAME" TEXT,
"COPY_YN" TEXT,
"COPY_LOC" INTEGER,
"REG_DATE" TEXT,
"MOD_DATE" TEXT,
PRIMARY KEY("IDX" AUTOINCREMENT)
)
Posted by 파파울프™
,

http://liveelectronics.musinou.net/MIDIdeviceName.php

 

MIDI device with a name of your choice

 

liveelectronics.musinou.net

 

2018-01-19.zip
0.04MB

 

1. 다운받은 부트로더 C:\user\사용자명\Arduino\hardware\ 안에 압축풀기

2. board.txt 수정

 

3. 보드 설정

 

4. 스케치 업로드

 

Posted by 파파울프™
,