이번 글에서는 Flask를 이용한 REST API 서버와 PLC 및 Redis와의 통합을 다루는 두 개의 코드 스니펫을 분석해 보겠다. 첫 번째 코드 스니펫은 Flask를 사용하여 EIP(Engineering Protocol) 관련 태그를 관리하는 REST API 서버를 설정하고, 두 번째 코드 스니펫은 PLC와 Redis를 이용하여 태그 데이터를 읽고 쓰는 기능을 구현한다.
1. Flask REST API 서버 코드
Flask와 Flask-RESTx 설정:
from flask import Flask, request
from flask_restx import Api, Resource, fields
from taglist import process_tags, start_read, stop_read, write_data, stop_tag
app = Flask(__name__)
api = Api(app, version='1.0', title='EIP Tag')
API 네임스페이스와 모델 정의:
ns = api.namespace('api/eip', description='EIP operations')
memory_map_model = api.model('MemoryMap', {
'type': fields.String(description='Memory type'),
'address': fields.Integer(description='Address'),
'dataType': fields.String(description='Data type'),
'rwType': fields.String(description='Read/Write type'),
'tagArraySize': fields.Integer(description='Tag array size'),
'tagArray': fields.List(fields.String, description='Tag array')
})
tag_model = api.model('Tag', {
'type': fields.String(description='Type'),
'id': fields.String(description='Unique ID'),
'name': fields.String(description='Alias name'),
'memoryMap': fields.List(fields.Nested(memory_map_model), description='Memory map')
})
write_data_model = api.model('WriteData', {
'tags': fields.List(fields.Nested(api.model('WriteTag', {
'tag': fields.String(required=True, description='Tag to write'),
'value': fields.String(required=True, description='Value to write')
})))
})
API 엔드포인트 정의:
@ns.route('/state')
class EIPState(Resource):
@ns.doc(description='Get the current state of the Python EIP server')
def get(self):
return {'state': 'running'}, 200
@ns.route('/tag')
class Tag(Resource):
@ns.doc(description='Register tags from the provided JSON')
@ns.expect(tag_model)
def post(self):
data = request.json
global tag_name_dict
tag_name_dict = process_tags(data) # process_tags 함수를 호출하여 tag_name_dict 생성
return {'results': list(tag_name_dict.keys())}, 201
@ns.doc(description='Stop reading specified tags')
def delete(self):
global tag_name_dict
if not tag_name_dict:
return {'message': 'No tags to stop'}, 400
tag_list = list(tag_name_dict.keys()) # 모든 등록된 태그 이름들의 리스트
results = stop_tag(tag_list)
tag_name_dict.clear()
return {'results': results}, 200
@ns.route('/read')
class Read(Resource):
@ns.doc(description='Start reading all registered tags')
def post(self):
global tag_name_dict
if not tag_name_dict:
return {'message': 'No tags to read'}, 400
tag_list = list(tag_name_dict.keys()) # 모든 등록된 태그 이름들의 리스트
results = start_read(tag_list)
return {'results': results}, 201
@ns.doc(description='Stop redis server')
def delete(self):
# Stop reading tags
stop_read()
return {'message': 'Stopped reading'}, 200
@ns.route('/write')
class Write(Resource):
@ns.doc(description='Write data to tags')
@ns.expect(write_data_model)
def post(self):
data = request.json
if not data or not data.get('tags'):
return {'message': 'No data to write'}, 400
result = write_data(data)
return {'result': result}, 201
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
핵심 기능
EIPState 클래스는 EIP 서버의 상태를 조회하는 엔드포인트를 제공한다.
Tag 클래스는 태그를 등록하고, 읽기 작업을 중지할 수 있는 엔드포인트를 제공한다.
Read 클래스는 등록된 태그의 읽기를 시작하고 중지하는 기능을 제공한다.
Write 클래스는 태그에 데이터를 쓰는 기능을 제공한다.