2023년 2월 15일 수요일

OPC UA python 연동

 ** OPC UA python 테스트 ** 

0. python으로 OPC UA의 서버-클라이언트 통신을 테스트한다
1. https://dibrary.tistory.com/39 (서버부) 참고해서 실행
   -단, 통신 포트를 4842에서 안되서 12346으로 해서 성공하였음
2. 아래 UaExpert 설치하여 서버에서 발생하는 데이터를 모니터링 할 수 있음
   -OPC UA python용어들에 대한 설명은 https://red-nose-cousin.tistory.com/4 참고함.
3. https://dibrary.tistory.com/38 (Client부) 참고해서 서버에서 오는 신호를 확인 가능


** UaExpert 설치 **

0. UaExpert는 OPC UA python의 서버 부분 실행 후에, 발생하는 데이터를 모니터링하는 툴
2. 회원 가입함
3. Download -> OPC UA Clients -> UaExpert를 다운로드
4. Windows10에 설치 후, 실행
매뉴얼의 12~15페이지 참고.

- UaExpert실행->Project>Server선택후 마우스 우클릭 'Add'선택->Local마우스 우클릭 후 Edit Discovery URL선택->IP와 Port number입력


# Server부 프로그램

import time
from opcua import Server

server = Server()

url = "opc.tcp://127.0.0.1:12346"
server.set_endpoint(url)

name = "OPCUA_SIMULATION_SERVER"
addspace = server.register_namespace(name)
node = server.get_objects_node()

param1 = node.add_object(addspace, "251-AM-001")
param2 = node.add_object(addspace, "251-AM-002")

normal_operation1 = param1.add_variable("ns=1; s=1630AT155-NO", "normal_operation", 0)
normal_operation2 = param2.add_variable("ns=2; i=34", "test_node", 12)
normal_operation2.set_writable()
normal_operation1.set_writable()

server.start()



# Client부 프로그램

from opcua import Client
import time

url = "opc.tcp://127.0.0.1:12346"
client = Client(url)
client.connect()

cnt = 0
while cnt <= 2:
    normal = client.get_node("ns=1; s=1630AT155-NO")
    print(normal.get_value())
    time.sleep(2)
    normal.set_value(22)
    print(normal.get_value())
    time.sleep(4)
    cnt += 1

cnt = 0
while cnt <= 2:
    normal = client.get_node("ns=2; i=34")
    print(normal.get_value())
    time.sleep(2)
    normal.set_value(12346)
    print(normal.get_value())
    time.sleep(4)
    cnt += 1



[References]


2023년 2월 13일 월요일

MySQL 사용법

 [Windows에서 MySQL 사용법]

Docker 설치 후, mysql를 pull하여 image 다운 후 실행

> docker run --name mysql_test -e MYSQL_ROOT_PASSWORD=1234 -d
-p 3306:3306 mysql:latest
> docker exec -it ee18155087ae /bin/bash
# mysql -u root -p

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

: 에러 메세지 나옴

> docker ps -a
ee18155087ae   mysql:latest      "docker-entrypoint.s…"   5 minutes ago   Exited (0) 7 seconds ago mysql-container
598d87a1bddc   mysql             "docker-entrypoint.s…"   8 days ago      Exited (255) 41 hours ago 0.0.0.0:3306->3306/tcp, 33060/tcp   mysql_test
....

이미 실행된 후 정지된 container있음(port 3306번을 이미 물고 있어서 오류가 남).

실행 중인 container 모두 정지 후, 기존 container 제거.

> docker stop ee18155087ae  # 실행 중인 container들 정지
> docker rm -f 598d87a1bddc  # 기존 container 제거
> docker restart ee18155087ae  # 재시작
...
# mysql -u root -p

비번 1234 넣으니 정상 실행 되며, mysql> prompt로 들어감


db생성하고, 생성된 db 선택 후, table 생성. data를 몇 개 삽입.

