[Python]파이썬을 이용한 태양광 모니터링 시스템 자작기 마지막
- 사용기 | 블로그/모바일 | IT
- 2020. 12. 6. 22:38

파이썬을 이용한 태양광 모니터링 마지막
- 사용자 환경(UI) 만들기 -
지난번에 이어 태양광 발전 모니터링 프로그램 개발기 마지막편 입니다.
이런 뻘짓을 하실 분이 또 있을지 모르겠지만 혹시나 참고가 될까 해서 남겨봅니다.
1,2탄에서 만든 시리얼통신으로 인버터 데이터를 얻는 부분과 실시간 그래프표시하는 위젯을
메인윈도우에 탑재하고 데이터 저장 및 각종 설정 부분을 툴바로 만들었습니다.
이번편에서는 기존 대비 PYQTGRAPH 보조축생성하기, 범례만들기등을 추가하였습니다.
기존 내용은 아래 지난번 글을 참고 바랍니다.
[Python]파이썬을 이용한 태양광 모니터링 시스템 자작기 1탄 : fantasy297.tistory.com/640
[Python]파이썬을 이용한 태양광 모니터링 시스템 자작기 2탄 : fantasy297.tistory.com/641
1. 전체 UI 환경
메인윈도우 중앙에 그래프와 데이터 라벨을 배치하고 상단에 간단한 명령툴바를 추가하였습니다.
다른 모니터링 프로그램을 레이아웃을 참고하여 최대한 꾸며 보았습니다.
아이콘은 대부분 파워포인트 도형으로 그렸습니다.

▲ 동양ENP 인버터 모니터링 프로그램 최종 레이아웃
툴바에는 과거 날짜를 선택하면 과거 데이터를 불러오고, 현재데이터를 저장하는 부분과
모니터링을 시작/정지하고 그래프와 데이터를 삭제하는 부분
그래프 선두께, 선타입, 데이터 표시여부들을 설정할 수 있는 부분
Y축 범위를 설정하는 부분, 시리얼통관 관련 설정 부분
그리고 일별 데이터를 컬러맵과 3D 차트로 보여주는 부분으로 구성하였습니다.

▲ 동양ENP 인버터 모니터링 프로그램 툴바 설명