mysql> create database opentutorials;  # db생성
mysql> drop database opentutorials;  # db제거
mysql> show databases;  # db보기
mysql> use opentutorials;  # db선택
mysql> create table topic(  # ";" 안 넣으면 ->로 넘어감
      ->     id int(11) not null auto_increment,
      ->     title varchar(100) not null,
      ->     description text null,
      ->     created datetime not null,
      ->     author varchar(30 null,
      ->     profile varchar(100) null,
      ->     primary key(id));
mysql> show tables;  # 생성 table 확인
mysql> desc topic;  # 입력 속성 확인(description)
mysql> insert into topic (title,description,created,author,profile)
values('mysql','mysql is ...',NOW(),'kdj','developer');
mysql> select * from topic;  # 삽입된 데이터 확인
mysql> insert into topic (title,description,created,author,profile)
values('oracle','oracle is ...',NOW(),'egoing','developer');
mysql> select * from topic;
mysql> insert into topic (title,description,created,author,profile)
values('postgresql','postgresql is ...',NOW(),'egoing','data scientist, developer');
mysql> insert into topic (title,description,created,author,profile)
values('mongdb','mongodb is ...',NOW(),'egoing','developer');

일부 data만 선택하여 확인해 보기

mysql> select id,title,created,author from topic;  # 일부 속성만 선택해 data확인
# author지정 data 선택 / 순서까지 지정 / 건수도 지정
mysql> select id,title,created,author from topic where author='egoing';  
mysql> select id,title,created,author from topic where author='egoing' order by id desc;  
mysql> select id,title,created,author from topic where author='egoing'
order by id desc limit 2;  
mysql>


[python 연동]

> pip install mysql-connector-python


import mysql.connector

mydb = mysql.connector.connect(
  host="localhost",
  user="root",
  password="1234",
  database="opentutorials"
)

mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM topic")
myresult = mycursor.fetchall()
for x in myresult:
  print(x)

mycursor.execute("insert into topic (title,description,created,author,profile)
       values('sqlserver','sqlserver is ...',NOW(),'kaka','database administrator')");

# 데이터베이스 변경 내용 저장
mydb.commit()

출력물:

(1, 'mysql', 'mysql is ...', datetime.datetime(2023, 5, 10, 2, 39, 5), 'kdj', 'developer')
(2, 'oracle', 'oracle is ...', datetime.datetime(2023, 5, 10, 2, 41, 9), 'egoing', 'developer')
(3, 'postgresql', 'postgresql is ...', datetime.datetime(2023, 5, 10, 2, 43, 5), 'hahaha', 'data scientist, developer')
(4, 'mongdb', 'mongodb is ...', datetime.datetime(2023, 5, 10, 2, 43, 46), 'kaka', 'developer')
(5, 'sqlserver', 'sqlserver is ...', datetime.datetime(2023, 5, 10, 5, 16, 31), 'kaka', 'database administrator')


[References]

1. https://opentutorials.org/course/3161


2023년 2월 10일 금요일

JPEG 이미지에서 GPS 위치 정보 추출 후, 주소로 전환

JPEG 이미지에서 GPS 위치 정보 추출 후, 주소로 전환.

이미지가 획득된 시간 정보도 출력. 


# From Image through GPS location to Address
from geopy.geocoders import Nominatim
from exif import Image as exImg


def geocoding_reverse(lat_lng_str):
    geolocoder = Nominatim(user_agent = 'South Korea', timeout=None)
    address = geolocoder.reverse(lat_lng_str)
    return address

def decimal_coords(coords, ref):
    decimal_degrees = coords[0] + coords[1] / 60 + coords[2] / 3600
    if ref == "S" or ref =='W' :
        decimal_degrees = -decimal_degrees
    return decimal_degrees

def image_coordinates(img):
    if img.has_exif:
        try:
            coords = (decimal_coords(img.gps_latitude, img.gps_latitude_ref),
                         decimal_coords(img.gps_longitude, img.gps_longitude_ref))
        except AttributeError:
            print ('No Coordinates')
            return {}
    else:
        print ('The Image has no EXIF information')
        return {}
    return {"imageTakenTime":img.datetime_original, "geolocation_lat":coords[0],"geolocation_lng":coords[1]}


image_path = 'bbb.jpg"
with open(image_path, 'rb') as src:
    img = exImg(src)

img_info = image_coordinates(img)
if "imageTakenTime" in img_info:
    posi = '{},{}'.format(img_info["geolocation_lat"],img_info["geolocation_lng"])
    address = geocoding_reverse(posi)
    print(img_info["imageTakenTime"], address)

#address = geocoding_reverse('36.5760732781656, 128.15935928504484')
#print(address)

2023년 2월 1일 수요일

PostgreSQL 설치 및 사용법

/* PostgreSQL 설치 및 사용법
 * (1) 설치(PostgreSQL과 DBeaver): Youbube를 참고하여 설치하였음
 * (2) SQL 기본 구문 구조 이해
 * (3) 파이썬 연결 관련
 * (4) SQL shell 명령(psql)
 * (5) 이미지 파일의 저장(BYTEA)
 * (6) 저장된 파일 경로
 *      d:\2023\postgresql\test_script.sql
 *      data도 있음
 */


/* (1) PostgreSQL과 DBeaver 설치
 *   Win10기준으로 Youtube를 참조하여 설치
 */
--자세한 내용은 Youtube를 참조함

/*
 * (2) SQL 기본 구문 구조 이해
 *   테스트 data는 (2)의 Youtube에 있음
 *   DBeaver에서 테스트(test_scripts.sql)
 */
-- 실행할 구문 선택 후 ^+Enter로 실행

select * from prod_cat_info;
select * from transactions;
select * from city;
select * from customer;


/* 테스트(필터링) 구문 */
select          count(distinct a.transaction_id) as cnt_orders
    ,       sum(a.total_amt) as sum_amt
    ,       max(a.tran_date) as latest_tran_date
from        transactions a
--where         total_amt > 0
--group by  customer_id
--having        count(discount transaction_id) >= 2
--order by  sum_amt desc
--limit         12;

-- c는 alias(별칭), distinct는 구별되는 유니크한 것만 추출


select      count(c.customer_id)
    ,       count(distinct c.transaction_id)
    ,       sum(c.total_amt)
from        transactions c;


select      a.customer_id       as  고객번호
    ,       a.tran_date         as  거래일자
    ,       a.rate              as  판매가
    ,       a.qty               as  주문수량
    ,       a.total_amt         as  주문금액
from        transactions a;


select      count(distinct  b.transaction_id)
        ,   count(distinct  b.customer_id)
        ,   sum(b.total_amt)
from        transactions b;


-- 중복포함 모두 출력
select      store_type
from        transactions;


-- 중복된 것은 제거하고 서로 다른 것만 출력
select      distinct store_type
from        transactions ;


-- 문자 형식의 리터럴은 ''으로 감싸서 입력
-- 날짜 리터럴은 date키워드와 함께 날짜형식으로 입력
-- 날짜와 nation이 일치하는 데이터만 추출
select      a.city_code
    ,       a.city_name
    ,       'KOREA'                 as  nation
    ,       date '2021-09-26'       as  insert_dt
    ,       4923                    as  number_literal
from        city a;


/* 새로운 테이블을 하나 만든다
 * 기 생성된 DB Retail아래에 mytable이란 테이블 생김
 * public -> Tables -> mytable이 생김
 */

create table mytable (
    name        varchar(80),
    pet         varchar(80)
);


insert into mytable values ('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt');


-- 테이블 만드는 또 다른 예제
CREATE TABLE CUSTOMER
(   CUSTOMER_ID VARCHAR(200)    PRIMARY KEY,
    DOB         DATE            NOT NULL,
    GENDER      VARCHAR(200),
    CITY_CODE   VARCHAR(200)
);


/* (3) Python 연결
 * Python 코드로 어떤 테이블에 데이터 추가
 * import psycopg2
 * conn = psycopg2.connect("host='localhost' dbname='Retail' user='postgres' password='0577' port=5432")
 * cur = conn.cursor()
 * cur.execute("INSERT INTO mytable (name, pet) values ('Kdj', 'tan');")
 * conn.commit()  # 데이터 추가됨
 */


select * from mytable;


 *  cur.execute("SELECT * from mytable;")
 *  rows = cur.fetchall()
 *  rows # 출력
 *  [('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt'), ('Kdj', 'tan')]
 */


-- 데이터 갱신
-- > cur.execute("update mytable set name='kdj' where pet='tan'")
-- > cur.execute("select * from mytable;")
-- > conn.commit()
-- > rows:
--   [('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt'), ('lee', 'tan')]


-- 데이터 삭제
-- > cur.execute("delete from mytable where name='lee'")
-- > cur.execute("select * from mytable;")
-- > rows = cur.fetchall()
-- > rows: [('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt')]


/* (4) SQL shell
 * >>> PostgreSQL13 -> SQL shell(psql) 실행 <<<
 * Table의 상위인 DATABASE의 조회, 생성, 삭제 가능
 * command #로 들어가서
 * \l or \l+  # 조회, 또는 상세 조회
 * CREATE DATABASE hello;  # DB생성
 * DROP DATABASE hello;  # DB제거
 * 이미 만들어진 Retail 확인 가능
 */


/* (5) 이미지 파일의 저장(BYTEA)
 * > 아래 파이썬 명령 참고
 */
 

-- > cur.execute("CREATE TABLE IF NOT EXISTS cartoon(cartoonID INTEGER, name TEXT, cartoonImg BYTEA)")
-- > conn.commit()
-- > cartoonID = 1
-- > name = "Casper"
-- > file_path = 'test.jpg'
-- > drawing = open(file_path, 'rb').read()
-- >
-- > cur.execute("INSERT INTO cartoon (cartoonID,name,cartoonImg) " + "VALUES(%s,%s,%s)", (cartoonID, name, psycopg2.Binary(drawing)))
-- > conn.commit()


-- image가 저장 되었는지 확인 가능
select *
from cartoon;