▲ 툴바에서 명령 실행시 나타나는 다이얼로그창 모습
2. 들어가면서
인터넷의 샘플 소스들을 참고하여 작성한 프로그램으로 제가 알아보기 쉽게 작성하는라 미흡한 점도 많고
코드가 매우 지저분 할 수 있습니다. 전체 코드를 설명하자니 복잡해질 것 같아
프로그램하면서 어려웠던 것 위주로 간단히 설명하겠습니다.
개념적인 설명이므로 상세한 내용은 전체 코드를 참고 바랍니다.
3. 메인윈도우에서 위젯 실행하기
메인윈도우에서 직접적으로 라벨이나 Pyqtgraph등을 배치하는 것은 불가능하므로 별도 Class를 추가하여
실행시켜 줍니다.
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# 그래프 위젯 호출 후 메인 윈도우에 생성
GraphWg = RS485Graph()
self.setCentralWidget(GraphWg)
class RS485Graph(QWidget):
.....
if __name__ == '__main__': # 직접 실행 여부 확인후 창 생성
import sys
if not QApplication.instance():
app = QApplication(sys.argv)
else:
app = QApplication.instance()
ex = MainWindow() # 실행
QApplication.setQuitOnLastWindowClosed(True)
app.exec_()
app.quit()
4. 툴바에 명령어 아이콘 생성하기
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# 툴바 액션 생성
SelectDateAction = QAction(QIcon('./icon/011_Calendar.png'), 'Select Date', self)
SelectDateAction.setStatusTip('Select a date to display monitoring data')
SelectDateAction.triggered.connect(GraphWg.SelectDateDialog)
...
# 툴바 생성
self.toolbar = self.addToolBar('Main_Tollbar')
self.toolbar.addAction(SelectDateAction)
...
5. 상태표시줄 생성하기 및 다른 Class에서 상태표시줄 호출하기
메인윈도우에서 생성한 상태표시줄에 다른 Class(여기서는 그래프를 그리는 위젯)에서 사용하기 위해
메인윈도우에 별도 함수를 지정하고 다른 메인윈도우에서 호출한 자식 클래스에서 부모(메인윈도우)의 함수를
호출하여 메인윈도우의 상태표시줄에 상태를 표시할 수 있습니다.
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
...
# 상태창 생성
self.statusBar().showMessage('Ready')
def set_status_message(self, message):
return self.statusBar().showMessage(message)
class RS485Graph(QWidget):
def __init__(self):
super().__init__()
...
def CreatFolderFile(self):
...
self.parent().set_status_message('Wrong Data Index')
6. PyqtGraph 보조축 사용하기
PyqtGraph의 레이아웃은 아래와 같습니다.
그래프가 그려지는 부분을 ViewBox라하고 이 ViewBox를 여러개 추가해주고 주 그래프와 링크를 맞춰주는 방식으로
보조축을 추가할 수 있습니다. 축아이템(Axisitem)은 여러개 추가할 수 있으며 오른쪽 첫번째는 'right'로 추가하고
그 이상의 축은 레이아웃 행렬 (예를 들어 오른쪽 2번째축은 (2, 3)형태로 추가할 수 있습니다.
메인뷰박스의 윈도우 크기가 변경되었을 경우 뷰박스 링크를 다시 맞춰줘야하므로 함수를 하나 만들고
Connect로 연결해 줍니다. (좀더 자사한 내용은 PyqtGraph 예제파일을 참고하시기 바랍니다.)

▲ PYQTGAPH 레이아웃
# Main Graph 보조축1(에너지 뷰박스) 설정
self.MainGraph_Energy = pyqtgraph.ViewBox()
self.MainGraph.plotItem.showAxis('right')
self.MainGraph.scene().addItem(self.MainGraph_Energy)
self.MainGraph.getAxis('right').linkToView(self.MainGraph_Energy)
self.MainGraph_Energy.setXLink(self.MainGraph)
self.MainGraph.getAxis('right').setPen(pyqtgraph.mkPen(color=(114, 166, 3), width=1))
# Main Graph 보조축2(온도 뷰박스) 설정
self.MainGraph_Temp = pyqtgraph.ViewBox()
self.tempAxis = pyqtgraph.AxisItem('right')
self.MainGraph.plotItem.layout.addItem(self.tempAxis, 2, 3)
self.MainGraph.scene().addItem(self.MainGraph_Temp)
self.tempAxis.linkToView(self.MainGraph_Temp)
self.MainGraph_Temp.setXLink(self.MainGraph)
self.tempAxis.setZValue(-1000)
self.tempAxis.setPen(pyqtgraph.mkPen(color=(242, 145, 27), width=1))
# Main Graph 뷰박스 업데이트
self.UpdateMainVB()
self.MainGraph.getViewBox().sigResized.connect(self.UpdateMainVB)
def UpdateMainVB(self):
self.MainGraph_Energy.setGeometry(self.MainGraph.getViewBox().sceneBoundingRect())
self.MainGraph_Temp.setGeometry(self.MainGraph.getViewBox().sceneBoundingRect())
self.MainGraph_Energy.linkedViewChanged(self.MainGraph.getViewBox(), self.MainGraph_Energy.XAxis)
self.MainGraph_Temp.linkedViewChanged(self.MainGraph.getViewBox(), self.MainGraph_Temp.XAxis)
7. 하루전, 한달전 날짜 계산하기
datautil의 relativedelta를 사용하여 이전 날짜를 계산할 수 있습니다.
from dateutil.relativedelta import relativedelta
def getDayList(self,day):
NowDay = datetime.datetime.now().strftime('%m/%d')
Daylist = [NowDay]
# 이전 24일 리스트 생성
for i in range(1,day):
Temp = datetime.datetime.now()-datetime.timedelta(days=i)
LastDay = Temp.strftime('%Y/%m-%d')
Daylist.append(LastDay)
return Daylist
def getMonthList(self,month):
# 이전 12개월 리스트 생성
NowMonth = datetime.datetime.now().strftime('%Y/%b')
Monthlist = [NowMonth]
for i in range(1,month):
Temp = datetime.datetime.now()-relativedelta(months=i)
LastMonth = Temp.strftime('%Y/%b')
Monthlist.append(LastMonth)
return Monthlist
8. 그래프 범례추가하기 및 범례 글꼴 설정
기본적으로 PYQTGRAPH의 범례는 메인뷰박스의 그래프만 나옵니다.
그래서 보조축에 들어간 그래프범례를 위해 메인뷰박스에 동일한 Curve를 추가해 주었습니다.
self.Effi_Legend = self.VAGraph.plot(pen=pyqtgraph.mkPen(color=(114, 166, 3), ....) # 범례용 커브
self.Effi_curve = pyqtgraph.PlotCurveItem(pen=pyqtgraph.mkPen(color=(114, 166, ....) # 실제 커브
self.VAGraph_Effi.addItem(self.Effi_curve)
# 범례 추가 및 글꼴 설정
font = QtGui.QFont('Bahnschrift SemiLight', 9)
LegMain = self.MainGraph.addLegend(offset=(10,10))
LegMain.setPen(pyqtgraph.functions.mkPen(180,180,180))
LegMain.setBrush(pyqtgraph.functions.mkBrush(245,245,245))
for item in LegMain.items:
for single_item in item:
if isinstance(single_item, pyqtgraph.graphicsItems.LabelItem.LabelItem):
single_item.item.setFont(font)
else:
pass
9. 툴바 명령 실행시 별도 창 생성하기
메인 윈도우에서 위젯을 실행하고 위젯 아래 다시 자식 클래스를 생성하여 창을 실행합니다.
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# 그래프 위젯 호출 후 메인 윈도우에 생성
GraphWg = RS485Graph()
self.setCentralWidget(GraphWg)
# 툴바 액션 생성
HeatMapAction = QAction(QIcon('./icon/045_Heatmap.png'), 'HeatMap Chart', self)
HeatMapAction.setStatusTip('Creat Daily Gen. Energy and Run Time Heat Map')
HeatMapAction.triggered.connect(GraphWg.CreateHeatMap)
....
self.toolbar.addAction(HeatMapAction)
....
class RS485Graph(QWidget):
def __init__(self):
super().__init__()
...
def CreateHeatMap(self):
Hetmapdlg = HeatMapGraph()
Hetmapdlg.exec_()
...
class HeatMapGraph(QDialog):
def __init__(self):
super().__init__()
...
10. 마치면서
이상으로 동양EnP 태양광 인버터에서 데이터를 취득하여 자동 저장하고 저장된 데이터를 그래프로
보여 주는 윈도우 프로그램을 제작해 보았습니다.
최종 프로그램 원본은 아래에서 다운 받으실 수 있습니다.
약 2달간 프로그램을 실행시켜보며 문제 있는 부분은 수정하였으나 오류가 있을 수 있습니다.
알려주시면 가능한한 최대한 수정해 보도록하겠습니다.
▲ 동양E&P 인버터 모니터링 프로그램 v1.19
각 시스템에 맞게 COM Port/ 인버터 ID등은
설정창에서 수정하여 사용하시기 바랍니다.


※ 글과 파이썬 코드의 저작권은 본인에게 있으며, 상업적용도의 사용을 금지합니다.
코딩에 대한 조언 이나, 개선할 점 등을 댓글로 남겨 주시면 감사하겠습니다.
'사용기 | 블로그 > 모바일 | IT' 카테고리의 다른 글
[Python]파이썬을 이용한 태양광 모니터링 시스템 자작기 2탄 (13) | 2020.09.09 |
---|---|
[Python]파이썬을 이용한 태양광 모니터링 시스템 자작기 1탄 (6) | 2020.08.29 |
화웨이 아너8 (HUAWEI HONOR 8) 오레오 업데이트 방법 및 바뀐점 (0) | 2018.07.29 |
화웨이 아너8 (HUAWEI HONOR 8) 한달 사용기 : 카톡 알림 설정등 (2) | 2017.10.19 |
LG 노트북 액전 자가 수리 하기. (0) | 2017.10.17 |
이 글을 공유하기