commit 0bd7c5a26aaa0362b8610743280df32e510e1c8c Author: esea_info Date: Tue Apr 11 14:18:14 2023 +0800 first commit diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f7c5140 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,91 @@ +{ + // 控制字体大小(像素) + "editor.fontSize": 16, + // 在 #editor.wordWrap# 为 wordWrapColumn 或 bounded 时,控制编辑器的折行列。100 列后换行 + "editor.wordWrapColumn": 100, + // 控制tab键是空格还是制表符 true 空格 false制表符 + "editor.detectIndentation": false, + // tab 对应空格大小 + "editor.tabSize": 4, + // 在保存时格式化文件。 + "editor.formatOnSave": false, + // 开启 vscode 文件路径导航 + "breadcrumbs.enabled": true, + // prettier 是否在每行末尾添加分号 ,C_cpp有用 + "prettier.semi": false, + // prettier 设置强制单引号 + "prettier.singleQuote": true, + // 尽可能控制尾随逗号的输出。 有效选项: 'none' - 无尾随逗号 ' es5' - 在ES5中有效的尾随逗号(对象,数组等) 'all' - 尾随逗号 尽可能(函数参数) + "prettier.trailingComma": "none", + // 定义函数参数括号前的空格处理方式。 + "javascript.format.insertSpaceBeforeFunctionParenthesis": true, + // 鼠标滚轮缩放, ctrl+滚轮 + "editor.mouseWheelZoom": true, + "editor.defaultFormatter": "ms-python.vscode-pylance", + "files.encoding":"utf8", + + // 针对python文件将 tab改为4个空格 + "[python]": { + "editor.insertSpaces": true, + "editor.tabSize": 4 + }, + + + + // 代码格式化 astyle,需要安装astyle 程序-适用C c++ java + // "astyle.executable": "D:\\AStyle\\bin\\astyle.exe", //window + // "astyle.executable": "/usr/bin/astyle", // linux + // "astyle.additional_languages": [ + // "c", + // "cpp", + // "*.h", + // ], + // "astyle.cmd_options": [ + // // 预定义风格 ----------------------------------------------------------- + // // "--style=ansi", //ANSI 风格格式和缩进 + // // "--style=kr", //Kernighan&Ritchie 风格格式和缩进 + // "--style=linux", //Linux 风格格式和缩进 + // //"--style=gnu", //GNU 风格格式和缩进 + // // "--style=java", //Java 风格格式和缩进 + // "--indent=spaces=4", //缩进4个空格 + // "--indent-preproc-block", + // "--pad-oper", //操作符两端插入一个空格 + // "--pad-header", + // "--unpad-paren", + // "--suffix=none", + // "--align-pointer=name", + // "--lineend=linux", + // "--convert-tabs", //TAB转换为空格 + // "--verbose", + // // "--delete-empty-lines", //删除多余空行 + // //"--pad-paren-in", //括号内部加入空格 + // "--unpad-paren", //移除括号两端多余空格 + // ], + + // pylint --python风格 pylint程序 + // "python.linting.enabled": true, + // "python.linting.pylintEnabled": true, + // "python.linting.lintOnSave": true, + // "python.linting.pylintPath": "D:\\pylint\\bin\\pylint.exe", + // "python.linting.pylintArgs": [ + // "--rcfile={path}/.pylintrc", + // "--extension-pkg-whitelist=PyQt5", + // "--disable=invalid-name,missing-module-docstring", + // "--disable=W0612,W0631,W0703,W0621,W0613,W0611,W1308,C0411,C0111,C0103,C0301,C0304,C0305,E1101,R0913,R0914,R0915,R0903" , + // ], + + + // 执行的终端选择,可选 + "terminal.integrated.defaultProfile.windows" : "PowerShell", + // "terminal.integrated.defaultProfile.windows" : "Git Bash", + // "terminal.integrated.defaultProfile.windows" : "Windows PowerShell", + // "terminal.integrated.defaultProfile.windows": "Ubuntu-20.04 (WSL)", + + "python.defaultInterpreterPath": "python3", // python3 或 python + "code-runner.executorMap": { + "python":"python3 -u $fullFileName" + }, + + + +} \ No newline at end of file diff --git a/__pycache__/configuration.cpython-38.pyc b/__pycache__/configuration.cpython-38.pyc new file mode 100644 index 0000000..a957762 Binary files /dev/null and b/__pycache__/configuration.cpython-38.pyc differ diff --git a/__pycache__/dataplot.cpython-38.pyc b/__pycache__/dataplot.cpython-38.pyc new file mode 100644 index 0000000..a74ae35 Binary files /dev/null and b/__pycache__/dataplot.cpython-38.pyc differ diff --git a/__pycache__/listctrl.cpython-38.pyc b/__pycache__/listctrl.cpython-38.pyc new file mode 100644 index 0000000..2548a6b Binary files /dev/null and b/__pycache__/listctrl.cpython-38.pyc differ diff --git a/__pycache__/myconfig.cpython-38.pyc b/__pycache__/myconfig.cpython-38.pyc new file mode 100644 index 0000000..db86d7a Binary files /dev/null and b/__pycache__/myconfig.cpython-38.pyc differ diff --git a/__pycache__/myexception.cpython-38.pyc b/__pycache__/myexception.cpython-38.pyc new file mode 100644 index 0000000..a5fb9d9 Binary files /dev/null and b/__pycache__/myexception.cpython-38.pyc differ diff --git a/__pycache__/mylogger.cpython-38.pyc b/__pycache__/mylogger.cpython-38.pyc new file mode 100644 index 0000000..b9969b7 Binary files /dev/null and b/__pycache__/mylogger.cpython-38.pyc differ diff --git a/__pycache__/mypanel.cpython-38.pyc b/__pycache__/mypanel.cpython-38.pyc new file mode 100644 index 0000000..3927029 Binary files /dev/null and b/__pycache__/mypanel.cpython-38.pyc differ diff --git a/__pycache__/mypath.cpython-38.pyc b/__pycache__/mypath.cpython-38.pyc new file mode 100644 index 0000000..4ab8db1 Binary files /dev/null and b/__pycache__/mypath.cpython-38.pyc differ diff --git a/__pycache__/mythread.cpython-38.pyc b/__pycache__/mythread.cpython-38.pyc new file mode 100644 index 0000000..71c6963 Binary files /dev/null and b/__pycache__/mythread.cpython-38.pyc differ diff --git a/__pycache__/readcal.cpython-38.pyc b/__pycache__/readcal.cpython-38.pyc new file mode 100644 index 0000000..2885d76 Binary files /dev/null and b/__pycache__/readcal.cpython-38.pyc differ diff --git a/__pycache__/uart.cpython-38.pyc b/__pycache__/uart.cpython-38.pyc new file mode 100644 index 0000000..0d082a3 Binary files /dev/null and b/__pycache__/uart.cpython-38.pyc differ diff --git a/__pycache__/viper.cpython-38.pyc b/__pycache__/viper.cpython-38.pyc new file mode 100644 index 0000000..0ce347e Binary files /dev/null and b/__pycache__/viper.cpython-38.pyc differ diff --git a/__pycache__/yiwinframe.cpython-38.pyc b/__pycache__/yiwinframe.cpython-38.pyc new file mode 100644 index 0000000..1aad270 Binary files /dev/null and b/__pycache__/yiwinframe.cpython-38.pyc differ diff --git a/app.py b/app.py new file mode 100644 index 0000000..0e3919d --- /dev/null +++ b/app.py @@ -0,0 +1,33 @@ +#! python3 +# -*- encoding: utf-8 -*- +''' +@File : app.py +@Time : 2021/09/12 12:38:46 +@Author : Jim +@Version : 1.0 +@Desp : +''' + +# VERSION = "3.3.2" +# LASTDATE = "2021-09-20" + +import wx +from yiwinframe import YiwinFrame +from mylogger import log + +from myconfig import VERSION,LASTDATE,COMPANY + +class YiwinApp(wx.App): + + def OnInit(self): + self.myframe = YiwinFrame( u'奕枫水体吸收系数测量软件 v1.0', parent=None) + self.myframe.statusBar.SetStatusText( u" 版权所有 " + COMPANY + +" Version "+ VERSION + " "+ LASTDATE, 1 ) #给状态栏设文字 + self.myframe.Show(True) + return True + +if __name__ == "__main__": + log.info(f"******** Shanghai Yiwin Instrument@Equipment Company *********", __name__, "", "") + log.info(f"******** Viper attenuation Software .... *********", __name__, "", "") + app = YiwinApp( ) + app.MainLoop() diff --git a/calfile/attenuation_pure_water.DAT b/calfile/attenuation_pure_water.DAT new file mode 100644 index 0000000..9b1e97d --- /dev/null +++ b/calfile/attenuation_pure_water.DAT @@ -0,0 +1,131 @@ +[Spectrum] +Version = 1 +IDData = VIPER_A05D_2021-07-09_12-19-30_Absorption_505 +IDDevice = VIPER_A05D +IDDataType = SPECTRUM +IDDataTypeSub1 = attenuation coefficient of pure water +IDDataTypeSub2 = SAMPLE +IDDataTypeSub3 = +DateTime = 2021-07-09 12:19:30 +PositionLatitude = 0 +PositionLongitude = 0 +Comment = +CommentSub1 = +CommentSub2 = +CommentSub3 = +IDMethodType = +MethodName = +Mission = 1 ; 54.1849 ; ; +MissionSub = 0 +RecordType = 0 +[Attributes] +Averaging = 1 +CalFactor = 39.6348 +Deviation = 54.1849 +FlashCount = 1 +IDBasisSpec = 1607002963 +IDDataBack = +IDDataCal = +IntegrationTime = 512 +Maximum = 1.06247 +P31 = 0 +P31e = 0 +PathLength = 150 +PathLengthCustomOn = 0 +RAWDynamic = 65535 +SQIBase = 0.02 +Salinity = 0 +SpectrumType = Absorption +Temperature = 29.8437 +Unit1 = $01 $01 Wavelength nm +Unit2 = $09 $08 Absorption 1 +Unit3 = $09 $08 Absorption 1 +Unit4 = $f1 $00 Status +lampLEDs = 255 +lampReference = 20293 +p999 = 0 +tempLampModule = 29.8437 +tempLampPower = 29.875 +tempMainCPU = 34.0625 +tempSpectrometer = 32.75 +[END] of [Attributes] +[DATA] + 0 8 0 0 +360 0.0158 0.0007 0 +365 0.0149 0.0007 0 +370 0.0142 0.0007 0 +375 0.0133 0.0007 1 +380 0.0125 0.0007 0 +385 0.0119 0.0007 0 +390 0.0114 0.0007 0 +395 0.0108 0.0007 0 +400 0.0104 0.0007 0 +405 0.0101 0.0007 0 +410 0.0098 0.0007 0 +415 0.0096 0.0006 0 +420 0.00924 0.0006 14 +425 0.00928 0.0006 13 +430 0.00925 0.0006 14 +435 0.0094 0.0006 13 +440 0.01025 0.0006 12 +445 0.01121 0.0005 11 +450 0.01272 0.0005 11 +455 0.01292 0.0005 10 +460 0.01299 0.0005 9 +465 0.01311 0.0005 9 +470 0.0135 0.0006 8 +475 0.0142 0.0005 7 +480 0.0154 0.0005 6 +485 0.0161 0.0004 6 +490 0.0174 0.0004 5 +495 0.0196 0.0004 5 +500 0.0226 0.0005 6 +505 0.0277 0.0005 6 +510 0.0345 0.0006 7 +515 0.0416 0.0006 6 +520 0.0428 0.0005 6 +525 0.0435 0.0008 8 +530 0.0451 0.0007 7 +535 0.0469 0.0008 8 +540 0.049 0.0008 7 +545 0.0526 0.0008 7 +550 0.058 0.0007 6 +555 0.061 0.0007 6 +560 0.0632 0.0007 5 +565 0.0655 0.0014 9 +570 0.0708 0.001 6 +575 0.0784 0.0014 8 +580 0.0908 0.0011 6 +585 0.1111 0.0012 6 +590 0.1362 0.0013 6 +595 0.1682 0.001 5 +600 0.2234 0.0011 4 +605 0.2587 0.0012 4 +610 0.2653 0.0012 4 +615 0.2687 0.0015 5 +620 0.2764 0.0009 3 +625 0.2842 0.0014 4 +630 0.2924 0.001 4 +635 0.302 0.0017 5 +640 0.3116 0.0011 4 +645 0.3257 0.0017 5 +650 0.3407 0.0012 4 +655 0.3717 0.0015 4 +660 0.4107 0.001 3 +665 0.4296 0.0016 4 +670 0.4396 0.0011 3 +675 0.4486 0.0016 4 +680 0.4656 0.0011 3 +685 0.4866 0.0012 3 +690 0.5166 0.0012 3 +695 0.5595 0.0014 4 +700 0.6245 0.001 3 +705 0.7045 0.0015 4 +710 0.8275 0.0009 3 +715 1.0075 0.0014 3 +720 1.2315 0.0011 3 +725 1.4894 0.0011 3 +[END] of [DATA] +[END] of Spectrum + + diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..a648145 --- /dev/null +++ b/config.yml @@ -0,0 +1,27 @@ +algorithm: + 'A720': 0 + 'PureWater': 0 + 'PureWater2': 0 +comsetting: + baudrate: 9600 + bytesize: 8 + parity: N + port: COM1 + stopbit: 1 +device: + UIPath: 150 + UISN: A05D +logsetting: + LogInterval: 1 + RefreshInterval: 0 +plotsetting: + LineBegin: 0 + LineInterval: 1 +register: + DataBeginAddress: 2614 + SNAddress: 2980 + SNLen: 5 + WLBeginAddress: 2102 + count: 3 + functioncode: 3 + slaveaddress: 1 diff --git a/configuration.py b/configuration.py new file mode 100644 index 0000000..fe19a58 --- /dev/null +++ b/configuration.py @@ -0,0 +1,32 @@ +from pathlib import Path, PurePath + +from mylogger import log +from readcal import ReadCal + +from myconfig import CAL_DIR, DATA_DIR, FILE_MARK, DeviceType + + +class Configuration: + def __init__(self, ) -> None: + log.info(f"Viper Configure init: ", __name__, "", "") + self.device_type = None + self.configuration =None + pass + + def setSystemCfgDict(self, cfg:dict) -> None: + self.configuration = cfg + log.info(f"self.configuration : {self.configuration} ", __name__, "", "") + pass + + def get_wl_from_datafile(self, fpath) -> None: + # self.cfgtool = Config() + if fpath.exists( ): + res = ReadCal.read_columns_set_by_mark( fpath, FILE_MARK, 1 ) + self.configuration.update({ "wavelength" : res[1][0] }) + pass + + def getCalConfiguration(self) -> None: + pass + + + diff --git a/data/20210305/ABSORPTI.DAT b/data/20210305/ABSORPTI.DAT new file mode 100644 index 0000000..c5c6f03 --- /dev/null +++ b/data/20210305/ABSORPTI.DAT @@ -0,0 +1,892 @@ +[Spectrum] +Version = 1 +IDData = VIPER_A05D_2011-01-28_00-00-32_Absorption_956 +IDDevice = VIPER_A05D +DateTime = 2011-01-28 00:00:32 +Comment = +CommentSub1 = +CommentSub2 = +CommentSub3 = +IDDataType = SPECTRUM +IDDataTypeSub1 = ABSORPTION +IDDataTypeSub2 = SAMPLE +Mission = 1 ; 12.1014 ; ; +[Attributes] +SpectrumType = Absorption +Averaging = 1 +CalFactor = 323.875 +FlashCount = 1 +IntegrationTime = 64 +PathLength = 150 +Temperature = 21.7187 +lampReference = 20728 +lampLEDs = 255 +tempLampModule = 21.7187 +tempLampPower = 21.8125 +tempSpectrometer = 27.875 +tempMainCPU = 29.375 +Deviation = 12.1014 +Maximum = 0.127814 +IDBasisSpec = 1607002963 +SQIBase = 0.02 +RAWDynamic = 65535 +Unit1 = $01 $01 Wavelength nm +Unit2 = $09 $08 Absorption 1 +Unit3 = $09 $08 Absorption 1 +Unit4 = $f1 $00 Status +[END] of [Attributes] +[DATA] +0 5 0 0 +348.449 0.127814 0 0 +350.582 0.11374 0 0 +352.714 0.112956 0 0 +354.846 0.112141 0 0 +356.978 0.113478 0 0 +359.109 0.113652 0 0 +361.239 0.112536 0 0 +363.37 0.112693 0 0 +365.499 0.113707 0 0 +367.629 0.114538 0 0 +369.757 0.114091 0 0 +371.886 0.113129 0 0 +374.014 0.112497 0 0 +376.141 0.112543 0 0 +378.268 0.113452 0 0 +380.394 0.113834 0 0 +382.52 0.113713 0 0 +384.646 0.113458 0 0 +386.771 0.113924 0 0 +388.895 0.115218 0 0 +391.019 0.116083 0 0 +393.142 0.116546 0 0 +395.265 0.115786 0 0 +397.388 0.115939 0 0 +399.509 0.115761 0 0 +401.631 0.1153 0 0 +403.751 0.115491 0 0 +405.872 0.115647 0 0 +407.991 0.115151 0 0 +410.11 0.115626 0 0 +412.229 0.116548 0 0 +414.347 0.118101 0 0 +416.465 0.118035 0 0 +418.582 0.116925 0 0 +420.698 0.115402 0 0 +422.814 0.113735 0 0 +424.929 0.113218 0 0 +427.044 0.114775 0 0 +429.158 0.116581 0 0 +431.271 0.117034 0 0 +433.384 0.117575 0 0 +435.497 0.11764 0 0 +437.608 0.118782 0 0 +439.72 0.119549 0 0 +441.83 0.121309 0 0 +443.94 0.122246 0 0 +446.049 0.122688 0 0 +448.158 0.12367 0 0 +450.266 0.12358 0 0 +452.374 0.123454 0 0 +454.481 0.122483 0 0 +456.587 0.121352 0 0 +458.693 0.120174 0 0 +460.798 0.118698 0 0 +462.902 0.116801 0 0 +465.006 0.115501 0 0 +467.109 0.114403 0 0 +469.211 0.113701 0 0 +471.313 0.113681 0 0 +473.414 0.113321 0 0 +475.514 0.112773 0 0 +477.614 0.113746 0 0 +479.713 0.113536 0 0 +481.812 0.116502 0 0 +483.909 0.116058 0 0 +486.007 0.116526 0 0 +488.103 0.114908 0 0 +490.199 0.116429 0 0 +492.294 0.114168 0 0 +494.388 0.115586 0 0 +496.482 0.114446 0 0 +498.575 0.113854 0 0 +500.667 0.112686 0 0 +502.758 0.11393 0 0 +504.849 0.112698 0 0 +506.939 0.111642 0 0 +509.028 0.111282 0 0 +511.117 0.111762 0 0 +513.205 0.11071 0 0 +515.292 0.111922 0 0 +517.378 0.113175 0 0 +519.464 0.112928 0 0 +521.549 0.112811 0 0 +523.633 0.113126 0 0 +525.717 0.113392 0 0 +527.799 0.113505 0 0 +529.881 0.113887 0 0 +531.962 0.113784 0 0 +534.043 0.114851 0 0 +536.122 0.113209 0 0 +538.201 0.113538 0 0 +540.279 0.113283 0 0 +542.356 0.113044 0 0 +544.433 0.112063 0 0 +546.508 0.111686 0 0 +548.583 0.111008 0 0 +550.658 0.110703 0 0 +552.731 0.110154 0 0 +554.803 0.109367 0 0 +556.875 0.109456 0 0 +558.946 0.109302 0 0 +561.016 0.108354 0 0 +563.085 0.108635 0 0 +565.153 0.108339 0 0 +567.221 0.108883 0 0 +569.288 0.109004 0 0 +571.353 0.109164 0 0 +573.419 0.108922 0 0 +575.483 0.108629 0 0 +577.546 0.108983 0 0 +579.609 0.109142 0 0 +581.67 0.108994 0 0 +583.731 0.108436 0 0 +585.791 0.108665 0 0 +587.85 0.107621 0 0 +589.908 0.107676 0 0 +591.965 0.106535 0 0 +594.022 0.105538 0 0 +596.077 0.103036 0 0 +598.132 0.101463 0 0 +600.186 0.100313 0 0 +602.238 0.0984701 0 0 +604.29 0.0978697 0 0 +606.341 0.0968281 0 0 +608.392 0.0973058 0 0 +610.441 0.0968114 0 0 +612.489 0.0944351 0 0 +614.537 0.0942494 0 0 +616.583 0.0941368 0 0 +618.629 0.0945533 0 0 +620.673 0.0931584 0 0 +622.717 0.0916116 0 0 +624.76 0.0916241 0 0 +626.801 0.0926359 0 0 +628.842 0.0909737 0 0 +630.882 0.0903093 0 0 +632.921 0.0891894 0 0 +634.959 0.0906699 0 0 +636.996 0.0912185 0 0 +639.032 0.0906486 0 0 +641.067 0.0902244 0 0 +643.102 0.0899626 0 0 +645.135 0.0900885 0 0 +647.167 0.0920863 0 0 +649.198 0.0905681 0 0 +651.228 0.090085 0 0 +653.258 0.0889907 0 0 +655.286 0.0890961 0 0 +657.313 0.0885218 0 0 +659.339 0.0879637 0 0 +661.364 0.0879287 0 0 +663.389 0.0864832 0 0 +665.412 0.0867878 0 0 +667.434 0.0864328 0 0 +669.455 0.0912282 0 0 +671.475 0.0889504 0 0 +673.494 0.0877137 0 0 +675.513 0.0872359 0 0 +677.53 0.0904399 0 0 +679.546 0.0894157 0 0 +681.561 0.0864097 0 0 +683.574 0.0874475 0 0 +685.587 0.0876873 0 0 +687.599 0.0856188 0 0 +689.61 0.0818516 0 0 +691.619 0.078733 0 0 +693.628 0.0829921 0 0 +695.636 0.0773868 0 0 +697.642 0.0758 0 0 +699.647 0.0795865 0 0 +701.652 0.0750983 0 0 +703.655 0.0713695 0 0 +705.657 0.0708702 0 0 +707.658 0.0715209 0 0 +709.658 0.0678586 0 0 +711.657 0.0620032 0 0 +713.655 0.0536908 0 0 +715.651 0.0621843 0 0 +717.647 0.0471298 0 0 +719.641 0.0310415 0 0 +721.634 0.0411625 0 0 +[END] of [DATA] +[END] of [Spectrum] + +[Spectrum] +Version = 1 +IDData = VIPER_A05D_2011-01-28_00-01-04_Absorption_160 +IDDevice = VIPER_A05D +DateTime = 2011-01-28 00:01:04 +Comment = +CommentSub1 = +CommentSub2 = +CommentSub3 = +IDDataType = SPECTRUM +IDDataTypeSub1 = ABSORPTION +IDDataTypeSub2 = SAMPLE +Mission = 1 ; 13.5109 ; ; +[Attributes] +SpectrumType = Absorption +Averaging = 1 +CalFactor = 323.812 +FlashCount = 1 +IntegrationTime = 64 +PathLength = 150 +Temperature = 21.7812 +lampReference = 20724 +lampLEDs = 255 +tempLampModule = 21.7812 +tempLampPower = 21.8437 +tempSpectrometer = 27.9375 +tempMainCPU = 29.3125 +Deviation = 13.5109 +Maximum = 0.123204 +IDBasisSpec = 1607002963 +SQIBase = 0.02 +RAWDynamic = 65535 +Unit1 = $01 $01 Wavelength nm +Unit2 = $09 $08 Absorption 1 +Unit3 = $09 $08 Absorption 1 +Unit4 = $f1 $00 Status +[END] of [Attributes] +[DATA] +0 5 0 0 +348.449 0.108085 0 0 +350.582 0.10192 0 0 +352.714 0.10706 0 0 +354.846 0.109759 0 0 +356.978 0.111303 0 0 +359.109 0.113366 0 0 +361.239 0.112528 0 0 +363.37 0.112052 0 0 +365.499 0.113259 0 0 +367.629 0.114201 0 0 +369.757 0.113857 0 0 +371.886 0.112792 0 0 +374.014 0.112201 0 0 +376.141 0.112261 0 0 +378.268 0.113023 0 0 +380.394 0.113304 0 0 +382.52 0.113249 0 0 +384.646 0.112358 0 0 +386.771 0.113042 0 0 +388.895 0.113877 0 0 +391.019 0.114588 0 0 +393.142 0.115162 0 0 +395.265 0.114966 0 0 +397.388 0.115377 0 0 +399.509 0.115393 0 0 +401.631 0.114693 0 0 +403.751 0.115193 0 0 +405.872 0.115299 0 0 +407.991 0.114797 0 0 +410.11 0.115215 0 0 +412.229 0.116395 0 0 +414.347 0.117736 0 0 +416.465 0.117751 0 0 +418.582 0.116494 0 0 +420.698 0.115208 0 0 +422.814 0.113344 0 0 +424.929 0.112895 0 0 +427.044 0.11412 0 0 +429.158 0.116002 0 0 +431.271 0.116312 0 0 +433.384 0.116362 0 0 +435.497 0.116765 0 0 +437.608 0.117822 0 0 +439.72 0.118828 0 0 +441.83 0.12058 0 0 +443.94 0.121688 0 0 +446.049 0.122383 0 0 +448.158 0.123141 0 0 +450.266 0.123204 0 0 +452.374 0.122973 0 0 +454.481 0.121994 0 0 +456.587 0.120883 0 0 +458.693 0.119155 0 0 +460.798 0.118027 0 0 +462.902 0.11581 0 0 +465.006 0.114698 0 0 +467.109 0.113399 0 0 +469.211 0.111818 0 0 +471.313 0.111491 0 0 +473.414 0.112154 0 0 +475.514 0.111309 0 0 +477.614 0.1114 0 0 +479.713 0.111655 0 0 +481.812 0.113382 0 0 +483.909 0.113187 0 0 +486.007 0.114004 0 0 +488.103 0.114976 0 0 +490.199 0.114088 0 0 +492.294 0.112901 0 0 +494.388 0.112421 0 0 +496.482 0.111632 0 0 +498.575 0.112724 0 0 +500.667 0.109042 0 0 +502.758 0.112645 0 0 +504.849 0.109365 0 0 +506.939 0.108869 0 0 +509.028 0.109577 0 0 +511.117 0.110742 0 0 +513.205 0.109466 0 0 +515.292 0.110859 0 0 +517.378 0.111149 0 0 +519.464 0.111518 0 0 +521.549 0.11156 0 0 +523.633 0.112085 0 0 +525.717 0.112538 0 0 +527.799 0.11314 0 0 +529.881 0.112739 0 0 +531.962 0.112797 0 0 +534.043 0.114011 0 0 +536.122 0.112618 0 0 +538.201 0.112746 0 0 +540.279 0.112775 0 0 +542.356 0.112288 0 0 +544.433 0.111321 0 0 +546.508 0.110755 0 0 +548.583 0.110041 0 0 +550.658 0.109749 0 0 +552.731 0.1095 0 0 +554.803 0.109152 0 0 +556.875 0.109147 0 0 +558.946 0.108567 0 0 +561.016 0.107955 0 0 +563.085 0.108047 0 0 +565.153 0.107941 0 0 +567.221 0.108294 0 0 +569.288 0.108127 0 0 +571.353 0.108807 0 0 +573.419 0.108418 0 0 +575.483 0.10778 0 0 +577.546 0.108123 0 0 +579.609 0.10827 0 0 +581.67 0.108208 0 0 +583.731 0.107326 0 0 +585.791 0.107585 0 0 +587.85 0.106841 0 0 +589.908 0.106934 0 0 +591.965 0.105943 0 0 +594.022 0.104301 0 0 +596.077 0.102476 0 0 +598.132 0.100827 0 0 +600.186 0.0995318 0 0 +602.238 0.0975342 0 0 +604.29 0.0969724 0 0 +606.341 0.0954195 0 0 +608.392 0.0954239 0 0 +610.441 0.0950918 0 0 +612.489 0.0934964 0 0 +614.537 0.0925861 0 0 +616.583 0.0919505 0 0 +618.629 0.0927997 0 0 +620.673 0.0923686 0 0 +622.717 0.0907163 0 0 +624.76 0.0908813 0 0 +626.801 0.0903943 0 0 +628.842 0.0900869 0 0 +630.882 0.0884865 0 0 +632.921 0.0881195 0 0 +634.959 0.0889955 0 0 +636.996 0.0898027 0 0 +639.032 0.0891579 0 0 +641.067 0.0873659 0 0 +643.102 0.0883067 0 0 +645.135 0.0879073 0 0 +647.167 0.0890207 0 0 +649.198 0.0895822 0 0 +651.228 0.0893833 0 0 +653.258 0.0880755 0 0 +655.286 0.0869999 0 0 +657.313 0.0888984 0 0 +659.339 0.0877311 0 0 +661.364 0.087686 0 0 +663.389 0.0841387 0 0 +665.412 0.085539 0 0 +667.434 0.085637 0 0 +669.455 0.0860182 0 0 +671.475 0.0872101 0 0 +673.494 0.0873932 0 0 +675.513 0.0833971 0 0 +677.53 0.0860587 0 0 +679.546 0.0844616 0 0 +681.561 0.083438 0 0 +683.574 0.081583 0 0 +685.587 0.0835701 0 0 +687.599 0.0804411 0 0 +689.61 0.0818398 0 0 +691.619 0.077305 0 0 +693.628 0.0760186 0 0 +695.636 0.0737182 0 0 +697.642 0.0735939 0 0 +699.647 0.071516 0 0 +701.652 0.0702327 0 0 +703.655 0.0650611 0 0 +705.657 0.0642871 0 0 +707.658 0.0610527 0 0 +709.658 0.0576016 0 0 +711.657 0.0497871 0 0 +713.655 0.0544937 0 0 +715.651 0.0495205 0 0 +717.647 0.0400808 0 0 +719.641 0.0219393 0 0 +721.634 0.0469534 0 0 +[END] of [DATA] +[END] of [Spectrum] + +[Spectrum] +Version = 1 +IDData = VIPER_A05D_2011-01-28_00-04-05_Absorption_299 +IDDevice = VIPER_A05D +DateTime = 2011-01-28 00:04:05 +Comment = +CommentSub1 = +CommentSub2 = +CommentSub3 = +IDDataType = SPECTRUM +IDDataTypeSub1 = ABSORPTION +IDDataTypeSub2 = SAMPLE +Mission = 1 ; 13.9479 ; ; +[Attributes] +SpectrumType = Absorption +Averaging = 1 +CalFactor = 323.844 +FlashCount = 1 +IntegrationTime = 64 +PathLength = 150 +Temperature = 21.75 +lampReference = 20726 +lampLEDs = 255 +tempLampModule = 21.75 +tempLampPower = 21.875 +tempSpectrometer = 28.25 +tempMainCPU = 29.375 +Deviation = 13.9479 +Maximum = 0.136324 +IDBasisSpec = 1607002963 +SQIBase = 0.02 +RAWDynamic = 65535 +Unit1 = $01 $01 Wavelength nm +Unit2 = $09 $08 Absorption 1 +Unit3 = $09 $08 Absorption 1 +Unit4 = $f1 $00 Status +[END] of [Attributes] +[DATA] +0 5 0 0 +348.449 0.136324 0 0 +350.582 0.115176 0 0 +352.714 0.114441 0 0 +354.846 0.112615 0 0 +356.978 0.113951 0 0 +359.109 0.114539 0 0 +361.239 0.112815 0 0 +363.37 0.113144 0 0 +365.499 0.1139 0 0 +367.629 0.114873 0 0 +369.757 0.114149 0 0 +371.886 0.113016 0 0 +374.014 0.112233 0 0 +376.141 0.112262 0 0 +378.268 0.113251 0 0 +380.394 0.113654 0 0 +382.52 0.11373 0 0 +384.646 0.113448 0 0 +386.771 0.113978 0 0 +388.895 0.115102 0 0 +391.019 0.115808 0 0 +393.142 0.116609 0 0 +395.265 0.115901 0 0 +397.388 0.115861 0 0 +399.509 0.115663 0 0 +401.631 0.115167 0 0 +403.751 0.115485 0 0 +405.872 0.115502 0 0 +407.991 0.115006 0 0 +410.11 0.115343 0 0 +412.229 0.116448 0 0 +414.347 0.117901 0 0 +416.465 0.117905 0 0 +418.582 0.116813 0 0 +420.698 0.115501 0 0 +422.814 0.113723 0 0 +424.929 0.113218 0 0 +427.044 0.114715 0 0 +429.158 0.116798 0 0 +431.271 0.117102 0 0 +433.384 0.117102 0 0 +435.497 0.117733 0 0 +437.608 0.11865 0 0 +439.72 0.119671 0 0 +441.83 0.121463 0 0 +443.94 0.12224 0 0 +446.049 0.122777 0 0 +448.158 0.123801 0 0 +450.266 0.123525 0 0 +452.374 0.123514 0 0 +454.481 0.122707 0 0 +456.587 0.121213 0 0 +458.693 0.120166 0 0 +460.798 0.118996 0 0 +462.902 0.11735 0 0 +465.006 0.115601 0 0 +467.109 0.114995 0 0 +469.211 0.113431 0 0 +471.313 0.113728 0 0 +473.414 0.11379 0 0 +475.514 0.114624 0 0 +477.614 0.115014 0 0 +479.713 0.114796 0 0 +481.812 0.116206 0 0 +483.909 0.1187 0 0 +486.007 0.11938 0 0 +488.103 0.118761 0 0 +490.199 0.119528 0 0 +492.294 0.117262 0 0 +494.388 0.11753 0 0 +496.482 0.115877 0 0 +498.575 0.116129 0 0 +500.667 0.114075 0 0 +502.758 0.114874 0 0 +504.849 0.112829 0 0 +506.939 0.112414 0 0 +509.028 0.111622 0 0 +511.117 0.112507 0 0 +513.205 0.111392 0 0 +515.292 0.112179 0 0 +517.378 0.112893 0 0 +519.464 0.112905 0 0 +521.549 0.112788 0 0 +523.633 0.113245 0 0 +525.717 0.113706 0 0 +527.799 0.114254 0 0 +529.881 0.113681 0 0 +531.962 0.113468 0 0 +534.043 0.114488 0 0 +536.122 0.113524 0 0 +538.201 0.113845 0 0 +540.279 0.113161 0 0 +542.356 0.112822 0 0 +544.433 0.111895 0 0 +546.508 0.111622 0 0 +548.583 0.111193 0 0 +550.658 0.110593 0 0 +552.731 0.109754 0 0 +554.803 0.109837 0 0 +556.875 0.109253 0 0 +558.946 0.108863 0 0 +561.016 0.108534 0 0 +563.085 0.108625 0 0 +565.153 0.10885 0 0 +567.221 0.108636 0 0 +569.288 0.109328 0 0 +571.353 0.109585 0 0 +573.419 0.108959 0 0 +575.483 0.108569 0 0 +577.546 0.108726 0 0 +579.609 0.10938 0 0 +581.67 0.108931 0 0 +583.731 0.108217 0 0 +585.791 0.108494 0 0 +587.85 0.108091 0 0 +589.908 0.107552 0 0 +591.965 0.107027 0 0 +594.022 0.105639 0 0 +596.077 0.103081 0 0 +598.132 0.101632 0 0 +600.186 0.100361 0 0 +602.238 0.0978726 0 0 +604.29 0.0978547 0 0 +606.341 0.0959855 0 0 +608.392 0.0967197 0 0 +610.441 0.096281 0 0 +612.489 0.0948728 0 0 +614.537 0.0936888 0 0 +616.583 0.0941201 0 0 +618.629 0.0950297 0 0 +620.673 0.0939001 0 0 +622.717 0.0916821 0 0 +624.76 0.0917877 0 0 +626.801 0.092899 0 0 +628.842 0.0915353 0 0 +630.882 0.090197 0 0 +632.921 0.0900162 0 0 +634.959 0.0904379 0 0 +636.996 0.0906262 0 0 +639.032 0.0905148 0 0 +641.067 0.0902132 0 0 +643.102 0.0904966 0 0 +645.135 0.090077 0 0 +647.167 0.0931446 0 0 +649.198 0.0929734 0 0 +651.228 0.0895644 0 0 +653.258 0.0913102 0 0 +655.286 0.0902204 0 0 +657.313 0.0907106 0 0 +659.339 0.0906925 0 0 +661.364 0.0917014 0 0 +663.389 0.0897471 0 0 +665.412 0.0899862 0 0 +667.434 0.0911066 0 0 +669.455 0.0925955 0 0 +671.475 0.0924066 0 0 +673.494 0.0874022 0 0 +675.513 0.0897929 0 0 +677.53 0.0955232 0 0 +679.546 0.0922561 0 0 +681.561 0.0908758 0 0 +683.574 0.0905933 0 0 +685.587 0.0926588 0 0 +687.599 0.0886542 0 0 +689.61 0.0891296 0 0 +691.619 0.0854017 0 0 +693.628 0.0855025 0 0 +695.636 0.0842639 0 0 +697.642 0.0807852 0 0 +699.647 0.0854365 0 0 +701.652 0.07816 0 0 +703.655 0.0797006 0 0 +705.657 0.0788991 0 0 +707.658 0.0736432 0 0 +709.658 0.0671164 0 0 +711.657 0.0635526 0 0 +713.655 0.0577297 0 0 +715.651 0.0664879 0 0 +717.647 0.0489089 0 0 +719.641 0.0403429 0 0 +721.634 0.0440485 0 0 +[END] of [DATA] +[END] of [Spectrum] + +[Spectrum] +Version = 1 +IDData = VIPER_A05D_2011-01-28_00-04-17_Absorption_782 +IDDevice = VIPER_A05D +DateTime = 2011-01-28 00:04:17 +Comment = +CommentSub1 = +CommentSub2 = +CommentSub3 = +IDDataType = SPECTRUM +IDDataTypeSub1 = ABSORPTION +IDDataTypeSub2 = SAMPLE +Mission = 1 ; 13.4412 ; ; +[Attributes] +SpectrumType = Absorption +Averaging = 1 +CalFactor = 323.766 +FlashCount = 1 +IntegrationTime = 64 +PathLength = 150 +Temperature = 21.8437 +lampReference = 20721 +lampLEDs = 255 +tempLampModule = 21.8437 +tempLampPower = 21.875 +tempSpectrometer = 28.25 +tempMainCPU = 29.4375 +Deviation = 13.4412 +Maximum = 0.123031 +IDBasisSpec = 1607002963 +SQIBase = 0.02 +RAWDynamic = 65535 +Unit1 = $01 $01 Wavelength nm +Unit2 = $09 $08 Absorption 1 +Unit3 = $09 $08 Absorption 1 +Unit4 = $f1 $00 Status +[END] of [Attributes] +[DATA] +0 5 0 0 +348.449 0.10921 0 0 +350.582 0.106249 0 0 +352.714 0.105195 0 0 +354.846 0.108626 0 0 +356.978 0.111923 0 0 +359.109 0.114493 0 0 +361.239 0.113352 0 0 +363.37 0.113044 0 0 +365.499 0.113505 0 0 +367.629 0.114128 0 0 +369.757 0.11401 0 0 +371.886 0.112603 0 0 +374.014 0.111936 0 0 +376.141 0.111843 0 0 +378.268 0.112687 0 0 +380.394 0.113114 0 0 +382.52 0.112869 0 0 +384.646 0.111981 0 0 +386.771 0.112436 0 0 +388.895 0.113517 0 0 +391.019 0.11404 0 0 +393.142 0.114612 0 0 +395.265 0.114632 0 0 +397.388 0.114846 0 0 +399.509 0.114851 0 0 +401.631 0.114871 0 0 +403.751 0.115197 0 0 +405.872 0.115325 0 0 +407.991 0.11484 0 0 +410.11 0.115362 0 0 +412.229 0.11637 0 0 +414.347 0.1177 0 0 +416.465 0.117591 0 0 +418.582 0.116502 0 0 +420.698 0.114842 0 0 +422.814 0.1131 0 0 +424.929 0.112616 0 0 +427.044 0.11372 0 0 +429.158 0.115484 0 0 +431.271 0.115557 0 0 +433.384 0.115916 0 0 +435.497 0.116502 0 0 +437.608 0.117354 0 0 +439.72 0.118454 0 0 +441.83 0.120266 0 0 +443.94 0.121645 0 0 +446.049 0.122079 0 0 +448.158 0.123031 0 0 +450.266 0.122925 0 0 +452.374 0.122868 0 0 +454.481 0.121753 0 0 +456.587 0.120446 0 0 +458.693 0.119326 0 0 +460.798 0.117968 0 0 +462.902 0.11599 0 0 +465.006 0.113837 0 0 +467.109 0.11301 0 0 +469.211 0.111439 0 0 +471.313 0.111222 0 0 +473.414 0.11099 0 0 +475.514 0.11188 0 0 +477.614 0.110008 0 0 +479.713 0.110535 0 0 +481.812 0.112125 0 0 +483.909 0.11235 0 0 +486.007 0.110902 0 0 +488.103 0.112517 0 0 +490.199 0.11306 0 0 +492.294 0.111639 0 0 +494.388 0.111179 0 0 +496.482 0.110239 0 0 +498.575 0.111034 0 0 +500.667 0.110069 0 0 +502.758 0.110104 0 0 +504.849 0.10934 0 0 +506.939 0.108707 0 0 +509.028 0.107879 0 0 +511.117 0.110376 0 0 +513.205 0.109624 0 0 +515.292 0.110353 0 0 +517.378 0.110075 0 0 +519.464 0.111713 0 0 +521.549 0.111439 0 0 +523.633 0.111188 0 0 +525.717 0.111954 0 0 +527.799 0.113031 0 0 +529.881 0.112574 0 0 +531.962 0.112225 0 0 +534.043 0.113628 0 0 +536.122 0.112248 0 0 +538.201 0.112604 0 0 +540.279 0.11195 0 0 +542.356 0.111843 0 0 +544.433 0.110936 0 0 +546.508 0.110427 0 0 +548.583 0.110015 0 0 +550.658 0.10992 0 0 +552.731 0.10846 0 0 +554.803 0.108746 0 0 +556.875 0.108695 0 0 +558.946 0.108357 0 0 +561.016 0.107934 0 0 +563.085 0.107459 0 0 +565.153 0.107969 0 0 +567.221 0.107848 0 0 +569.288 0.107727 0 0 +571.353 0.108068 0 0 +573.419 0.108107 0 0 +575.483 0.107759 0 0 +577.546 0.107757 0 0 +579.609 0.108146 0 0 +581.67 0.108133 0 0 +583.731 0.107197 0 0 +585.791 0.106876 0 0 +587.85 0.106707 0 0 +589.908 0.106796 0 0 +591.965 0.105353 0 0 +594.022 0.103984 0 0 +596.077 0.102093 0 0 +598.132 0.100495 0 0 +600.186 0.0986265 0 0 +602.238 0.096471 0 0 +604.29 0.0970756 0 0 +606.341 0.0955266 0 0 +608.392 0.0946823 0 0 +610.441 0.0941084 0 0 +612.489 0.0931622 0 0 +614.537 0.092011 0 0 +616.583 0.0915196 0 0 +618.629 0.0924397 0 0 +620.673 0.0916639 0 0 +622.717 0.0902531 0 0 +624.76 0.0889851 0 0 +626.801 0.0903655 0 0 +628.842 0.089774 0 0 +630.882 0.0878642 0 0 +632.921 0.087469 0 0 +634.959 0.0883135 0 0 +636.996 0.0893167 0 0 +639.032 0.0876719 0 0 +641.067 0.0867012 0 0 +643.102 0.0886909 0 0 +645.135 0.0868806 0 0 +647.167 0.0880887 0 0 +649.198 0.0881187 0 0 +651.228 0.0890211 0 0 +653.258 0.0873401 0 0 +655.286 0.0854753 0 0 +657.313 0.0858908 0 0 +659.339 0.0866596 0 0 +661.364 0.085676 0 0 +663.389 0.0855105 0 0 +665.412 0.0835606 0 0 +667.434 0.0843269 0 0 +669.455 0.0862712 0 0 +671.475 0.087192 0 0 +673.494 0.0864687 0 0 +675.513 0.0811654 0 0 +677.53 0.0830458 0 0 +679.546 0.0837456 0 0 +681.561 0.0815851 0 0 +683.574 0.0831213 0 0 +685.587 0.0811132 0 0 +687.599 0.0800009 0 0 +689.61 0.0791275 0 0 +691.619 0.0740054 0 0 +693.628 0.0774927 0 0 +695.636 0.0705968 0 0 +697.642 0.0692218 0 0 +699.647 0.0703695 0 0 +701.652 0.0660184 0 0 +703.655 0.0638062 0 0 +705.657 0.061031 0 0 +707.658 0.0542104 0 0 +709.658 0.057598 0 0 +711.657 0.0550848 0 0 +713.655 0.0425706 0 0 +715.651 0.0445557 0 0 +717.647 0.0297176 0 0 +719.641 0.0237477 0 0 +721.634 0.0383917 0 0 +[END] of [DATA] +[END] of [Spectrum] + diff --git a/dataplot.py b/dataplot.py new file mode 100644 index 0000000..8c737c2 --- /dev/null +++ b/dataplot.py @@ -0,0 +1,466 @@ +# import numpy as np + +from pathlib import Path + + +class DataPlot(): + ''' + 从文件读取数据,出来成待显示数据 + ''' + + # def __init__(self, mypanel, ): + def __init__(self, ): + # self.mypanel = mypanel + # self.__eventManager = eventManger + # self.dataSaveFile = DATA_FNAME_WITHOUT_WATER + # self.axes_title = "Water Attenuation Coefficient" + # self.axes_xlabel = "Wavelength (nm)" + # self.axes_ylabel = "Attenuation Coefficient m(-1)" + # self.axes_title = "Attenuation Coefficient Demo" + self.demo_time = '' + self.demo_wl = [] # 纯水 + self.demo_data = [] # 纯水 + + self.wavelength = None + self.data_one = None + self.data_multi = None + # self.mode = "one" # multi + # self.begin_line = None + # self.line_interval = None + self.fpath :Path = Path() + self.total_lines = 0 + self.token = ";" + # self.MPL = myPanel.MPL_Panel(self) # 调用自己建立的 panel 类 + # self.Figure = self.MPL.Figure + # self.axes = self.MPL.axes + # self.FigureCanvas = self.MPL.FigureCanvas + def set_file_path( self, fpath:Path ): + self.fpath = fpath + pass + + def set_wavelength(self): + pass + + # def set_mode(self, mode ="one"): + # self.mode = mode + # pass + + def set_token(self, token =";"): + self.token = token + pass + + def set_begin_line( self, lineno = 0 ): + self.begin_line = lineno + pass + + def set_line_interval( self, line_interval = 0 ): + self.line_interval = line_interval + pass + + def get_total_lines( self, ): + ''' 大文件 ''' + count = 0 + thefile = open( self.fpath, 'rb') + while True: + buffer = thefile.read(8192*1024) + if not buffer: + break + count += buffer.count(b'\n') + self.total_lines = count + 1 + + def get_wavelength_from_file( self, ): + tmp = self.get_first_line() + self.wavelength = tmp.split(self.token)[1:] + pass + + def get_reverse_x_lineno( self, x ): + line = self.__get_reverse_x_lineno(x) + line = line.split(self.token) + return line[0], line[1:] + pass + + def get_multi_by_x_m_n( self, x,m,n ): + # res_time = [] + # res_lines = [] + lines = self.__get_reverse_x_m_n_line(x,m,n) + # print(f'+++++ {lines}') + # for i in range(len(lines)): + # ln = + # res_time.append( lines[i] [0] ) + # res_lines.append( lines[i][1:] ) + # return res_time, res_lines + return lines + pass + + def __get_reverse_x_lineno(self, x): + """ + 获得倒数第x行 + """ + try: + # filesize = os.path.getsize(self.fpath) + filesize = self.fpath.stat().st_size + if filesize == 0: + return None + else: + with open(self.fpath, 'rb') as fp: # to use seek from end, must use mode 'rb' + offset = -8 # initialize offset + while -offset < filesize: # offset cannot exceed file size + fp.seek(offset, 2) # read # offset chars from eof(represent by number '2') + lines = fp.readlines() # read from fp to eof + if len(lines) >= x+1: # if contains at least 2 lines + return lines[-1*x] # then last line is totally included + else: + offset *= 2 # enlarge offset + fp.seek(0) + lines = fp.readlines() + if len(lines) < x: + raise Exception("行数有误,请重试") + return lines[-1*x] + except FileNotFoundError: + print(self.fpath.name + ' not found!') + return None + + def __get_reverse_x_m_n_line(self, x, m=1, n=1): + """ + 获得倒数第x行, 间隔m行, 共取n个行 + """ + print(f'__get_reverse_x_m_n_line {x} {self.fpath}') + min_lines = x + m*n + res_lines = [] + try: + # filesize = os.path.getsize(self.fpath) + filesize = self.fpath.stat().st_size + if filesize == 0: + return None + else: + with open(self.fpath, 'rb') as fp: # to use seek from end, must use mode 'rb'x + offset = -8 # initialize offset + while -offset < filesize: # offset cannot exceed file size + fp.seek( offset, 2 ) # read # offset chars from eof(represent by number '2') + lines = fp.readlines() # read from fp to eof + if len(lines) >= min_lines+1 : + for i in range(n): + res_lines.append( lines[-1*(x+m*i)].decode()) + return res_lines + else: + offset *= 2 # enlarge offset + fp.seek( 0 ) + lines = fp.readlines( ) + if len(lines) < min_lines: + raise Exception("行数有误,请重试") + for i in range(n): + res_lines.append( lines[-1*(x+m*i)].decode()) + return res_lines + print(res_lines) + except FileNotFoundError: + print(self.fpath.name + ' not found!') + return None + + def get_first_line(self, ): + firstline = '' + with open(self.fpath, 'rb') as fp: # to use seek from end, must use mode 'rb'x + firstline = fp.readline() + return firstline.decode() + + def get_last_line(self,filename:Path): + """ + 获得最后一行 + :param filename: file name + :return: last line or None for empty file + """ + try: + filesize = filename.stat().st_size + if filesize == 0: + return None + else: + with open(filename, 'rb') as fp: # to use seek from end, must use mode 'rb' + offset = -8 # initialize offset + while -offset < filesize: # offset cannot exceed file size + fp.seek(offset, 2) # read # offset chars from eof(represent by number '2') + lines = fp.readlines() # read from fp to eof + if len(lines) >= 2: # if contains at least 2 lines + return lines[-1] # then last line is totally included + else: + offset *= 2 # enlarge offset + fp.seek(0) + lines = fp.readlines() + return lines[-1] + except FileNotFoundError: + print(filename + ' not found!') + return None + + def tail(file, taillines=500, return_str=True, avg_line_length=None): + """ + 大文件的尾行,小文件会导致报错 + taillines : 读取尾部多少行 + avg_line_length:每行字符平均数, + return_str:返回类型,默认为字符串,False为列表。 + offset:每次循环相对文件末尾指针偏移数 + f.tell() 当前指针位置 + f.seek(a,b) a 偏移量, b:0 1 2 ,文件头 当前位置 文件尾部 + """ + with open(file, errors='ignore') as f: + if not avg_line_length: + f.seek(0, 2) + f.seek(f.tell() - 3000) + avg_line_length = int(3000 / len(f.readlines())) + 10 + f.seek(0, 2) + end_pointer = f.tell() + offset = taillines * avg_line_length + if offset > end_pointer: + f.seek(0, 0) + lines = f.readlines()[-taillines:] + return "".join(lines) if return_str else lines + offset_init = offset + i = 1 + while len(f.readlines()) < taillines: + location = f.tell() - offset + f.seek(location) + i += 1 + offset = i * offset_init + if f.tell() - offset < 0: + f.seek(0, 0) + break + else: + f.seek(end_pointer - offset) + lines = f.readlines() + if len(lines) >= taillines: + lines = lines[-taillines:] + + return "".join(lines) if return_str else lines + + + # def makeMsg(self,key,value): + # """ + # 事件对象:制造事件 + # 将事件写入event 并send + # """ + # # event = eventManager.Event( type_ = eventManager.EVENT_MSG) + # event.dict[key] = value + + # # 发送事件 + # self.__eventManager.SendEvent(event) + +if __name__ == "__main__": + d = DataPlot() + + + + # def plot_demo( self, time_, data ,wavelength): + # ''' + # @ 根据数据画demo曲线 + # ''' + # x = np.array( wavelength ).astype(np.float) + # datetime_ = str(time_ ) + # y = np.array(data).astype(np.float) + + # self.mypanel.axes.clear() # 清空上次画的内容 + # self.mypanel.axes.set_title( self.axes_title ) + # self.mypanel.axes.set_xlabel( self.axes_xlabel ) + # self.mypanel.axes.set_ylabel( self.axes_ylabel ) + + # self.mypanel.axes.plot(x, y, color="green", linewidth=0.5 , label=datetime_ ) + # self.mypanel.axes.legend() + # self.mypanel.axes.grid(True) + # self.mypanel.FigureCanvas.draw() + + # def plot_one( self, time_, data ,wavelength): + # ''' + # @ 根据数据画一条曲线 + # @ 参数 data + # ''' + # x = np.array( wavelength ).astype(np.float) + # datetime_ = str(time_ ) + # y = np.array(data).astype(np.float) + + # self.mypanel.axes.clear() # 清空上次画的内容 + # self.mypanel.axes.set_title( self.axes_title ) + # self.mypanel.axes.set_xlabel( self.axes_xlabel ) + # self.mypanel.axes.set_ylabel( self.axes_ylabel ) + + # self.mypanel.axes.plot(x, y, color="green", linewidth=0.5 , label=datetime_ ) + # self.mypanel.axes.legend() + # self.mypanel.axes.grid(True) + # self.mypanel.FigureCanvas.draw() + + # def plotOne( self, data ): + # ''' + # @ 根据数据画一条曲线 + # @ 参数 data + # ''' + # x = np.array( self.wavelength ).astype(np.float) + + # datetime_ = data[0] + # y = np.array(data[1:]).astype(np.float) + + # self.mypanel.axes.clear() # 清空上次画的内容 + # self.mypanel.axes.set_title( self.axes_title ) + # self.mypanel.axes.set_xlabel( self.axes_xlabel ) + # self.mypanel.axes.set_ylabel( self.axes_ylabel ) + + # self.mypanel.axes.plot(x, y, color="green", linewidth=0.5 , label=datetime_ ) + # self.mypanel.axes.legend() + # self.mypanel.axes.grid(True) + # self.mypanel.FigureCanvas.draw() + + + # def OnPlot(self, wl, fpath ): + # """ + # * 查看历史曲线 + # * 默认从最后一条记录读取 + # """ + # temp = self.__get_last_line( fpath ).decode().split(TOKEN) + # time_ = temp[0] + # data = temp[1:] + + # # 加判断波长 + # print(fpath) + + # if len(data) > len( wl ): + # for i in range( len(data)-len(wl) ): + # data.pop() + + # self.plot_one( time_ , data, wl ) + + + # def plotSeven(self,wavelength,d): + # ''' + # * 根据数据画七条曲线 + # * 兼容数量不够七条的 + # ''' + # # myDebug.MyDebug.log_info( ":::::::::::: Class : %s -> Function : get_file_list " % ( __name__, ) ) + # # myDebug.MyDebug.log_ctl( " d len : %s " % ( len(d), ) ) + # # myDebug.MyDebug.log_ctl( " d : %s " % ( d, ) ) + + # x = np.array( wavelength ).astype(np.float) + # self.mypanel.axes.clear() # 清空上次画的内容 + # self.mypanel.axes.set_title( self.axes_title ) + # self.mypanel.axes.set_xlabel( self.axes_xlabel ) + # self.mypanel.axes.set_ylabel( self.axes_ylabel ) + + # # 处理 data + # length = len(d) + # data = [] + # for s in d: + # ss = s.split(TOKEN) + # ss0 = ss[0] + # ss1 = ss[1:] + # # 去掉尾部多余 + # if len(ss1) > len( wavelength ): + # for i in range( len(ss1)-len(wavelength) ): + # ss1.pop() + # data.append( [ss0, ss1] ) + + # print( " data : %s " % ( len(data) , ) ) + + # if length >=1 : + # print( " data[0][0] %s " % (data[0][0],)) + + # d0 = data[0][0] + # y0 =np.array(data[0][1]).astype(np.float) + # self.mypanel.axes.plot(x, y0, 'r', linewidth=0.5 , label = d0 ) + + # # len(data) =2 + # if len(data) >=2 : + # d1 = data[1][0] + # y1 =np.array(data[1][1]).astype(np.float) + # self.mypanel.axes.plot(x, y1, color='orange', linewidth=0.5 , label=d1 ) + # # len(data) =3 + # if len(data) >=3 : + # d2 = data[2][0] + # y2 =np.array(data[2][1]).astype(np.float) + # self.mypanel.axes.plot(x, y2, 'y', linewidth=0.5 , label=d2 ) + # # len(data) =4 + # if len(data) >=4 : + # d3 = data[3][0] + # y3 =np.array(data[3][1]).astype(np.float) + # self.mypanel.axes.plot(x, y3, 'g', linewidth=0.5 , label=d3 ) + # # len(data) =5 + # if len(data) >=5 : + # d4 = data[4][0] + # y4 =np.array(data[4][1]).astype(np.float) + # self.mypanel.axes.plot(x, y4, 'c', linewidth=0.5 , label=d4 ) + # # len(data) =6 + # if len(data) >=6 : + # d5 = data[5][0] + # y5 =np.array(data[5][1]).astype(np.float) + # self.mypanel.axes.plot(x, y5, 'b', linewidth=0.5 , label=d5 ) + # # len(data) =7 + # if len(data) >=7 : + # d6 = data[6][0] + # y6 =np.array(data[6][1]).astype(np.float) + # self.mypanel.axes.plot(x, y6, color='purple', linewidth=0.5 , label=d6 ) + + # self.mypanel.axes.legend() + # self.mypanel.axes.grid( True ) + # self.mypanel.FigureCanvas.draw() + + + # def OnPlot_7(self, wl, fpath): + # """ + # 最后间隔七条 + # 默认间隔数为1 + # """ + # result_line = [] + # count = 0 + # thefile = open( fpath, 'rb') + # while True: + # buffer = thefile.read(8192*1024) + # if not buffer: + # break + # count += buffer.count(b'\n') + # count = count + 1 + # self.makeMsg(1, u" 文件共有 " + str(count) + " 行" ) + # # self.statusBar.SetStatusText(u" 文件共有 "+str(count)+" 行",0) + # # 判断文件是否已有数据 + # if count == 0: + # #print('文件没有内容!') + # self.makeMsg(2, u"数据文件没有记录!" ) + # # with wx.MessageDialog(self, u"数据文件没有记录!", u"错误提示", wx.OK )as dlg: + # # dlg.ShowModal() + # elif count < 8: + # for i in range(count-1): + # result_line.append(linecache.getline( fpath, count-i).strip("\n")) + # else: + # for i in range(7): + # result_line.append(linecache.getline( fpath, count-i).strip("\n")) + + # # 画7天的图像 + # thefile.close() + # self.plotSeven( wl,result_line ) + + # def OnPlot_D(self, wl,fpath, interval, begin): + # """ + # 指定位置间隔七条 + # 考虑数据是否够 + # """ + # # print( "i am plot d") + # # self.readConfig() + # result_line = [] + # count = 0 + # thefile = open( fpath, 'rb') + # while True: + # buffer = thefile.read(8192*1024) + # if not buffer: + # break + # count += buffer.count(b'\n') + # count = count + 1 + # self.makeMsg(1, u" 文件共有 "+str(count)+" 行" ) + + # # 判断文件绘图参数设置是否正确 + # if count == 0: + # #print('文件没有内容!') + # self.makeMsg(2, u"数据文件没有记录!" ) + # # with wx.MessageDialog(self, u"数据文件没有记录!", u"错误提示", wx.OK )as dlg: + # # dlg.ShowModal() + # elif ( interval*7 + begin ) < (count-1): + # for i in range(7): + # result_line.append( linecache.getline( fpath,count-begin-i*interval ).strip("\n") ) + # else: + # for i in range( ( (count-1)-begin )//interval ): + # result_line.append(linecache.getline( fpath,count-begin-i*interval ).strip("\n") ) + + # # 画7天的图像 + # thefile.close() + # self.plotSeven( wl, result_line ) + \ No newline at end of file diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000..9d501c8 Binary files /dev/null and b/icon.ico differ diff --git a/listctrl.py b/listctrl.py new file mode 100644 index 0000000..210bc4f --- /dev/null +++ b/listctrl.py @@ -0,0 +1,32 @@ +from myconfig import TOKEN +import wx + +class Listctrl(wx.Panel): + ''' + # 需要在 Frame 实例化一个实例 + # 改变需要对实例化后的进行操作 + ''' + def __init__(self, parent ): + ''' + * panel 初始化后的样子 + ''' + # self.para_setting = para + super(Listctrl,self).__init__(parent) + self.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED) + + self.SetBackgroundColour('lightgrey') + + self.box = wx.BoxSizer(wx.HORIZONTAL) + + self.list_ctrl = wx.ListCtrl(self, -1, style = wx.LC_REPORT | wx.LC_SORT_DESCENDING) + self.list_ctrl.SetBackgroundColour( 'lightgrey' ) + + self.list_ctrl.InsertColumn(0, u'测量时间', width = 180) + self.list_ctrl.InsertColumn(1, u'花粉_Pollen', width = 180) + i = 1 + + self.list_ctrl.SetFont( wx.Font( 11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False ) ) + + self.box.Add(self.list_ctrl,1,wx.EXPAND) + self.SetSizer(self.box) + self.Fit() diff --git a/myconfig.py b/myconfig.py new file mode 100644 index 0000000..a1b8ed9 --- /dev/null +++ b/myconfig.py @@ -0,0 +1,187 @@ +#! python3 +# -*- encoding: utf-8 -*- +''' +@File : myconfig.py +@Time : 2023/03/01 15:28:20 +@Author : Jim @ Yiwin +@Version : 1.0 +@Contact : jim@yi-win.com +@Descrip : SysConfig +''' + +import yaml +from enum import Enum +from pathlib import Path +VERSION = "3.5.0" +LASTDATE = "2023-03-7" +COMPANY = u"奕枫仪器" + +CURRENT_DIR = Path() +DATA_DIR = "data" +CAL_DIR = "calfile" +OUTPUT_DIR = "output" +YAML_FILE_NAME = "config.yml" +RETRIEVE_CFG_FILE = "retrieve.yml" +PURE_WATER_FNAME = "attenuation_pure_water.DAT" +FILE_MARK = ['Spectrum', 'DATA'] +SAVE_EXT_NAME = ".csv" +INTERVAL = 1.0 +SEPARATOR = ";" +TOKEN = ";" +NEWLINE = "\n" + + +class DeviceType(Enum) : + VIPER = 1 + OSCAR = 2 + SC6 = 3 + + +DEVICE = { + "UIPath" : 150 , + "UISN" : "A05D" + } + +# 一次最多 256个字节,步长<128, 字节数<256,浮点数最多63个 +# viper 2100 2462 352/2 = 171, 一次60个 +# oscar 2100 2329 230/2 = 116 一次60个 +REGISTER = { + "slaveaddress" : 1, + "functioncode" : 3, + "SNAddress" : 10, # 测试使用2980 + "SNLen" : 5, + "WLBeginAddress" : 2102, # 2100+2 + "DataBeginAddress" : 2614, # 2612+2 + "count" : 3 #oscar 2 viper 3 + } + +COMSETTING = { + "port" : "COM1" , + "baudrate" : 9600, + 'bytesize' : 8, + 'parity' : "N", + 'stopbit' : 1 + } + +PLOTSETTING = { + "LineInterval" : 1 , + "LineBegin" : 0 + } + +LOGSETTING= { + "LogInterval" : 1, + "RefreshInterval" : 0 + } + +ALGORITHM = { + "A720" : 0, # 0: 720 11项平均值法, 1: 720 附近两个点插值 2: 720 为0 + "PureWater" : 0, # 0 :包含纯水系数 1: 不包含纯水系数 + "PureWater2" : 0 + } + +RETRIEVE = { + # "Enable" : 1, + "BeginWL" : 360, + "EndWL" : 721, + "Interval" : 1 + } + +FILEPATH = { + "path" : '' + } + +class MyConfig(object): + """ + 如上预定义数据 + 先写一个yaml 文件出来,修改后,读文件数据就可以 + """ + def __init__(self) -> None: + self.device_sn = "" + self.system_cfg = {} + self.cfg_path = Path() + self.yml_cfg_file = self.cfg_path.joinpath(YAML_FILE_NAME) + self.retrieve_cfg_file = Path(RETRIEVE_CFG_FILE) + self.getSystemCfg() # 默认的值 + + def getSystemCfg(self,)->None: + ''' + 获得默认的值 + ''' + self.system_cfg = {} + self.system_cfg.update( {"device":DEVICE} ) + self.system_cfg.update( {"register":REGISTER} ) + self.system_cfg.update( {"plotsetting":PLOTSETTING} ) + self.system_cfg.update( {"logsetting":LOGSETTING} ) + self.system_cfg.update( {"comsetting":COMSETTING} ) + self.system_cfg.update( {"algorithm":ALGORITHM} ) + self.system_cfg.update( {"filepath":FILEPATH} ) + pass + + def getDictByAttr(self, *args) -> dict: + ret = {} + if len(args) == 0: + return ret + if len(args) == 1: + if not hasattr( self, args[0] ): + return ret + tmp = getattr( self, args[0] ) + if isinstance( tmp, dict ): + ret.update(tmp) + return ret + if len(args) == 2: + if not hasattr(self, args[0]): + return ret + if not isinstance(getattr(self, args[0]), dict): + return ret + tmp: dict = getattr(self, args[0]) + if not tmp.__contains__(args[1]): + return ret + tmp2 = tmp[args[1]] + if isinstance(tmp2, dict): + ret.update(tmp2) + return ret + if len(args) > 2: + return ret + pass + + # 设置字典对应的键值 + def set_attr(self, d: dict, k, v) -> bool: + if d.__contains__(k): + d.update({k: v}) + return True + return False + + def write_yaml(self, d: dict): + with open(self.yml_cfg_file, "w", encoding = "utf-8") as f: + yaml.dump(d, f) + + def read_yaml(self ) -> dict: + # self.write_yaml(self.system_cfg) + with open(self.yml_cfg_file, "r", encoding="utf-8") as f: + content = f.read() # conent 读出来是字符串 + d = yaml.load(content, Loader=yaml.FullLoader) # 用load方法转字典 + return d + + def write_rtv_yaml(self, d: dict): + with open(self.retrieve_cfg_file, "w", encoding="utf-8") as f: + yaml.dump(d, f) + + def read_rtv_yaml(self ) -> dict: + with open(self.retrieve_cfg_file, "r", encoding="utf-8") as f: + content = f.read() # conent 读出来是字符串 + d = yaml.load(content, Loader=yaml.FullLoader) # 用load方法转字典 + return d + + def set_retrieve(self) -> dict: + retrieve = {} + # retrieve.update({"enable": RETRIEVE["Enable"]}) + retrieve.update({"beginWL": RETRIEVE["BeginWL"]}) + retrieve.update({"endWL": RETRIEVE["EndWL"]}) + retrieve.update({"interval": RETRIEVE["Interval"]}) + self.write_rtv_yaml(retrieve) + return retrieve + pass + + +if __name__ == "__main__": + pass \ No newline at end of file diff --git a/myexception.py b/myexception.py new file mode 100644 index 0000000..6e1209e --- /dev/null +++ b/myexception.py @@ -0,0 +1,14 @@ +class TCPIPException(Exception): + + def __init__(self, message="TCPIP 自定义异常"): + self.message = "TCPIP exception : " + message + +class SerialException(Exception): + + def __init__(self, message="Serial 自定义异常"): + self.message = "serial exception : " + message + +class MyException(Exception): + + def __init__(self, message=" 自定义异常"): + self.message = "自定义异常: " + message \ No newline at end of file diff --git a/mylogger.py b/mylogger.py new file mode 100644 index 0000000..9c85ec9 --- /dev/null +++ b/mylogger.py @@ -0,0 +1,285 @@ +# coding=utf-8 +''' +单例模式日志 -- 使用一次关闭 handler +这种方法优缺点: +缺点: 输出的format 需要自己定义 ,并过滤 + 过滤要看是否以什么开头,或包含什么 +优点: 不占用文件资源,占用系统资源小 +调用 log.info( ) log.error() +''' + +import logging +import logging.handlers +import os +import time +import threading +# from config import LOG_PATH,LOG_LEVEL,LOG_ENABLED,LOG_FORMAT, \ +# LOG_TO_CONSOLE,LOG_TO_FILE + +MY_LOGGER_NAME = "DefaultLogger" +LOG_ENABLED = True # 是否启用日志 +LOG_TO_CONSOLE = True # 是否启用控制台输出日志 +LOG_TO_FILE = False # 是否启用文件输出 +LOG_COLOR_ENABLE = True # 是否启用颜色日志 + +LOGGER_DIR = "logs" +LOGGER_PATH = os.path.join( os.path.dirname(__file__), LOGGER_DIR ) +LOGGER_FILENAME = os.path.join( LOGGER_PATH, 'logs.log' ) + +""" +logging.INFO , logging.DEBUG , logging.WARNING , logging.ERROR , +""" +LOG_LEVEL = logging.INFO # 日志等级DEBUG INFO WARNIG ERROR +# LOG_LEVEL = logging.DEBUG +# LOG_LEVEL = logging.WARNING + +""" +# LOG_FORMAT = " %(name)s - %(module)s - %(filename)s - %(lineno)d | %(levelname)s : %(message)s" +# LOG_FORMAT = "%(levelname)s - %(asctime)s - process: %(process)d - threadname: %(thread)s " \ +# "- %(filename)s - %(funcName)s - %(lineno)d - %(module)s " \ +# "- %(message)s " +# LOG_FORMAT = "%(asctime)s - %(thread)s " \ +# "- %(levelname)s ::: %(message)s " +# '[%(asctime)s] |%(thread)s| %(levelname)-6s: %(message)s' +# fm = '%(levelname):%(levelno)s:%(name)s:%(funcName)s:%(asctime):%(pathname):%(filename):%(module):%(thread):%(threadName)' +# 此处日志颜色,修改日志颜色是通过 Filter实现的 +""" +LOG_FORMAT = '%(levelname)s\t[%(asctime)s] %(package)s:%(classname)s:%(funcname)s \t>> %(message)s' + +""" +# 此处日志颜色,修改日志颜色是通过 Filter实现的 +""" +LOG_FORMAT_COLOR_DICT = { + 'ERROR' : "\033[31mERROR\033[0m", + 'INFO' : "\033[36mINFO\033[0m", + 'DEBUG' : "\033[1mDEBUG\033[0m", + 'WARN' : "\033[33mWARN\033[0m", + 'WARNING' : "\033[33mWARNING\033[0m", + 'CRITICAL': "\033[35mCRITICAL\033[0m", +} + +""" +# Filter 用法, 以package class function 过滤 __package__ __class__ +# log.error( f"{__package__}::{__class__.__name__}::{sys._getframe().f_code.co_name} >> ") +# log.error( f"PacakgeName::ClassName::FunctionName:: ") +# LOGGER_FILTER_PACKAGE=[] 为空, 则Filter不起作用 +# 不为空,则只显示定义的报名 +# LOGGER_FILTER_CLASS=[] 为空, 则Filter不起作用 +# 不为空,则只显示定义的类或 +# LOGGER_FILTER_FUNCNAME=[] 为空, 则Filter不起作用 +# 不为空,则只显示定义的函数 +""" +# LOGGER_FILTER_PACKAGE = [ "test_logger" ] # 包名,文件名去 .py?? +LOGGER_FILTER_PACKAGE = [ ] +LOGGER_FILTER_CLASS = [ ] # 类名,文件名去 .py?? +# LOGGER_FILTER_CLASS = [ "LogTest" ] +# LOGGER_FILTER_FUNCNAME = [ "test1","test" ] # 函数名 +LOGGER_FILTER_FUNCNAME = [ ] +LOGGER_FILTER_LEVELNAME = [ ] # INFO DEBUG WARNING + +class PackageFilter(logging.Filter): + def __init__(self, filter_word:list = []): + self.filter_word = filter_word + pass + def filter(self, record: logging.LogRecord) -> bool: + if self.filter_word is not None: + return record.package in self.filter_word + +class ClassFilter(logging.Filter): + def __init__(self, filter_word:list = []): + self.filter_word = filter_word + pass + def filter(self, record: logging.LogRecord) -> bool: + if self.filter_word is not None: + return record.classname in self.filter_word + + pass + +class FunctionFilter(logging.Filter): + def __init__(self, filter_word:list = []): + self.filter_word = filter_word + pass + def filter(self, record:logging.LogRecord) -> bool: + if self.filter_word is not None: + return record.funcname in self.filter_word + +class LevelNameFilter(logging.Filter): + def __init__(self, filter_word:list = []): + self.filter_word = filter_word + pass + def filter(self, record:logging.LogRecord) -> bool: + if self.filter_word is not None: + return record.levelname in self.filter_word + +class ColorFilter(logging.Filter): + def __init__(self,): + pass + def filter(self, record: logging.LogRecord) -> bool: + record.levelname = LOG_FORMAT_COLOR_DICT.get(record.levelname) + return True + +class Log(object): + _instance_lock = threading.Lock() + + def __new__(cls, *args, **kwargs): + if not hasattr(Log, "_instance"): + with Log._instance_lock: + if not hasattr(Log, "_instance"): + Log._instance = object.__new__(cls) + return Log._instance + + def __init__(self, loggername = "DefaultLog" ): + # 文件命名 os.path.join(): 将多个路径组合后返回 + self.logger_filepath = LOGGER_FILENAME + self.loggername = loggername + self.level = LOG_LEVEL + + # 日志输出格式 + fm = LOG_FORMAT + self.formatter = logging.Formatter( fm ) + + # 生成记录器对象 + self.logger = logging.getLogger( self.loggername ) + self.logger.setLevel(LOG_LEVEL) + + # 日志过滤 + self.__add_filter() + + def __console(self, level, message, extra={} ): + # 添加 handler + self.__add_handler() + + # 判断日志级别 + if level == logging.INFO: + self.logger.info( message, extra=extra) + elif level == logging.DEBUG: + self.logger.debug(message,extra=extra) + elif level == logging.WARNING: + self.logger.warning(message,extra=extra) + elif level == logging.ERROR: + self.logger.error(message,extra=extra) + + # removeHandler在记录日志之后移除句柄,避免日志输出重复问题 + self.__remove_handler() + # if LOG_TO_FILE and self.file_handler: + # self.logger.removeHandler(self.file_handler) + # # 关闭打开的文件 + # self.file_handler.close() + # if LOG_TO_CONSOLE and self.stream_handler: + # self.logger.removeHandler(self.stream_handler) + # # 关闭打开的文件 + # self.stream_handler.close() + pass + + # debug < info< warning< error< critical + # debug模式 + def debug(self, message, package="Unknown", classname="Unknown", funcname="Unknown" ): + self.__console(logging.DEBUG, message, extra={"package":package, "classname":classname, "funcname":funcname} ) + # self.__remove_handler() + # info模式 + def info(self, message, package="Unknown", classname="Unknown", funcname="Unknown" ): + self.__console(logging.INFO, message, extra={"package":package, "classname":classname, "funcname":funcname} ) + # self.__remove_handler() + # warning模式 + def warning(self, message, package="Unknown", classname="Unknown", funcname="Unknown"): + self.__console(logging.WARNING, message, extra={"package":package, "classname":classname, "funcname":funcname} ) + # self.__remove_handler() + + # error模式 + def error(self, message, package="Unknown", classname="Unknown", funcname="Unknown"): + self.__console(logging.ERROR, message, extra={"package":package, "classname":classname, "funcname":funcname} ) + # self.__remove_handler() + + def __add_filter(self ): + if len( LOGGER_FILTER_PACKAGE ) > 0 : + self.logger.addFilter( PackageFilter( filter_word=LOGGER_FILTER_PACKAGE ) ) + if len( LOGGER_FILTER_CLASS ) > 0 : + self.logger.addFilter( ClassFilter( filter_word=LOGGER_FILTER_CLASS ) ) + if len( LOGGER_FILTER_FUNCNAME ) > 0 : + self.logger.addFilter( FunctionFilter( filter_word=LOGGER_FILTER_FUNCNAME ) ) + if len(LOGGER_FILTER_LEVELNAME) > 0 : + self.logger.addFilter( LevelNameFilter( filter_word=LOGGER_FILTER_LEVELNAME ) ) + + def __add_handler(self ): + if LOG_ENABLED and LOG_TO_FILE: + # 考虑使用 RotatingFileHandler TimedRotatingFileHandler防止日志过大 + # RotatingFileHandler("test", "a", 4096, 2, "utf-8") + # TimedRotatingFileHandler(filename=LOG_PATH+"thread_", when="D", interval=1, backupCount=7) + self.file_handler = logging.handlers.TimedRotatingFileHandler(filename=self.logger_filepath, when='D', interval=1, backupCount=30, encoding='utf-8') + # self.file_handler = logging.FileHandler( self.logger_filepath, encoding='utf-8' ) + self.file_handler.setFormatter( self.formatter ) + # self.file_handler.setLevel( LOG_LEVEL ) + # if LOG_COLOR_ENABLE: # 文件日志无需加彩色 + # self.file_handler.addFilter( ColorFilter( ) ) + self.logger.addHandler(self.file_handler) + + if LOG_ENABLED and LOG_TO_CONSOLE: + # 创建一个StreamHandler,用于输出到控制台 + + self.stream_handler = logging.StreamHandler() + self.stream_handler.setFormatter(self.formatter) + # self.stream_handler.setLevel( LOG_LEVEL ) + if LOG_COLOR_ENABLE: + self.stream_handler.addFilter( ColorFilter( ) ) + self.logger.addHandler(self.stream_handler) + + def __remove_handler(self ): + if LOG_TO_FILE and self.file_handler: + self.logger.removeHandler(self.file_handler) + if len(self.logger.handlers)>0: + self.logger.handlers.pop() + # 关闭打开的文件 + self.file_handler.close() + if LOG_TO_CONSOLE and self.stream_handler: + self.logger.removeHandler(self.stream_handler) + if len(self.logger.handlers)>0: + self.logger.handlers.pop() + # 关闭控制台 + self.stream_handler.close() + + def __remove_handler2(self ): + if LOG_ENABLED and LOG_TO_CONSOLE: + self.logger.removeHandler(self.stream_handler) + self.logger.handlers.pop() + # 关闭控制台 + self.stream_handler.close() + if LOG_ENABLED and LOG_TO_FILE: + self.logger.removeHandler(self.file_handler) + self.logger.handlers.pop() + # 关闭打开的文件 + self.file_handler.close() + + +log = Log( loggername = "DefaultLog") + +""" +filename: 指定日志文件名 +filemode: 和file函数意义相同,指定日志文件的打开模式,’w’或’a’ +format: 指定输出的格式和内容,format可以输出很多有用信息。显示的条目可以是以下内容: +%(levelname): 日志级别的名字格式 +%(levelno)s: 日志级别的数字表示 +%(name)s: 日志名字 loggername +%(funcName)s: 函数名字 +%(asctime): 日志时间,可以使用datefmt去定义时间格式,如上图。 +%(pathname): 脚本的绝对路径 +%(filename): 脚本的名字 +%(module): 模块的名字 +%(thread): thread id +%(threadName): 线程的名字 +""" + +""" +文件名行号 函数名, 要在调用的时候想办法了 +# 绝对路径 +print( __file__ ) +print( sys.argv[0] ) + +# 文件名 +print( os.path.basename(__file__) ) +print( os.path.basename(sys.argv[0]) ) + +self.__class__.__name__ +self.__class__.__name__, get_current_function_name() + +logger名 __name__ +""" \ No newline at end of file diff --git a/mypanel.py b/mypanel.py new file mode 100644 index 0000000..8c78afd --- /dev/null +++ b/mypanel.py @@ -0,0 +1,137 @@ +import wx +import numpy as np +from enum import Enum +from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas #FigureCanvasWxAgg +from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar # FIgure 导航 +from matplotlib.figure import Figure + +class LineColor(Enum): + RED = 0 + ORANGE = 1 + YELLOW = 2 + GREEN = 3 + CYAN = 4 + BLUE = 5 + PURPLE = 6 + + +class Plot(wx.Panel): + ''' + # 需要在 Frame 实例化一个实例 + # 改变需要对实例化后的进行操作 + ''' + ''' + Matplotlib Panel 单独拿出来画图 + 可以 __do_layout + 可以 __add_widgets + 可以 button事件 + 可以鼠标事件 + ''' + def __init__(self,parent): + ''' + * panel 初始化后的样子 + ''' + super(Plot,self).__init__(parent) + # 本地化语言 + self.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED) + + self.Figure = Figure(figsize=(4,3)) # 4,3 为英寸 + self.axes = self.Figure.add_axes([0.1,0.1,0.8,0.8],facecolor="lightgray") # 坐标系起始位置 + self.FigureCanvas = FigureCanvas(self,-1,self.Figure) + + #继承鼠标移动显示鼠标处坐标的事件 + # self.FigureCanvas.mpl_connect('motion_notify_event',self.MPLOnMouseMove) + + # self.NavigationToolbar = NavigationToolbar(self.FigureCanvas) + + # self.StaticText = wx.StaticText(self,-1,label=u'坐标信息') + + # self.SubBoxSizer = wx.BoxSizer(wx.HORIZONTAL) + # self.SubBoxSizer.Add(self.NavigationToolbar,proportion =0, border = 2,flag = wx.ALL | wx.EXPAND) + # self.SubBoxSizer.Add(self.StaticText,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND) + + self.TopBoxSizer = wx.BoxSizer(wx.VERTICAL) + # self.TopBoxSizer.Add(self.SubBoxSizer,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND) + self.TopBoxSizer.Add(self.FigureCanvas,proportion =-10, border = 2,flag = wx.ALL | wx.EXPAND) + + self.SetSizer(self.TopBoxSizer) + + self.purewater_legend = ("Pure Water Attenuation Coefficient" + ,"Wavelength (nm)" + ,"Attenuation Coefficient m(-1)" ) + + def set_axes_title(self,title): + self.axes.set_title(title) + + def set_axes_xlabel(self,x): + self.axes.set_xlabel(x) + + def set_axes_ylable(self,y): + self.axes.set_ylabel(y) + + def set_title_x_y(self,title, x, y): + self.axes.set_title(title) + self.axes.set_xlabel(x) + self.axes.set_ylabel(y) + + def plot_one( self, time_, wavelength:np.ndarray, data:np.ndarray, color="green" ): + self.axes.plot(wavelength, data, color=color, linewidth=0.5 , label=time_ ) + self.axes.legend( ) + self.axes.grid( True ) + self.FigureCanvas.draw() + + + def plot_multi( self, time_, wavelength:np.ndarray, data:np.ndarray ): + len_ = len(data) + for i in range(len_): + self.axes.plot(wavelength, data[i], color=LineColor(i).name.lower(), linewidth=0.5 , label=time_[i] ) + # self.axes.legend(time_) + self.axes.grid(True) + self.FigureCanvas.draw() + + def clear_past( self, ): + self.axes.clear() + + # def MPLOnMouseMove(self,event): + # ''' + # * 显示坐标值 + # ''' + # ex=event.xdata#这个数据类型是numpy.float64 + # ey=event.ydata#这个数据类型是numpy.float64 + # if ex and ey : + # #可以将numpy.float64类型转化为float类型,否则格式字符串可能会出错 + # self.StaticText.SetLabel('%10.5f,%10.5f' % (float(ex),float(ey))) + +class MyPanel(wx.Panel): + """docstring for MyPanel.""" + def __init__(self, *arg, **kwarg): + super(MyPanel, self).__init__( *arg,**kwarg) + + self.SetBackgroundColour("#F2F2F2") + self.sb = wx.StaticBox( self, label='系统信息', pos = (30,30) ) + + self.sbs = wx.StaticBoxSizer( self.sb, orient=wx.VERTICAL ) + + self.vbox1 = wx.BoxSizer(wx.VERTICAL) + self.staticText0 = wx.StaticText(self , label='',size=(60, 30), style=wx.ALIGN_CENTRE_VERTICAL ) + + self.staticText1 = wx.StaticText(self, -1,size=(600, -1), + label='''\n上海奕枫仪器设备有限公司 + \n电话: 021-54270075 + \n网站: http://www.yi-win.com + \n邮件: sales@yi-win.com + \n描述: AWRAMS离线数据处理 ''' ) + + + self.vbox1.Add(self.staticText0, flag=wx.TOP|wx.LEFT, border=5) + self.vbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + # self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + # self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.vbox1, flag=wx.TOP|wx.LEFT, border= 5) + self.SetSizer(self.sbs) + + + def setStaticText(self, msg:str): + self.staticText1.SetLabel(msg) + + \ No newline at end of file diff --git a/mypath.py b/mypath.py new file mode 100644 index 0000000..675a694 --- /dev/null +++ b/mypath.py @@ -0,0 +1,277 @@ +from pathlib import PurePath, Path + +# from myconfig import NEWLINE,TOKEN,SEPARATOR +""" +""" +class MyDir(object): + """ + 操作方法:设置base tuple_dir header + 设置的是路径, 文件名要 ifNotNewFile 传入 + 调用方法: + self.mydir.setBaseDir(path) + self.mydir.newDirIfNot() + self.mydir.newFileIfNot(file_name) + + self.mydir.setHeader(header_list, TOKEN, header_str) + if self.mydir.checkHeader() == 0: + self.mydir.writeHeader() + if self.mydir.checkHeader() == -1: + pass + self.mydir.setContent(header_list, TOKEN, header_str) + self.mydir.writeContent() + """ + + def __init__(self) -> None: + self.base_dir = Path() + self.dir_tuple = () + self.header = [] + self.header_str = "" + self.content = [] + self.content_str = "" + self.current_dir = None + self.current_filepath = None + pass + + def getDir(self,): + return self.current_dir + pass + + def setBaseDir(self, dir: Path): + self.base_dir = dir + self.current_dir = self.base_dir + pass + + def setDir(self, t:tuple=()): + self.dir_tuple = t + if len(self.dir_tuple) == 0 : + self.current_dir = self.base_dir + else: + self.current_dir = self.base_dir.joinpath( *t ) + pass + + def getDirFromBaseAndTuple(self, base_dir:Path, dir_tuple: tuple): + '''外部调用返回路径''' + ret_path = base_dir + t = dir_tuple + if len(t) == 0 : + ret_path = ret_path + else: + ret_path = ret_path.joinpath( *t ) + return ret_path + pass + + def setHeader(self, headerlist:list, headerSeperator: str = ";", headerinfo: str = None): + header_str = "" + if len(headerlist) == 0: + return + if headerinfo != None: + header_str = headerinfo + headerSeperator + for hl in headerlist: + header_str = header_str + str(hl) + headerSeperator + self.header_str = header_str[:-1] + pass + + def setContent(self, contentlist: list, contentSeperator: str = ";", contentinfo: str = None): + content_str = "" + if len(contentlist) == 0: + return + if contentinfo != None: + content_str = contentinfo + contentSeperator + tmp_str = "" + for cl in contentlist: + tmp_str = tmp_str + str(cl) + contentSeperator + self.content_str = content_str + tmp_str[:-1] + pass + + def newDirIfNot(self,) -> None: + # self.current_path = self.base_path.joinpath(self.path_tuple) + self.current_dir.mkdir(parents=True, exist_ok=True) + pass + + def newFileIfNot(self, fname: str) -> None: + self.newDirIfNot() + self.current_filepath = self.current_dir.joinpath(fname) + if not self.current_filepath.exists(): + with open(self.current_filepath, 'a') as f: + pass + return + pass + + def getCurrentFileSize(self,): + return self.current_filepath.stat().st_size + + def getFirstline(self,): + first_line = "" + with open(self.current_filepath, 'r') as f: # 打开文件 + first_line = f.readline() # 取第一行 + return first_line.strip('\n').strip('\r') + + def checkHeader(self,) -> int: + ''' + 返回: + 0 : 文件为空,可以直接写header + 1 : header对应上 无需处理 + -1: 需要提醒用户保存数据后,删除文件后再处理 + ''' + if self.getCurrentFileSize() == 0: + return 0 + first_line = self.getFirstline() + # print(f"firstline: {first_line}" ) + # print(f"header_str: {self.header_str}" ) + if first_line == self.header_str: + return 1 + return -1 + pass + + def writeHeader(self,) -> None: + with open(self.current_filepath, "a") as f: + f.write(self.header_str) + return None + pass + + def writeContent(self,new_line="\n") -> None: + with open(self.current_filepath, "a") as f: + f.write(new_line+self.content_str) + return None + pass + + def is_dir_empty(self, ): + '''文件夹是否为空''' + has_next = next(self.current_dir.iterdir(), None) + if has_next is None: + return True + return False + + def is_file_empty(self,): + '''文件是否为空''' + if self.current_dir.stat().st_size ==0: + return True + return False + + def deleteDir(self,): + '''文件夹是否为空''' + try: + if self.current_dir.exists(): + self.current_dir.rmdir() + except OSError as e: + raise Exception(e) + return True + + ## 其他需求 + def get_child_dir(self,) -> list: + ret = [] + tmp_dir = self.current_dir.glob("**/") + for td in tmp_dir: + if td.is_dir(): + ret.append(td.relative_to(self.current_dir)) + return ret + pass + + def get_child_dir_only(self,) -> list: + ret = [] + for d in self.current_dir.iterdir(): + if d.is_dir(): + ret.append(d.relative_to(self.current_dir)) + return ret + pass + + def get_files_from_currentdir(self, fmt:str="*/*" ) -> list: + '''fmt: * */* */*/*''' + ret = [] + tmp_dir = self.current_dir.glob(fmt) + print(tmp_dir) + for td in tmp_dir: + if td.is_file(): + ret.append(td) + return ret + pass + + def sort_dir_and_check( self, dirs:list ): + '''相对目录排序,目录最后一级''' + ret = [] + if len(dirs) == 0: + return ret + tmp = {} + tmp_lst = [] + for d in dirs: + last:str = d.parts[-1] + if last.isdigit() : + tmp.update( {last:d} ) + tmp_lst.append(int(last)) + pass + + tmp_lst.sort() + for t in tmp: + ret.append(tmp.get(str(t))) + pass + return ret + + + def sort_filepath_and_check(self, path_files:list): + '''相对目录排序,目录最后一级''' + ret = [] + if len(path_files) == 0: + return ret + tmp = {} + tmp_lst = [] + for d in path_files: + last:str = d.stem + if last.isdigit() : + tmp.update( {last:d} ) + tmp_lst.append(int(last)) + pass + + tmp_lst.sort() + for t in tmp: + ret.append(tmp.get(str(t))) + pass + return ret + + def group_and_sort_filepath(self,path_files:list): + ret = {} + # dirs_lst = [] + # len_files = len(path_files) + # if len_files == 0: + # return False + # for pf in path_files: + # pf_dir:str = pf.parts[-2] + # if pf_dir.isdigit() and int(pf_dir) not in dirs_lst: + # dirs_lst.append( int(pf_dir) ) + # dirs_lst.sort() + + + + + def check_dirs(self, dirs:list, begin:int =0, step:int=1): + '''检查目录是否从begin开始递增''' + len_dirs = len(dirs) + if len_dirs == 0: + return False + for i in range(begin,len_dirs,step) : + if dirs[i].parts[-1] != str(i) : + return False + return True + + def check_path_files(self,path_files:list,begin:int =0, step:int=1): + '''检查文件名从begin开始递增''' + len_files = len(path_files) + if len_files == 0: + return False + for i in range(begin,len_files,step) : + if path_files[i].stem != str(i) : + return False + return True + +if __name__ == "__main__": + mp = MyDir() + mp.setBaseDir(Path()) + print(mp.current_dir) + # t = ("test_dir","1","11") + t = ("test_dir", ) + mp.setDir( t ) + print(mp.current_dir) + + cd = mp.get_child_dir_only() + c = mp.sort_dir_and_check(cd) + print(cd ) + print(c ) diff --git a/mythread.py b/mythread.py new file mode 100644 index 0000000..b2ba0e1 --- /dev/null +++ b/mythread.py @@ -0,0 +1,126 @@ +import threading +import time + +class Mythead(threading.Thread): + '''线程守护''' + def __init__(self ): + super(Mythead, self).__init__() + pass + + def set_task(self, func, *args): + self.func = func + self.args = args + + def run(self): + # print(f" --- {len(self.args)}") + if len(self.args) > 0: + self.func(self.args) + else: + self.func( ) + +class Multithread(threading.Thread): + ''' + 多线程 + 子线程.join() -> ( 设置在start之后, 等所有阻塞线程运行完, 再运行主线程 ) + 子线程.setDaemon(True) -> 设置子线程A为守护线程, 主线程所在的进程内所有非守护线程统统运行完毕, + 无论子线程A有没有结束, 程序都结束 + Method: + + ''' + def __init__(self): + super(Multithread, self).__init__() + self.__tasks = [] + self.act = [] + # self.__block = False + pass + + # def set_task( self, tasks ): + # self.__tasks = tasks + + def add_task(self, func, daemon=False, join=True,args=()): + tmp_dict = {} + tmp_dict.update( {"func" : func}) + if daemon == True: + tmp_dict.update( {"daemon" : True}) + else: + tmp_dict.update( {"daemon" : False}) + if join == True: + tmp_dict.update( {"join" : True}) + else: + tmp_dict.update( {"join" : False}) + if args == (): + tmp_dict.update( {"args" : ()}) + else: + tmp_dict.update( {"args" : args}) + self.__tasks.append( tmp_dict ) + + def remove_tasks(self, ): + self.__tasks = [] + self.act = [] + + def add_task_2_act(self, task): + t = threading.Thread( target = task['func'], args = task['args'] ) + self.act.append(t) + t.start() + + def execute_one_act(self,i): + if self.__tasks[i]['join']: + self.act[i].join() # 子线程阻塞完毕再运行主线程 + pass + + def prepare_tasks(self): + self.act = [] + for task in self.__tasks: + self.add_task_2_act(task) + + def execute_tasks(self): + try: + for i in range( len(self.act) ): + self.execute_one_act( i ) + pass + except Exception as e: + print(e) + + def prepare_tasks(self): + self.act = [] + for task in self.__tasks: + t = threading.Thread( target = task['func'], args = task['args'] ) + self.act.append(t) + t.start() + + def simultaneously_execute_tasks(self): + self.prepare_tasks() + self.execute_tasks() + + def sequently_execute_tasks(self): + for task in self.__tasks: + t = threading.Thread( target = task['func'], args = task['args'] ) + t.start() + t.join() + + + def t1(self): + print("thread1...") + time.sleep(10) + print("thread1... after sleep...") + + def t2(self): + print("thread2...") + time.sleep(5) + print("thread2... after sleep...") + + def t3(self): + print("thread3...") + time.sleep(3) + print("thread3... after sleep...") + +if __name__ == '__main__': + mt = Multithread() + mt.add_task(mt.t1) + mt.add_task(mt.t2) + mt.add_task(mt.t3) + # mt.prepare_tasks() # 线程同步运行 + # mt.execute_tasks() + # mt.simultaneously_execute_tasks() + mt.sequently_execute_tasks() + diff --git a/mytime.py b/mytime.py new file mode 100644 index 0000000..ec7b4b2 --- /dev/null +++ b/mytime.py @@ -0,0 +1,71 @@ +from datetime import datetime, timedelta +# import locale +# locale.setlocale(locale.LC_ALL, '') + +TIME_STR = "2022-06-10 16:16:16" +STD_TIME_STR_FMT = "%Y-%m-%d %H:%M:%S" # 小写y是两位年份 +CUR_TIME_STR_FMT = "%Y-%m-%d %H:%M:%S" + + +class MyTime(object): + """ + 操作方法:设置base tuple_path header + 调用方法 + self.mytime = Mytime() + self.mytime.setCurrentTimeStrFmt() + print(self.mytime.cur_datetime) + s + """ + + def __init__(self) -> None: + self.cur_time_str_fmt = "%Y-%m-%d %H:%M:%S" + self.std_time_str_fmt = "%Y-%m-%d %H:%M:%S" + self.cur_time_str = "" + self.std_time_str = "" + self.cur_datetime = "" + pass + + def setCurrentTimeStrFmt(self, s): + self.cur_time_str_fmt = s + pass + + def setStdTimeStrFmt(self, s): + self.std_time_str_fmt = s + pass + + def setCurrentTimeStr(self, s): + self.cur_time_str = s + self.cur_datetime = datetime.strptime(self.cur_time_str, self.cur_time_str_fmt) + pass + + def setStdTimeStr(self, s): + self.std_time_str = s + self.cur_datetime = datetime.strptime( + self.std_time_str, STD_TIME_STR_FMT) + pass + + def Current2STD(self): + # self.cur_datetime = datetime.strptime(self.cur_time_str , CUR_TIME_STR_FMT) + self.std_time_str = datetime.strftime( + self.cur_datetime, STD_TIME_STR_FMT) + pass + + def STD2Current(self, format: str): + # self.cur_datetime = datetime.strptime(self.std_time_str , STD_TIME_STR_FMT) + self.cur_time_str = datetime.strftime( + self.cur_datetime, CUR_TIME_STR_FMT) + pass + + def timeDelta(self, days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0): + self.cur_datetime = self.cur_datetime + \ + timedelta(days=0, seconds=0, microseconds=0, + milliseconds=0, minutes=0, hours=0, weeks=0) + pass + + +if __name__ == "__main__": + s = "2023-02-07 14:02:46" + mt = MyTime() + mt.setCurrentTimeStr(s) + print(mt.cur_datetime) + pass diff --git a/readcal.py b/readcal.py new file mode 100644 index 0000000..7a00e66 --- /dev/null +++ b/readcal.py @@ -0,0 +1,1020 @@ +from mylogger import log +from myexception import MyException +from typing import Tuple,List,Optional,Union,Callable +from pathlib import Path, PurePath +from myconfig import MyConfig,DeviceType,FILE_MARK,CURRENT_DIR,CAL_DIR,DATA_DIR,SAVE_EXT_NAME,\ + INTERVAL,SEPARATOR + +class ReadCal(): + def __init__(self) -> None: + pass + + # 数据加时间值 + @staticmethod + def read_columns_set_by_mark(fpath:Path, mark:list, *column ) -> Tuple[str,List] : + # def read_column_1set_by_mark(fpath:str, column:int, *args ) -> Tuple[ str, List ] : + ''' + return: time:str List + mark : ['Spectrum','DATA'] + default end with "[END]" + column参数直接写,如: 0,1,2 + ''' + log.info(f"read_column_1set_by_mark : \ + {fpath} , mark:{mark} , column:{column}", __name__, "", "") + + # 处理mark args[0] = Spectrum + if len(mark) != 2: + log.error( f"read_column_1set_by_mark() wrong args ",__name__, "", "" ) + raise MyException( f"read_column_1set_by_mark() wrong args " ) + + if len(column) == 0: + log.error(f"read_column_1set_by_mark(), no column para, pls input column ",__name__, "", "" ) + raise MyException( f"read_column_1set_by_mark() , pls input column " ) + + if len( mark ) == 0: + mark_1 = '[Spectrum]' + mark_2 = '[DATA]' + + mark_1 = '['+ mark[0] +']' + mark_2 = '['+ mark[1] +']' + res = [] + sn = ReadCal.readFileSNbyIDDevice(fpath) + # 预备返回数据结构 + # res_time = [] + res_data = [] + columnLen = len(column) + for i in range(columnLen): + res_data.append( [] ) + + with fpath.open('r') as f_handle: + rflag = 0 + # res = [] + # res_time = [] + # res_data = [] + + for line in f_handle: + if mark_1 in line and rflag == 0: + log.debug(f" find {mark_1}", __name__, "", "" ) + rflag += 1 + continue + + if mark_2 in line and rflag > 3 : + log.debug(f" find {mark_1} end ", __name__, "", "" ) + rflag = 0 + continue + + # 获取时间 + if rflag == 1 : + data = line.strip('\n').strip(' ').split('=') + if data[0].strip() == "DateTime" : + log.debug(f" find {mark_1} -> DateTime {data[1]} ", __name__, "", "" ) + time_ = data[1].strip() + rflag += 1 + continue + + if rflag == 2 and ( mark_2 in line ) : + log.debug(f" find {mark_2} -> ", __name__, "", "" ) + rflag += 1 + continue + + if rflag == 3 : + if mark_2 not in line: + # log.debug(f" get data {line}", __name__, "", "" ) + data = line.strip('\n').strip(' ').split(' ') + # 忽略第一行,第一行0开头,保存积分时间的 + if data[0].strip() == "0" : + continue + else: + # if data[1] != "-NAN" and data[1] != "NAN" and data[1] != "+NAN" : + # 处理多列 + for i in range(columnLen): + # res_time.append( time_ ) + # print(f" ==== {data}") + res_data[i].append( data[column[i]] ) + continue + + if rflag == 3 and ( mark_2 in line ) : + log.debug(f" find {mark_2} end , line: {line} ", __name__, "", "" ) + rflag += 1 + continue #需要继续让其找到 + + if rflag == 4: + log.debug(f" job done......", __name__, "", "" ) + res_time = time_ + # res_data.append( res ) + # 只读一组数据就 break + rflag += 1 + # res = [] + # rflag = 0 + + if rflag == 5: + log.debug(f" job done, break...", __name__, "", "" ) + break + return ( res_time, res_data) + pass + + # 数据加时间值 + @staticmethod + def read_columns_sets_by_mark(fpath:Path, mark:list, *column + ) -> Tuple[List[str],List[List]] : + # def read_column_1set_by_mark(fpath:str, column:int, *args ) -> Tuple[ str, List ] : + ''' + @desc: 获取多列数据,且为多套数据,非单套数据 + @return: + res_time + ['2011-01-28 00:00:32', '2011-01-28 00:01:04', '2011-01-28 00:04:05', '2011-01-28 00:04:17'] + res_data [ [[,,,]], [[,,,]], [[,,,]], [[,,,]]] + 取 res_data[0] + @args : ['Spectrum','DATA'] + default end with "[END]" + ''' + log.info(f"read_column_1set_by_mark : \ + {fpath} , mark:{mark} , column:{column}", __name__, "", "") + + # 处理mark args[0] = Spectrum + if len(mark) != 2: + log.error( f"read_columns_sets_by_mark() wrong args ",__name__, "", "" ) + raise MyException( f"read_columns_sets_by_mark() wrong args " ) + + if len(column) == 0: + log.error(f"read_columns_sets_by_mark(), no column para, pls input column ",__name__, "", "" ) + raise MyException( f"read_columns_sets_by_mark() , pls input column " ) + + if len( mark ) == 0: + mark_1 = '[Spectrum]' + mark_2 = '[DATA]' + + mark_1 = '['+ mark[0] +']' + mark_2 = '['+ mark[1] +']' + res = [] + sn = ReadCal.readFileSNbyIDDevice(fpath) + # 预备返回数据结构 + res_data = [] + res_time = [] + res = [] + columnLen = len(column) + for i in range(columnLen): + # res_time.append( [] ) + res.append( [] ) + + with fpath.open('r') as f_handle: + rflag = 0 + + for line in f_handle: + if mark_1 in line and rflag == 0: + log.debug(f" find {mark_1}", __name__, "", "" ) + rflag += 1 + continue + + if mark_2 in line and rflag > 3 : + log.debug(f" find {mark_1} end ", __name__, "", "" ) + rflag = 0 + continue + + # 获取时间 + if rflag == 1 : + data = line.strip('\n').strip(' ').split('=') + if data[0].strip() == "DateTime" : + log.debug(f" find {mark_1} -> DateTime {data[1]} ", __name__, "", "" ) + time_ = data[1].strip() + rflag += 1 + continue + + if rflag == 2 and ( mark_2 in line ) : + log.debug(f" find {mark_2} -> ", __name__, "", "" ) + rflag += 1 + continue + + if rflag == 3 : + if mark_2 not in line: + # log.debug(f" get data {line}", __name__, "", "" ) + data = line.strip('\n').strip(' ').split(' ') + # 忽略第一行,第一行0开头,保存积分时间的 + if data[0].strip() == "0" : + continue + else: + # if data[1] != "-NAN" and data[1] != "NAN" and data[1] != "+NAN" : + # 处理多列 + for i in range(columnLen): + # res_time.append( time_ ) + res[i].append( data[column[i]] ) + continue + + if rflag == 3 and ( mark_2 in line ) : + log.debug(f" find {mark_2} end , line: {line} ", __name__, "", "" ) + rflag += 1 + continue #需要继续让其找到 + + if rflag == 4: + log.debug(f" job done......", __name__, "", "" ) + res_time.append( time_ ) + res_data.append( res ) # 可能导致不同组数据拼接起来???? + rflag += 1 + # res = [] + # rflag = 0 + + if rflag == 5: + log.debug(f" job done, break...", __name__, "", "" ) + rflag = 0 + continue + + log.debug(f" res.time len {len(res_time)} , \ + res.data len {len(res_data)} , ", __name__, "", "" ) + + return res_time, res_data + + # 数据加时间值 + @staticmethod + def read_columns_sets_by_mark_callback(fpath:Path, mark:list, callback:Callable, *column ) : + ''' + @desc: 获取多列数据,且为多套数据,非单套数据 + @return: + res_time + ['2011-01-28 00:00:32', '2011-01-28 00:01:04', '2011-01-28 00:04:05', '2011-01-28 00:04:17'] + res_data [ [[,,,]], [[,,,]], [[,,,]], [[,,,]]] + 取 res_data[0] + @args : ['Spectrum','DATA'] + default end with "[END]" + ''' + log.debug(f"read_column_1set_by_mark : \ + {fpath} , mark:{mark} , column:{column}", __name__, "", "") + + # 处理mark args[0] = Spectrum + if len(mark) != 2: + log.error( f"read_columns_sets_by_mark() wrong args ",__name__, "", "" ) + raise MyException( f"read_columns_sets_by_mark() wrong args " ) + + if len(column) == 0: + log.error(f"read_columns_sets_by_mark(), no column para, pls input column ",__name__, "", "" ) + raise MyException( f"read_columns_sets_by_mark() , pls input column " ) + + if len( mark ) == 0: + mark_1 = '[Spectrum]' + mark_2 = '[DATA]' + + mark_1 = '['+ mark[0] +']' + mark_2 = '['+ mark[1] +']' + + # 预备返回数据结构 + res_data = [] + res_time = [] + res = [] + sn = ReadCal.readFileSNbyIDDevice(fpath) + + columnLen = len(column) + for i in range(columnLen): + # res_time.append( [] ) + res.append( [] ) + + with fpath.open('r') as f_handle: + rflag = 0 + + for line in f_handle: + if mark_1 in line and rflag == 0: + log.debug(f" find {mark_1}", __name__, "", "" ) + rflag += 1 + continue + + if mark_2 in line and rflag > 3 : + log.debug(f" find {mark_1} end ", __name__, "", "" ) + rflag = 0 + continue + + # 获取时间 + if rflag == 1 : + data = line.strip('\n').strip(' ').split('=') + if data[0].strip() == "DateTime" : + log.debug(f" find {mark_1} -> DateTime {data[1]} ", __name__, "", "" ) + time_ = data[1].strip() + rflag += 1 + continue + + if rflag == 2 and ( mark_2 in line ) : + log.debug(f" find {mark_2} -> ", __name__, "", "" ) + rflag += 1 + continue + + if rflag == 3 : + if mark_2 not in line: + # log.debug(f" get data {line}", __name__, "", "" ) + data = line.strip('\n').strip(' ').split(' ') + # 忽略第一行,第一行0开头,保存积分时间的 + if data[0].strip() == "0" : + continue + else: + # if data[1] != "-NAN" and data[1] != "NAN" and data[1] != "+NAN" : + # 处理多列 + for i in range(columnLen): + res[i].append( data[column[i]] ) + continue + + if rflag == 3 and ( mark_2 in line ) : + log.debug(f" find {mark_2} end , line: {line} ", __name__, "", "" ) + rflag += 1 + continue #需要继续让其找到 + + if rflag == 4: + log.debug(f" job done......", __name__, "", "" ) + # callable , not return。 每读出一组就回调,不建议。频繁读写硬盘 + # callback(time_, res) + res_time.append( time_ ) + res_data.append( res ) + rflag += 1 + # res = [] + # rflag = 0 + + if rflag == 5: + log.debug(f" job done, break...", __name__, "", "" ) + rflag = 0 + continue + + # callable , not return。 一个文件读完直接处理 + + callback(sn, res_time, res_data) + + # res_time ['2011-01-28 00:00:32', '2011-01-28 00:01:04', '2011-01-28 00:04:05', '2011-01-28 00:04:17'] + # res_data [ [[,,,]], [[,,,]], [[,,,]], [[,,,]]] 取 res_data[0] + log.debug(f" res.time len {len(res_time)} , \ + res.data len {len(res_data)} , ", __name__, "", "" ) + + # return ( res_time, res_data) + + @staticmethod + def readDataIPinfo(fpath:Path, mark:list, callback:Callable ): + ''' + SAMIP sensor ,Inclination Pressure, InclX InclY Pressure + ''' + log.debug(f"readDataIPinfo : {fpath} , mark:{mark} , ", __name__, "", "") + + # 处理mark args[0] = Spectrum + if len(mark) != 2: + log.error( f"readDataIPinfo() wrong args ",__name__, "", "" ) + raise MyException( f"readDataIPinfo() wrong args " ) + + if len( mark ) == 0: + mark_1 = '[Spectrum]' + mark_2 = '[DATA]' + + mark_1 = '['+ mark[0] +']' + + # 预备返回数据结构 + res_data = [] + res_time = [] + res = [] + tags = ['InclX' , 'InclY', 'Pressure'] + + with fpath.open('r') as f_handle: + rflag = 0 + for line in f_handle: + if mark_1 in line and rflag == 0: + log.debug(f" find {mark_1}", __name__, "", "" ) + rflag += 1 + continue + if mark_1 in line and rflag > 5: + log.debug(f" find {mark_1} end", __name__, "", "" ) + rflag = 0 + continue + # 获取时间 + if rflag == 1 : + data = line.strip('\n').strip(' ').split('=') + if data[0].strip() == "DateTime" : + log.debug(f" find {mark_1} -> DateTime {data[1]} ", __name__, "", "" ) + time_ = data[1].strip() + rflag += 1 + continue + if rflag == 2: + if "[" not in line : + data = line.strip('\n').strip(' ').split('=') + # RAMSES 数据通过MethodName 获得传感器序列号 + if data[0].strip() in tags : + res.append( data[1].strip(' ') ) + rflag += 1 + if rflag == 5: + res_time.append(time_) + res_data.append(res) + rflag = 0 + pass + callback(res_time,res_data) + return (res_time,res_data) + + @staticmethod + def readSamSNFromIni( fpath:Path ): + """ + @description : 依据文件路径获得samsn, 兼容 SAM SAMIP传感器 + """ + + with fpath.open('r') as f_handle: + for line in f_handle: + # IDDevice = SAM_85AF + ln = line.strip('\n').strip(' ').split('=') + if ln[0].strip() == "IDDevice": + if ln[1].strip().split('_')[0] == "SAM": + return ln[1].strip().split('_')[1] + return None + pass + + @staticmethod + def readIPCalFromIni( fpath:Path ): + """ + @description : 依据文件路径获得IPCal IP标定信息 + """ + ipcal = {} + with fpath.open('r') as f_handle: + flag = 0 + for line in f_handle: + # IDDevice = SAM_85AF + ln = line.strip('\n').strip(' ').split('=') + + if flag == 0 and ln[0].strip() == "IDDevice": + if ln[1].strip().split('_')[0] == "IP": + ipcal["IPSN"] = ln[1].strip().split('_')[1] + flag += 1 + continue + + if flag == 1 and "[" in line: + flag += 1 + continue + + if flag == 2: + if "[" in line: + flag = flag + 1 + + if not "[" in line: + line_ = line.strip('\n').strip(' ').split('=') + ipcal.update({line_[0].strip():line_[1].strip()}) + + if flag == 3: + break + + return ipcal + + @staticmethod + def readSAMCalFromIni( fpath:Path ): + """ + @description : 依据文件路径获得SAMCal SAM标定信息 + """ + samcal = {} + with fpath.open('r') as f_handle: + flag = 0 + for line in f_handle: + # IDDevice = SAM_85AF + line_ = line.strip('\n').strip(' ').split('=') + if flag == 0 and line_[0].strip() == "IDDevice": + if line_[1].strip().split('_')[0] == "SAM": + samcal["SAMSN"] = line_[1].strip().split('_')[1] + flag += 1 + continue + + if flag == 1 and "[" in line: + flag += 1 + continue + + if flag == 2: + if "[" in line: + flag = flag + 1 + + if not "[" in line: + line_ = line.strip('\n').strip(' ').split('=') + samcal.update({line_[0].strip():line_[1].strip()}) + + if flag == 3: + break + return samcal + + @staticmethod + def readFileSNbyIDDevice(fpath:Path): + sn_from_file = '' + with fpath.open('r') as f_handle: + rflag = 0 + for line in f_handle: + if '[Spectrum]' in line and '[END]' not in line and rflag == 0: + rflag += 1 + pass + if rflag == 1: + data = line.strip('\n').strip(' ').split('=') + # RAMSES 数据通过MethodName 获得传感器序列号 + if data[0].strip() == "IDDevice": + sn_from_file = data[1].strip(' ').split('_')[1] + break + return sn_from_file + + @staticmethod + def readDatafileSNbyMethodName(fpath:Path): + ''' + SAMIP SAM的数据文件中, MethodName对应的值都是 SAM_{SAMSN} + 读SAMIP的数据,建议用 {SAMSN}的处理 + ''' + sn_from_file = '' + with fpath.open('r') as f_handle: + rflag = 0 + for line in f_handle: + if '[Spectrum]' in line and '[END]' not in line and rflag == 0: + rflag += 1 + pass + if rflag == 1: + data = line.strip('\n').strip(' ').split('=') + # RAMSES 数据通过MethodName 获得传感器序列号 + if data[0].strip() == "MethodName": + sn_from_file = data[1].strip(' ').split('_')[1] + break + return sn_from_file + + +if __name__ == "__main__": + log.info(f"******** main read *********", __name__, "", "") + + # path = PurePath() + # print(path) + + pass + + # def read_data_sn(self,fpath): + # with open(fpath, 'r') as f_handle: + # rflag = 0 + # for line in f_handle: + # if '[Spectrum]' in line and '[END]' not in line and rflag == 0: + # rflag += 1 + # pass + # if rflag == 1 : + # data = line.strip('\n').strip(' ').split('=') + # if data[0].strip() == "IDDevice" : + # return data[1].strip(' ').split('_')[1] + # pass + + # def read_data1(self,fpath): + # with open(fpath, 'r') as f_handle: + # rflag = 0 + # res = [] + # res_time = [] + # res_data = [] + + # for line in f_handle: + # if '[Spectrum]' in line and '[END]' not in line and rflag == 0: + # rflag += 1 + # pass + + # if '[Spectrum]' in line and '[END]' in line : + # rflag = 0 + # pass + + # # 获取时间 + # if rflag == 1 : + # data = line.strip('\n').strip(' ').split('=') + # if data[0].strip() == "DateTime" : + # time_ = data[1].strip() + # rflag += 1 + + # if rflag == 2 and ( '[DATA]' in line or '[Data]' in line ) : + # rflag += 1 + + # if rflag == 3 : + # data = line.strip('\n').strip(' ').split(' ') + + # if int(data[0].strip()) == 0 : + # pass + # else: + # # if data[1] != "-NAN" and data[1] != "NAN" and data[1] != "+NAN" : + + # res.append( float(data[1] ) ) + # if rflag == 3 and '[' in line and ']' in line: + # rflag += 1 + # if rflag == 4: + # # 这个地方 + # # self. __save_absorbance_data( res_time, res, sn ) + # res_time.append( time_ ) + # res_data.append( res ) + # # ?? 可以调用函数直接处理 + # # DealResult.deal_one_data(time_,res) + # res = [] + # rflag = 0 + # # return [['data']] + # pass + + + # def read_data_column( self,fpath, column=1 ): + # column_ = 1 + # if int(column_) : + # column_ = int(column_) + # pass + # else: + # pass + + # with open(fpath, 'r') as f_handle: + # rflag = 0 + # res = [] + # res_time = [] + # res_data = [] + + # for line in f_handle: + # if '[Spectrum]' in line and '[END]' not in line and rflag == 0: + # rflag += 1 + # pass + + # if '[Spectrum]' in line and '[END]' in line : + # rflag = 0 + # pass + + # # 获取时间 + # if rflag == 1 : + # data = line.strip('\n').strip(' ').split('=') + # if data[0].strip() == "DateTime" : + # time_ = data[1].strip() + # rflag += 1 + + # if rflag == 2 and ( '[DATA]' in line or '[Data]' in line ) : + # rflag += 1 + + # if rflag == 3 : + # data = line.strip('\n').strip(' ').split(' ') + + # if int(data[0].strip()) == 0 : + # pass + # else: + # res.append( float(data[column_] ) ) + # if rflag == 3 and '[' in line and ']' in line: + # rflag += 1 + # if rflag == 4: + # # 这个地方 + # # self. __save_absorbance_data( res_time, res, sn ) + # # res_time.append( time_ ) + # # res_data.append( res ) + # # ?? 可以调用函数直接处理 + # return time_, res + + # # return [['data']] + # pass + + # def read_data_wl( self, fpath ): + # wl = self.read_data_column( fpath, column=0 ) + # pass + + # def get_cal_file(self,sn): + # sn_ = sn + # file_ = {} + # if open( os.path.join( CAL_PATH, "SAM_"+sn_+"ini" ),"r"): + # file_ = { + # "type": "SAM", + # "back":"Back_SAM_", + # "cal":"Cal_SAM_", + # "calaq":"CalAQ_SAM_", + # "ini":"SAM_", #ini + # "immersion":"immersion_factors_Lu.DAT" + # } + # return file_ + # if open( os.path.join( CAL_PATH, "SAMIP_"+ sn_ +"_ALL.ini" ),"r"): + # file_ = { + # "type": "SAMIP", + # # "back":"Back_SAM_" + sn_ + CAL_EXT_NAME, + # # "cal":"Cal_SAM_" + sn_ + CAL_EXT_NAME, + # # "calaq":"CalAQ_SAM_" + sn_ + CAL_EXT_NAME, + # "ini":"SAMIP_"+sn+"_ALL.ini", #ini + # "immersion":"immersion_factors_Lu.DAT" + # } + # if file_['ini'] : + # samsn = self.read_ini(file_['ini'], "SAMSN") + # file_.update("cal", "Cal_SAM_" + samsn + CAL_EXT_NAME) + # file_.update("calaq", "CalAQ_SAM_" + samsn + CAL_EXT_NAME) + # file_.update("back", "Back_SAM_" + samsn + CAL_EXT_NAME) + # return file_ + # return + + # def read_cal(self,sn): + # # SAM SAMIP 不同 + # self.cal_data= {} + # # 1. 依据序列号读 ini, 判读是否有文件 SAM_8578.ini SAMIP_50BB_ALL.ini + # self.calfile = self.get_cal_file(sn) # 其中sam的是错误的 + + # # 2 读ini 文件错误 + + # cal_data = {} + # for key in self.calfile: + # if key == "immersion" : + # path_ = os.path.join( CAL_PATH, self.calfile[key] ) + # content_ = [self.read_data_column( path_, column=0 )[1]] + # content_.append( self.read_data_column( path_, column=0 )[1] ) + # cal_data.update({key:content_}) + + # if key == "cal" : + + # path_ = os.path.join( CAL_PATH, self.calfile[key] ) + # content_ = self.read_data_column( path_, column=0 ) + # cal_data.update({key:content_}) + + # if key == "back" : + # path_ = os.path.join( CAL_PATH, self.calfile[key] ) + # content_ = self.read_data_column( path_, column=0 ) + # cal_data.update({key:content_}) + + # if key == "calaq" : + # path_ = os.path.join( CAL_PATH, self.calfile[key] ) + # content_ = self.read_data_column( path_, column=0 ) + # cal_data.update({key:content_}) + + # if key == "ini" : + # cal_data.update({ "samcal" : self.read_ini( os.path.join( CAL_PATH, self.calfile[key] ), "SAMCAL" ) }) + # cal_data.update({ "ipcal" : self.read_ini( os.path.join( CAL_PATH, self.calfile[key] ), "IPCAL" ) }) + + # pass + + # DealResult.deal_cal(cal_data) + + # pass + + # def read_data(self,fname,lst): + # """ + # @description : 线程守护读取数据文件 ,循环读取 + # 考虑一次读取多组,只读一列的情况 + # sn ,begin,end, 指定读的列 + # 返回:[ [[第一组时间],[第二组时间] .... ], [ [第一组data],[第二组data] ...] ] + # RAMSES 要考虑 : InclX = -6.42, InclY = -6.5625 , Pressure = 6.61394049205538 + # 需要读一组波长出来 + # """ + # log.info( ":::::::::::: Class : %s -> Function :__read_data " % ( __name__, ) ) + # log.info( " __read_data : lst %s" % ( lst, ) ) + # sn = lst[0] + # begin = lst[1] + # end = lst[2] + # column = lst[3] + # samip_sn= lst[4] + + # # 检查 sn--- 不检查sn ,读数据就 成csv + + # # 读取一组数据的0列作为波长??? + + # # if is_sn_ok : + + # log.info( "正在处理文件 .... " + fname ) + # with open(fname, 'r') as f_handle: + # time_ = "" + # rflag = 0 + # intlx = 0.0 + # intly = 0.0 + # pressure = 0.0 + # res = [] + # res_time = [] + # res_data = [] + + # for line in f_handle: + # if rflag == 0 and '[Spectrum]' in line and '[END]' not in line : + # rflag += 1 + # pass + + # if '[Spectrum]' in line and '[END]' in line : + # rflag = 0 + # pass + + # # 获取时间, InclX, InclY ,Pressure + # if rflag == 1 : + # data = line.strip('\n').strip(' ').split('=') + # if data[0].strip() == "DateTime" : + # time_ = data[1].strip() + # rflag += 1 + # # InclX, InclY ,Pressure + + # if rflag == 2: + # data = line.strip('\n').strip(' ').split('=') + + # if data[0].strip() == "InclX" : + # intlx = data[1].strip() + + # if data[0].strip() == "InclY" : + # intly = data[1].strip() + + # if data[0].strip() == "Pressure" : + # pressure = data[1].strip() + + + # # DATA set 结束添加数据 + # if rflag == 4 and '[DATA]' in line and '[END]' in line: + # # time.sleep(10) + # res_time.append( [time_,intlx,intly,pressure] ) + # res_data.append( res ) + # res = [] + # rflag += 1 + + # if rflag == 3 : + # data = line.strip('\n').strip(' ').split(' ') + # # print("rflag %s +++++++++++++++++++++++++++++++++ %s" %(rflag,data) ) + # if data[0] != "0" and data[1] != "-NAN" and data[1] != "NAN" and data[1] != "+NAN" : #去掉第一行 0, 对应的积分时间 2^(n+1) + # # print("append %s -- %s" %(data[0],data[1]) ) + # res.append( float( data[column-1] ) ) + # if data[0] != "0" and float(data[0]) > 950 : + # # print("> 950... %s %s" %(data[0],data[1]) ) + # rflag += 1 + + # # 处理data 部分 + # if rflag == 2 and '[DATA]' in line and '[END]' not in line: + # # print("rflag %s +++++++++++++++++++++++++++++++++ data+1 " %(rflag,) ) + # rflag += 1 + + + # if rflag == 5: + # DealResult.deal_ramses_data(time_, [[intlx,intly,pressure], res]) + # # 这个地方 + # # self. __save_absorbance_data( res_time, res, sn ) + # # print("rflag 4 ......................") + # # res_time.append( [time_,intlx,intly,pressure] ) + # # print(" append time %s " %res_time) + # # res_data.append( res ) + # res = [] + # rflag = 0 + # intlx = 0.0 + # intly =0.0 + # pressure =0.0 + # # else: + # # return [] + + # log.info( "已经转换完文件,正在保存... " + fname ) + + # # 分析处理数据,还是返回原始数据 或空 ?? + # log.info( " Function :__read_data %s - %s " % ( res_time[0] ,res_data[0] ) ) + + + # # # 光强保存文件路径 + # # fpath = os.path.join(INTENSITY_PATH, samip_sn + SAVE_EXT_NAME ) + # # fpath_IP = os.path.join(INTENSITY_PATH, samip_sn + "_IP" + SAVE_EXT_NAME ) + + # # for i in range ( len(res_time) ) : + # # # print("1111111111..............%s %s " %(res_time[i],res_time[i][0]) ) + # # # time.sleep(2) + # # ProcessFile.save_time_list( str(res_time[i][0]) , res_data[i], TOKEN, fpath ) + # # # 不是samip 不保存 IP 文件 + # # if sn != samip_sn: + # # ProcessFile.save_time_list( str(res_time[i][0]) , res_time[i][1:], TOKEN, fpath_IP ) + + + # # log.info( "保存结束 ... " + fname ) + + # # 返回 ok 表示文件处理结束 + # return + # pass + + # def read_ini(self,fname ,type_): + # """ + # @description : 三个不同任务, SAM SN, SAM ATTR, IP ATTR + # 分别记为 SAMSN SAMCAL IPCAL + # """ + # log.info( " RAMSES __read_ini -> lst -> %s " % type_) + # typ = type_ + # data = [] + + # if typ == "SAMSN" : + + # with open(fname, 'r') as f_handle: + # for line in f_handle: + # # IDDevice = SAM_85AF + # ln = line.strip('\n').strip(' ').split('=') + # if ln[0].strip() == "IDDevice" : + # if ln[1].strip().split('_')[0] =="SAM" : + # return ln[1].strip().split('_')[1] + # pass + + # if typ == "SAMCAL" : + # samcal= {} + # with open(fname, 'r') as f_handle: + # flag = 0 + # for line in f_handle: + # # IDDevice = SAM_85AF + # line_ = line.strip('\n').strip(' ').split('=') + # if flag == 0 and line_[0].strip() == "IDDevice" : + # if line_[1].strip().split('_')[0] =="SAM" : + # samcal["SAMSN"] = line_[1].strip().split('_')[1] + # flag += 1 + + # if flag == 2 and "[END]" in line: + # flag += 1 + + # if flag == 2: + # # print(" 1 %s %s %s" % (fname,line_[0],line_[1])) + # samcal[line_[0]] = line_[1] + + # if flag == 1 and line_[0].strip() == "[ATTRIBUTES]" : + # flag += 1 + + # if flag == 2 and "[END]" in line: + # flag += 1 + + # return samcal + + # pass + + # if typ == "IPCAL" : + # ipcal= {} + # with open(fname, 'r') as f_handle: + # flag = 0 + # for line in f_handle: + # # IDDevice = SAM_85AF + # ln = line.strip('\n').strip(' ').split('=') + + # if flag == 0 and ln[0].strip() == "IDDevice" : + # if ln[1].strip().split('_')[0] =="IP" : + # ipcal["IPSN"] = ln[1].strip().split('_')[1] + # flag += 1 + + # if flag == 2 and "[END]" in line: + # flag += 1 + + # if flag == 2: + # ipcal[ln[0]] = ln[1] + + # if flag == 1 and ln[0].strip() == "[ATTRIBUTES]" : + # flag += 1 + + # return ipcal + + # return + # pass + + # def read_raw( self, fname , lst, uiraw): + # """ + # @description : 三个不同任务, SAM SN, SAM ATTR, IP ATTR + # 对波长进行标定处理 + # 并存入文件 + # λ(N) = C0s + C1s·N + C2s· N2 + C3s·N3 + # """ + + # sep = uiraw["1"] + # air_water = int(uiraw["2"]) + + # with open(fname, 'r') as f_handle: + # sn = "" + # wl = "" + # is_samip = 0 + # # data = data[2:] + # # cal_data = lst[sn] + # wl_cal = [] + # cal_data = [] + # intg_time = 128 + # ip_cal = [] + # cal = [] + # calaq = [] + # b0 = [] + # b1 = [] + + # for line in f_handle: + # data = line.split(",") + # sn_d = data[0] + + # if sn_d != sn : + # sn = sn_d + # intg_time = int( data[1] ) + # cal_data = lst[sn] + # # 判断sam SAMIP + # if cal_data[0][0] != cal_data[0][1] : + # is_samip = 1 + + # wl_cal = cal_data[1] + # ip_cal = cal_data[2] + + # if air_water == 1 : + # cal = cal_data[3] + # else: + # cal = cal_data[2] + + # b0 = cal_data[4] + # b1 = cal_data[5] + + # for i in range(1,256): + # temp = float(wl_cal["C0s"]) + \ + # float(wl_cal["C1s"]) * i + \ + # float(wl_cal["C2s"]) * i * i + \ + # float(wl_cal["C3s"]) * i *i *i + # wl.append(temp) + + + + # # 处理数据 + # data = data[2:] + # intensity = [] + # Cn = [] + + # for i in range( 255 ): + # # NAN 为 0 + # # if cal[i] = "+NAN": + # # intensity.append(0) + # # else: + # Mn = data[i] / 65535 + # Bn = float( b0[i] ) + float( b1[i] ) * intg_time / 8192 #积分时间比 + # Cn.append(Bn - Mn) + + # offset = 0 # DarkPixelStart = 237 DarkPixelStop = 254的平均值. 数组中236-254 + # for i in range( int( wl_cal['DarkPixelStart']) -1 , int( wl_cal['DarkPixelStop']) ): + # offset = offset + float( Cn[i] ) + # offset = offset/ ( int( wl_cal['DarkPixelStop']) - int( wl_cal['DarkPixelStart']) +1 ) + + # for i in range( 255 ): + # Dn = Cn[i] - offset + # En = 8192 * Dn / intg_time + + # # ???? Sn 来自 cal calaq 文件的部分 + # Sn = cal[i] + # intensity.append( En / Sn ) + + # # 还需要处理传感器的 IP + # if is_samip : + # # ip 数据过来后的格式 + # pass + + # return intensity + + # # 数据分别写到文件 diff --git a/retrieve.yml b/retrieve.yml new file mode 100644 index 0000000..7119f5d --- /dev/null +++ b/retrieve.yml @@ -0,0 +1,3 @@ +beginWL: 360 +endWL: 721 +interval: 1 diff --git a/uart.py b/uart.py new file mode 100644 index 0000000..19fc96d --- /dev/null +++ b/uart.py @@ -0,0 +1,200 @@ +import serial +import struct +import time + +class Uart(object): + def __init__(self,): + self.ser = serial.Serial() + self.__buf = b'' + self.command = b'' + self._is_connected = False + self.begin_time = None + pass + + def set_serial_para(self, port="COM1",baudrate=9600,bytesize=8,parity="N", stopbit=1, timeout = 4): + self.port = port + self.ser.port = port + self.ser.baudrate = baudrate + self.ser.bytesize = bytesize + self.ser.parity = parity + self.ser.stopbits = stopbit + self.ser.timeout = timeout + + def set_modbus(self, slaveaddress=1, functioncode=3, beginaddress=0, step=5 ): + self.slaveaddress = slaveaddress + self.functioncode = functioncode + self.beginaddress = beginaddress + self.step = step + self.command = self.__get_modbus_command() + self.rcv_len = 2*self.step + 5 # 16bit + + def connect(self,): + try: + self.ser.open() + if self.ser.isOpen(): + self._is_connected = True + self.ser.close() + except Exception as e: + self._is_connected = False + # SerialException(f"KH3000 can not open port : {self.ser.port}") + + if self.ser is not None and self.ser.isOpen(): + self.ser.close() + return self._is_connected + + def disconnect(self,): + if self._is_connected or self.ser.isOpen(): + self.ser.close() + self._is_received = False + self._is_connected = False + pass + + def write(self,) -> None: + try: + self.ser.open() + if self.ser.isOpen(): + self.ser._is_connected = True + except Exception as e: + self.ser. _is_connected = False + + if self.ser._is_connected: + self.begin_time = time.time() + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() + # print(f"========= command {self.command.hex() }") + self.ser.write(self.command) + # if isHex: + # data = bytes.fromhex(data) + # self.ser.write(bytes(data)) + # else: + # self.ser.write(bytes(data, encoding='utf8')+b'\x0A\x0D') + + def receive(self,): + self.flush() + while 1: + if not self._is_receiving: + break + if self.ser.in_waiting: # 这个接收是随机的 + for _ in range(self.ser.in_waiting): + # print( type(_serial.read(1))) + temp = self.ser.read(1) # 可以直接读取指定长度 + self.__buf = self.__buf + temp + if len(self.__buf) >= self.rcv_len: + break + if time.time() - self.begin_time > self.ser.timeout: + self.__buf = b'' + break + + self._is_receiving = False + + def OneMeasure(self) -> bytes: + if not self.ser.isOpen(): + self.ser.open() + self._is_receiving = True + self.__buf = b'' + self.receive() + + if len(self.__buf)>=self.rcv_len and not self._is_receiving : + return self.__buf + + return b'' + pass + + def reset_input_buffer(self)->None: + self.ser.reset_input_buffer() + pass + + def reset_output_buffer(self)->None: + self.ser.reset_output_buffer() + pass + + def flush(self)->None: + self.ser.flush() + pass + + def IsOpen(self)->bool: + return self._is_connected + pass + + def IsReceived(self)->bool: + return self._is_received + pass + + def getResult(self)->bytes: + return self.__buf + pass + + def add_crc16( self, buf:bytes ): + ''' + 一般发送命令都是'01030000000A'这样的字符串 + 输入:test2 = '01030000000A' + 输出:0xc5cd + hexstr[2:].upper() 去掉 + ''' + crc = 0xFFFF + for pos in buf: + crc ^= pos + for i in range(8): + if ((crc & 1) != 0): + crc >>= 1 + crc ^= 0xA001 + else: + crc >>= 1 + return ((crc & 0xff) << 8) + (crc >> 8) + # return hex(((crc & 0xff) << 8) + (crc >> 8))[2:].upper() + + def crc16Check(self,buf:bytes): + if len(buf) > 4 : + crc = self.add_crc16(buf[:-2]) + if (crc & 0xff) == buf[-1] and (crc >> 8)== buf[-2]: + return True + else: + return False + else: + return False + + def __get_modbus_command(self, ): + res = b'' + res = res + self.slaveaddress.to_bytes(1, byteorder="big") + res = res + self.functioncode.to_bytes(1, byteorder="big") + res = res + self.beginaddress.to_bytes(2, byteorder="big") + res = res + self.step.to_bytes(2, byteorder="big") + crc = self.add_crc16(res) + hi = (crc >> 8).to_bytes(1, byteorder="big") + lo = (crc & 0xff).to_bytes(1, byteorder="big") + return res + hi + lo + + pass + +if __name__ == '__main__': + # 字符串转字节 + u = Uart() + s = "01030000000A" + sss = b'\x01\x03\x00\x00\x00\x0A\xC5\xCD' + print(bytes.fromhex(s)) + print(bytearray.fromhex(s)) + + + print( u.add_crc16(bytes.fromhex(s)) ) + print("00000000000000000000000000000000000") + print(sss[:-2]) + if u.crc16Check(sss): + print("TRUE,...") + else: + print("fffffffffffff") + + # 数字转字节 + a = 1024 + b=a.to_bytes(2, byteorder='big') # 2个字节 + + + a.from_bytes(b'\x04\x00', byteorder='big') + + # ASCIIunpack + data = "a" + bytes(data, encoding='utf8') + + # struct 打包转字节 + ss = struct.pack('>H', 8) # unpack + print(ss) + pass \ No newline at end of file diff --git a/uiconfig/__pycache__/ui_com_setting.cpython-38.pyc b/uiconfig/__pycache__/ui_com_setting.cpython-38.pyc new file mode 100644 index 0000000..391fc76 Binary files /dev/null and b/uiconfig/__pycache__/ui_com_setting.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/ui_filepath_setting.cpython-38.pyc b/uiconfig/__pycache__/ui_filepath_setting.cpython-38.pyc new file mode 100644 index 0000000..24a3f8c Binary files /dev/null and b/uiconfig/__pycache__/ui_filepath_setting.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/ui_log_setting.cpython-38.pyc b/uiconfig/__pycache__/ui_log_setting.cpython-38.pyc new file mode 100644 index 0000000..ce0939a Binary files /dev/null and b/uiconfig/__pycache__/ui_log_setting.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/ui_pathsn_setting.cpython-38.pyc b/uiconfig/__pycache__/ui_pathsn_setting.cpython-38.pyc new file mode 100644 index 0000000..43b8f48 Binary files /dev/null and b/uiconfig/__pycache__/ui_pathsn_setting.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/ui_plot_setting.cpython-38.pyc b/uiconfig/__pycache__/ui_plot_setting.cpython-38.pyc new file mode 100644 index 0000000..6f31d6a Binary files /dev/null and b/uiconfig/__pycache__/ui_plot_setting.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uiabout.cpython-38.pyc b/uiconfig/__pycache__/uiabout.cpython-38.pyc new file mode 100644 index 0000000..1e0f3f2 Binary files /dev/null and b/uiconfig/__pycache__/uiabout.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uihelp.cpython-38.pyc b/uiconfig/__pycache__/uihelp.cpython-38.pyc new file mode 100644 index 0000000..14d360c Binary files /dev/null and b/uiconfig/__pycache__/uihelp.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uilogging.cpython-38.pyc b/uiconfig/__pycache__/uilogging.cpython-38.pyc new file mode 100644 index 0000000..c928f3b Binary files /dev/null and b/uiconfig/__pycache__/uilogging.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uioscar.cpython-38.pyc b/uiconfig/__pycache__/uioscar.cpython-38.pyc new file mode 100644 index 0000000..33d0229 Binary files /dev/null and b/uiconfig/__pycache__/uioscar.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uiport.cpython-38.pyc b/uiconfig/__pycache__/uiport.cpython-38.pyc new file mode 100644 index 0000000..97eafcc Binary files /dev/null and b/uiconfig/__pycache__/uiport.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uiprofiler.cpython-38.pyc b/uiconfig/__pycache__/uiprofiler.cpython-38.pyc new file mode 100644 index 0000000..6bd85ca Binary files /dev/null and b/uiconfig/__pycache__/uiprofiler.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uiramses.cpython-38.pyc b/uiconfig/__pycache__/uiramses.cpython-38.pyc new file mode 100644 index 0000000..718ad52 Binary files /dev/null and b/uiconfig/__pycache__/uiramses.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uisensor.cpython-38.pyc b/uiconfig/__pycache__/uisensor.cpython-38.pyc new file mode 100644 index 0000000..a8c4229 Binary files /dev/null and b/uiconfig/__pycache__/uisensor.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uisurface.cpython-38.pyc b/uiconfig/__pycache__/uisurface.cpython-38.pyc new file mode 100644 index 0000000..020ad86 Binary files /dev/null and b/uiconfig/__pycache__/uisurface.cpython-38.pyc differ diff --git a/uiconfig/__pycache__/uiviper.cpython-38.pyc b/uiconfig/__pycache__/uiviper.cpython-38.pyc new file mode 100644 index 0000000..d120bb2 Binary files /dev/null and b/uiconfig/__pycache__/uiviper.cpython-38.pyc differ diff --git a/uiconfig/ui_algorithm.py b/uiconfig/ui_algorithm.py new file mode 100644 index 0000000..50ba6d7 --- /dev/null +++ b/uiconfig/ui_algorithm.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +import wx +# from configobj import ConfigObj +from myconfig import MyConfig +from myconfig import YAML_FILE_NAME + +class UI_Algorithm(wx.Dialog): + """ + @description : 算法配置 + """ + def __init__(self, parent, id): + # 串口页面配置 + super(UI_Algorithm, self).__init__( parent ,id = id ) + self.config = MyConfig() + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle(" 算法配置 ") + + def InitUI(self): + self.config_yml = self.config.read_yaml() + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='算法配置') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, label='浊度校正 ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL ) + self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) ) + tmp = self.get_str_from_config( "algorithm", "A720" ) + if tmp is not None: + self.textCtrl1.SetValue(tmp) + self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5) + + self.hbox2 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText2 = wx.StaticText(self.panel, label='包含纯水: ' ,size=(60, -1)) + # self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl2 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config( "algorithm", "2" ) + if tmp is not None: + self.textCtrl2.SetValue(tmp) + self.hbox2.Add(self.staticText2, flag=wx.TOP|wx.LEFT, border=5) + self.hbox2.Add(self.textCtrl2,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox2, flag=wx.TOP|wx.LEFT, border=5) + + self.hbox3 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText3 = wx.StaticText(self.panel, label='纯水: ' ,size=(60, -1)) + # self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl3 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config( "algorithm", "3" ) + if tmp is not None: + self.textCtrl3.SetValue(tmp) + self.hbox3.Add(self.staticText3, flag=wx.TOP|wx.LEFT, border=5) + self.hbox3.Add(self.textCtrl3,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox3, flag=wx.TOP|wx.LEFT, border=5) + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'保存配置') + self.closeButton = wx.Button(self, label='Close') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5) + + # 添加 vbox 到panel + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + def get_str_from_config( self, section, key ): + return str(self.config_yml[section][key]) + pass + + def set_config_by_section_key_val( self, section, key, val ): + # print(f" {key} current type {type( self.config_yml[section][key] )}") + if type( self.config_yml[section][key] ) == int: + self.config_yml[section][key] = int(val) + elif type( self.config_yml[section][key] ) == float: + self.config_yml[section][key] = float(val) + else: + self.config_yml[section][key] = val + pass + + def saveData(self, e): + pass + + def OnClose(self, e): + self.Destroy() + + def OnSave(self, e): + success = True + # 赋值字典,写入文件 + self.set_config_by_section_key_val( 'algorithm',"1",self.textCtrl1.GetValue( ) ) + self.set_config_by_section_key_val( 'algorithm',"2",self.textCtrl2.GetValue( ) ) + self.set_config_by_section_key_val( 'algorithm',"3",self.textCtrl2.GetValue( ) ) + self.config.write_yaml(self.config_yml) + del self.config + if success: + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/ui_com_setting.py b/uiconfig/ui_com_setting.py new file mode 100644 index 0000000..9c9bef8 --- /dev/null +++ b/uiconfig/ui_com_setting.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +import wx +from myconfig import MyConfig +from myconfig import YAML_FILE_NAME + +class UI_Com_Setting(wx.Dialog): + """ + @description : Com 配置 + """ + def __init__(self, parent,id): + # 串口页面配置 + super(UI_Com_Setting, self).__init__( parent ,id=id ) + self.config = MyConfig() + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle(" 设置串口参数 ") + + def InitUI(self): + + self.config_yml = self.config.read_yaml() + # print(self.config_yml['comsetting']) + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='设置串口') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, label='串口号: ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL ) + self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) ) + tmp = self.get_str_from_config("comsetting",'port') + if tmp is not None: + self.textCtrl1.SetValue(tmp) + self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5) + + self.hbox2 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText2 = wx.StaticText(self.panel, label='波特率: ' ,size=(60, -1)) + # self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl2 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config("comsetting",'baudrate') + if tmp is not None: + self.textCtrl2.SetValue(tmp) + self.hbox2.Add(self.staticText2, flag=wx.TOP|wx.LEFT, border=5) + self.hbox2.Add(self.textCtrl2,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox2, flag=wx.TOP|wx.LEFT, border=5) + + self.hbox3 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText3 = wx.StaticText(self.panel, label='数据位: ' ,size=(60, -1)) + # self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl3 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config("comsetting",'bytesize') + if tmp is not None: + self.textCtrl3.SetValue(tmp) + self.hbox3.Add(self.staticText3, flag=wx.TOP|wx.LEFT, border=5) + self.hbox3.Add(self.textCtrl3,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox3.Add(self.staticText3_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox3, flag=wx.TOP|wx.LEFT, border=5) + + self.hbox4 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText4 = wx.StaticText(self.panel, label='奇偶性: ' ,size=(60, -1)) + # self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl4 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config("comsetting",'parity') + if tmp is not None: + self.textCtrl4.SetValue(tmp) + self.hbox4.Add(self.staticText4, flag=wx.TOP|wx.LEFT, border=5) + self.hbox4.Add(self.textCtrl4,flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add( self.hbox4, flag=wx.TOP|wx.LEFT, border=5 ) + + self.hbox5 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText5 = wx.StaticText(self.panel, label='停止位: ' ,size=(60, -1)) + # self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl5 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config("comsetting",'stopbit') + if tmp is not None: + self.textCtrl5.SetValue(tmp) + self.hbox5.Add(self.staticText5, flag=wx.TOP|wx.LEFT, border=5) + self.hbox5.Add(self.textCtrl5, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add( self.hbox5, flag=wx.TOP|wx.LEFT, border=5 ) + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'保存配置') + self.closeButton = wx.Button(self, label='Close') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5) + + # 添加 vbox 到panel + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + def get_str_from_config( self, section, key ): + return str(self.config_yml[section][key]) + pass + + def set_config_by_section_key_val( self, section, key, val ): + # print(f" {key} current type {type( self.config_yml[section][key] )}") + if type( self.config_yml[section][key] ) == int: + self.config_yml[section][key] = int(val) + elif type( self.config_yml[section][key] ) == float: + self.config_yml[section][key] = float(val) + else: + self.config_yml[section][key] = val + pass + + def saveData( self, e ): + pass + + def OnClose( self, e ): + self.Destroy() + + def OnSave(self, e): + success = True + # 赋值字典,写入文件 + self.set_config_by_section_key_val("comsetting", 'port', self.textCtrl1.GetValue( )) + self.set_config_by_section_key_val("comsetting", 'baudrate', self.textCtrl2.GetValue( )) + self.set_config_by_section_key_val("comsetting", 'bytesize', self.textCtrl3.GetValue( )) + self.set_config_by_section_key_val("comsetting", 'parity', self.textCtrl4.GetValue( )) + self.set_config_by_section_key_val("comsetting", 'stopbit', self.textCtrl5.GetValue( )) + + self.config.write_yaml(self.config_yml) + del self.config + + if success: + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/ui_filepath_setting.py b/uiconfig/ui_filepath_setting.py new file mode 100644 index 0000000..f08eeaa --- /dev/null +++ b/uiconfig/ui_filepath_setting.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +import wx +# from configobj import ConfigObj +from myconfig import MyConfig +from myconfig import YAML_FILE_NAME + +class UI_Filepath_Setting(wx.Dialog): + """ + @description : 文件路径 配置 + """ + def __init__(self, parent,id): + # 串口页面配置 + super(UI_Filepath_Setting, self).__init__( parent ,id=id ) + self.config = MyConfig() + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle(" 设置文件路径 ") + + def InitUI(self): + self.config_yml = self.config.read_yaml() + # self.sensor = self.config_sensor.get(self.did) + # print(self.config_sensor) + # print(self.sensor) + + self.panel = wx.Panel( self ) + self.vbox = wx.BoxSizer( wx.VERTICAL ) + + self.sb = wx.StaticBox(self.panel, label='文件路径 配置') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, label='文件路径: ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL ) + self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) ) + tmp = self.get_str_from_config("filepath","path") + if tmp is not None: + self.textCtrl1.SetValue(tmp) + self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5) + + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'保存配置') + self.closeButton = wx.Button(self, label='Close') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5) + + # 添加 vbox 到panel + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + def get_str_from_config( self, section, key ): + return str(self.config_yml[section][key]) + pass + + def set_config_by_section_key_val( self, section, key, val ): + # print(f" {key} current type {type( self.config_yml[section][key] )}") + if type( self.config_yml[section][key] ) == int: + self.config_yml[section][key] = int(val) + elif type( self.config_yml[section][key] ) == float: + self.config_yml[section][key] = float(val) + else: + self.config_yml[section][key] = val + pass + + + def saveData(self, e): + pass + + def OnClose(self, e): + + self.Destroy() + + def OnSave(self, e): + success = True + # 赋值字典,写入文件 + self.set_config_by_section_key_val('filepath',"file",self.textCtrl1.GetValue( )) + self.config_yml.write_yaml(self.config_sensor) + del self.config + + if success: + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/ui_log_setting.py b/uiconfig/ui_log_setting.py new file mode 100644 index 0000000..ae32c8e --- /dev/null +++ b/uiconfig/ui_log_setting.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +import wx +# from configobj import ConfigObj +from myconfig import MyConfig +from myconfig import YAML_FILE_NAME + +class UI_Log_Setting(wx.Dialog): + """ + @description : Sensor 配置 + """ + def __init__(self, parent, id): + # 串口页面配置 + super(UI_Log_Setting, self).__init__( parent ,id = id ) + self.config = MyConfig() + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle(" 设置光程 序列号 ") + + def InitUI(self): + self.config_yml = self.config.read_yaml() + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='设置光程 序列号') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, label='采集间隔: ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL ) + self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) ) + tmp = self.get_str_from_config( "logsetting", "LogInterval" ) + if tmp is not None: + self.textCtrl1.SetValue(tmp) + self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5) + + self.hbox2 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText2 = wx.StaticText(self.panel, label='保存间隔: ' ,size=(60, -1)) + # self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl2 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config( "logsetting", "RefreshInterval" ) + if tmp is not None: + self.textCtrl2.SetValue(tmp) + self.hbox2.Add(self.staticText2, flag=wx.TOP|wx.LEFT, border=5) + self.hbox2.Add(self.textCtrl2,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox2, flag=wx.TOP|wx.LEFT, border=5) + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'保存配置') + self.closeButton = wx.Button(self, label='Close') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5) + + # 添加 vbox 到panel + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + def get_str_from_config( self, section, key ): + return str(self.config_yml[section][key]) + pass + + def set_config_by_section_key_val( self, section, key, val ): + # print(f" {key} current type {type( self.config_yml[section][key] )}") + if type( self.config_yml[section][key] ) == int: + self.config_yml[section][key] = int(val) + elif type( self.config_yml[section][key] ) == float: + self.config_yml[section][key] = float(val) + else: + self.config_yml[section][key] = val + pass + + + def saveData(self, e): + pass + + def OnClose(self, e): + + self.Destroy() + + def OnSave(self, e): + success = True + # 赋值字典,写入文件 + self.set_config_by_section_key_val('logsetting',"LogInterval",self.textCtrl1.GetValue( )) + self.set_config_by_section_key_val('logsetting',"RefreshInterval",self.textCtrl2.GetValue( )) + self.config.write_yaml(self.config_yml) + del self.config + if success: + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/ui_pathsn_setting.py b/uiconfig/ui_pathsn_setting.py new file mode 100644 index 0000000..73215b2 --- /dev/null +++ b/uiconfig/ui_pathsn_setting.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +import wx +# from configobj import ConfigObj +from myconfig import MyConfig +from myconfig import YAML_FILE_NAME + +class UI_PathSN_Setting(wx.Dialog): + """ + @description : 设置光程 序列号 + """ + def __init__(self, parent,id): + # 串口页面配置 + super(UI_PathSN_Setting, self).__init__( parent ,id=id ) + self.config = MyConfig() + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle(" 设置光程 序列号 ") + + def InitUI(self): + self.config_yml = self.config.read_yaml() + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='设置光程 序列号') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, label='光 程: ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL ) + self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) ) + tmp = self.get_str_from_config( "device", "UIPATH" ) + if tmp is not None: + self.textCtrl1.SetValue(tmp) + self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5) + + self.hbox2 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText2 = wx.StaticText(self.panel, label='序列号: ' ,size=(60, -1)) + # self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl2 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config( "device", "UISN" ) + if tmp is not None: + self.textCtrl2.SetValue(tmp) + self.hbox2.Add(self.staticText2, flag=wx.TOP|wx.LEFT, border=5) + self.hbox2.Add(self.textCtrl2,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox2, flag=wx.TOP|wx.LEFT, border=5) + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'保存配置') + self.closeButton = wx.Button(self, label='Close') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5) + + # 添加 vbox 到panel + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + def get_str_from_config( self, section, key ): + return str(self.config_yml[section][key]) + pass + + def set_config_by_section_key_val( self, section, key, val ): + # print(f" {key} current type {type( self.config_yml[section][key] )}") + if type( self.config_yml[section][key] ) == int: + self.config_yml[section][key] = int(val) + elif type( self.config_yml[section][key] ) == float: + self.config_yml[section][key] = float(val) + else: + self.config_yml[section][key] = val + pass + + + def saveData(self, e): + pass + + def OnClose(self, e): + + self.Destroy() + + def OnSave(self, e): + success = True + # 赋值字典,写入文件 + self.set_config_by_section_key_val('device',"UIPATH",self.textCtrl1.GetValue( )) + self.set_config_by_section_key_val('device',"UISN",self.textCtrl2.GetValue( )) + self.config.write_yaml(self.config_yml) + del self.config + if success: + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/ui_plot_setting.py b/uiconfig/ui_plot_setting.py new file mode 100644 index 0000000..cafdbc9 --- /dev/null +++ b/uiconfig/ui_plot_setting.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +import wx +# from configobj import ConfigObj +from myconfig import MyConfig +from myconfig import YAML_FILE_NAME + +class UI_Plot_Setting(wx.Dialog): + """ + @description : 绘图 配置 + """ + def __init__(self, parent, id): + # 串口页面配置 + super(UI_Plot_Setting, self).__init__( parent ,id = id ) + self.config = MyConfig() + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle(" 绘图 序列号 ") + + def InitUI(self): + self.config_yml = self.config.read_yaml() + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='绘图 序列号') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, label='起始行号 ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL ) + self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) ) + tmp = self.get_str_from_config( "plotsetting", "LineBegin" ) + if tmp is not None: + self.textCtrl1.SetValue(tmp) + self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5) + + self.hbox2 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText2 = wx.StaticText(self.panel, label='间隔行号: ' ,size=(60, -1)) + # self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl2 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.get_str_from_config( "plotsetting", "LineInterval" ) + if tmp is not None: + self.textCtrl2.SetValue(tmp) + self.hbox2.Add(self.staticText2, flag=wx.TOP|wx.LEFT, border=5) + self.hbox2.Add(self.textCtrl2,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox2, flag=wx.TOP|wx.LEFT, border=5) + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'保存配置') + self.closeButton = wx.Button(self, label='Close') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5) + + # 添加 vbox 到panel + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + def get_str_from_config( self, section, key ): + return str(self.config_yml[section][key]) + pass + + def set_config_by_section_key_val( self, section, key, val ): + # print(f" {key} current type {type( self.config_yml[section][key] )}") + if type( self.config_yml[section][key] ) == int: + self.config_yml[section][key] = int(val) + elif type( self.config_yml[section][key] ) == float: + self.config_yml[section][key] = float(val) + else: + self.config_yml[section][key] = val + pass + + + def saveData(self, e): + pass + + def OnClose(self, e): + + self.Destroy() + + def OnSave(self, e): + success = True + # 赋值字典,写入文件 + self.set_config_by_section_key_val('plotsetting',"LineBegin",self.textCtrl1.GetValue( )) + self.set_config_by_section_key_val('plotsetting',"LineInterval",self.textCtrl2.GetValue( )) + self.config.write_yaml(self.config_yml) + del self.config + if success: + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/uiabout.py b/uiconfig/uiabout.py new file mode 100644 index 0000000..56a33c7 --- /dev/null +++ b/uiconfig/uiabout.py @@ -0,0 +1,60 @@ +import wx + +# 设置串口参数的对话框类 + +class About(wx.Dialog): + + def __init__(self, *args, **kwds): + + # 参数调入后初始化 + super(About, self).__init__(*args, **kwds) + + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle("使用帮助") + + def InitUI(self): + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='使用帮助') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, + label='''\n上海奕枫仪器设备有限公司 +电话: 021-54270075 +网站: http://www.yi-win.com +邮件: sales@yi-win.com ''' ) + self.hbox1.Add(self.staticText1) + self.sbs.Add(self.hbox1) + + + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'确认') + self.closeButton = wx.Button(self, label='关闭') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag=wx.LEFT, border=5) + + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + + def saveData(self, e): + pass + + def OnClose(self, e): + self.Destroy() + + def OnSave(self, e): + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/uihelp.py b/uiconfig/uihelp.py new file mode 100644 index 0000000..8c7a1c7 --- /dev/null +++ b/uiconfig/uihelp.py @@ -0,0 +1,58 @@ +import wx + +# 设置串口参数的对话框类 + +class Help(wx.Dialog): + + def __init__(self, *args, **kwds): + + # 参数调入后初始化 + super(Help, self).__init__(*args, **kwds) + + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle("使用帮助") + + def InitUI(self): + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='使用帮助') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, + label='''\n上海奕枫仪器设备有限公司 +电话: 021-54270075 +网站: http://www.yi-win.com +邮件: sales@yi-win.com ''' ) + self.hbox1.Add(self.staticText1) + self.sbs.Add(self.hbox1) + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'确认') + self.closeButton = wx.Button(self, label='关闭') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag=wx.LEFT, border=5) + + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + + def saveData(self, e): + pass + + def OnClose(self, e): + self.Destroy() + + def OnSave(self, e): + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/uiconfig/uisensor.py b/uiconfig/uisensor.py new file mode 100644 index 0000000..36a2e1b --- /dev/null +++ b/uiconfig/uisensor.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +import wx +# from configobj import ConfigObj +from myconfig import MyConfig +from myconfig import YAML_FILE_NAME + +class UISensor(wx.Dialog): + """ + @description : Sensor 配置 + """ + def __init__(self, parent, id, did): + # 参数调入后初始化 + self.did = did + super(UISensor, self).__init__( parent, id=id ) + self.config = MyConfig() + self.InitUI() + self.SetSize((400, 400)) + self.SetTitle(" 设置页面 串口 采集间隔 ") + + def InitUI(self): + + self.config_sensor = self.config.read_yaml() + # self.sensor = self.config_sensor.get(self.did) + # print(self.config_sensor) + # print(self.sensor) + + self.panel = wx.Panel(self) + self.vbox = wx.BoxSizer(wx.VERTICAL) + + self.sb = wx.StaticBox(self.panel, label='设置页面') + self.sbs = wx.StaticBoxSizer(self.sb, orient=wx.VERTICAL) + + self.hbox1 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText1 = wx.StaticText(self.panel, label='Lsky: ',size=(60, -1), style=wx.ALIGN_CENTRE_VERTICAL ) + self.textCtrl1 = wx.TextCtrl(self.panel, value="",size=(250,25) ) + tmp = self.getSnByDidAndFunc("Lsky",self.did) + if tmp is not None: + self.textCtrl1.SetValue(tmp) + self.hbox1.Add(self.staticText1, flag=wx.TOP|wx.LEFT, border=5) + self.hbox1.Add(self.textCtrl1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox1, flag=wx.TOP|wx.LEFT, border= 5) + + self.hbox2 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText2 = wx.StaticText(self.panel, label='Esky: ' ,size=(60, -1)) + # self.staticText2_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl2 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.getSnByDidAndFunc("Esky",self.did) + if tmp is not None: + self.textCtrl2.SetValue(tmp) + self.hbox2.Add(self.staticText2, flag=wx.TOP|wx.LEFT, border=5) + self.hbox2.Add(self.textCtrl2,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox2.Add(self.staticText2_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox2, flag=wx.TOP|wx.LEFT, border=5) + + self.hbox3 = wx.BoxSizer(wx.HORIZONTAL) + self.staticText3 = wx.StaticText(self.panel, label='Lwater: ' ,size=(60, -1)) + # self.staticText3_1 = wx.StaticText(self.panel, label='分钟 ' ,size=(60, -1)) + self.textCtrl3 = wx.TextCtrl(self.panel, value="",size=(250,25)) + tmp = self.getSnByDidAndFunc("Lwater",self.did) + if tmp is not None: + self.textCtrl3.SetValue(tmp) + self.hbox3.Add(self.staticText3, flag=wx.TOP|wx.LEFT, border=5) + self.hbox3.Add(self.textCtrl3,flag=wx.TOP|wx.LEFT, border=5) + # self.hbox3.Add(self.staticText3_1, flag=wx.TOP|wx.LEFT, border=5) + self.sbs.Add(self.hbox3, flag=wx.TOP|wx.LEFT, border=5) + + self.panel.SetSizer(self.sbs) + + self.hbox_0 = wx.BoxSizer(wx.HORIZONTAL) + self.okButton = wx.Button(self, label=u'保存配置') + self.closeButton = wx.Button(self, label='Close') + self.hbox_0.Add(self.okButton) + self.hbox_0.Add(self.closeButton, flag = wx.LEFT, border=5) + + # 添加 vbox 到panel + self.vbox.Add(self.panel, proportion=1, + flag=wx.ALL | wx.EXPAND, border=5) + + self.vbox.Add(self.hbox_0, flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, border=10) + + self.SetSizer(self.vbox) + + self.okButton.Bind(wx.EVT_BUTTON, self.OnSave) + self.closeButton.Bind(wx.EVT_BUTTON, self.OnClose) + + def getSnByDidAndFunc(self,func,did): + temp:dict = self.config_sensor.get(did) + for v in temp.values(): + if v["FUNC"] == func: + return v["SN"] + return None + pass + + def setSnByDidAndFunc(self,func,did,val): + temp:dict = self.config_sensor.get(did) + for k,v in temp.items(): + if v["FUNC"] == func: + temp[k]['SN'] =val + self.config_sensor.update({did:temp}) + + pass + + def saveData(self, e): + pass + + def OnClose(self, e): + + self.Destroy() + + def OnSave(self, e): + success = True + # 赋值字典,写入文件 + self.setSnByDidAndFunc('Lsky',self.did,self.textCtrl1.GetValue( )) + self.setSnByDidAndFunc('Esky',self.did,self.textCtrl2.GetValue( )) + self.setSnByDidAndFunc('Lwater',self.did,self.textCtrl3.GetValue( )) + print(self.textCtrl3.GetValue( )) + + print(self.config_sensor) + self.config.write_yaml(self.config_sensor) + del self.config + + if success: + self.EndModal(wx.ID_OK) \ No newline at end of file diff --git a/viper.py b/viper.py new file mode 100644 index 0000000..43342a4 --- /dev/null +++ b/viper.py @@ -0,0 +1,427 @@ +import numpy as np +import struct +import math + +from myconfig import TOKEN, DATA_DIR, FILE_MARK, OUTPUT_DIR, CAL_DIR +from myconfig import PURE_WATER_FNAME,SAVE_EXT_NAME +from myconfig import MyConfig +from configuration import Configuration + +from myexception import MyException +from mylogger import log +from mypath import MyDir +from mythread import Multithread +from readcal import ReadCal +from uart import Uart +from pathlib import Path, PurePath +from wx.lib.pubsub import pub + +class Viper(object): + def __init__(self,): + self.cfg = {} + self.mydir = MyDir() + self.file_lst = [] + self.raw_wavelength = [] + self.raw_wavelength_np = np.array([]) + self.purewater_wavelength = [] + self.purewater_attenuation = [] + self.output_wavelength = [] + self.begin = 0 + self.end = 0 + + self.dir :Path = Path() + self.datadir :Path = self.dir.joinpath(DATA_DIR) + self.output_dir:Path= self.datadir.joinpath(OUTPUT_DIR) + self.measure_time = '' + self.data = [] + self.res = b'' + self.msg = {"type":"", "data":{}} + self.__get_purewater_wl_and_data() + self.purewater_after_interp = None + self.uart = Uart() + self.uart_thread = Multithread() + pass + + def set_cfg(self, cfg): + self.cfg = cfg + self.ui_sn = self.cfg['device']['UISN'] + pass + + # def set_read_para(self, cfg): + # self.cfg = cfg + # self.ui_sn = self.cfg['device']['UISN'] + # pass + + # def set_uart_para(self, cfg): + # self.cfg = cfg + # self.ui_sn = self.cfg['device']['UISN'] + # pass + + def __set_msg(self, typ, d): + self.msg = {} + self.msg.update( {"type":typ} ) + self.msg.update( {"data":d} ) + pass + + # def file_deal_thread(self, func) -> list: + # self.get_data_files() + # self.__deal_file_lst(func) + # pass + + def get_data_files(self,) -> list: + # 读取配置文件 + self.mydir.setBaseDir(Path(self.datadir)) + self.file_lst = self.mydir.get_files_from_currentdir(fmt="*/*.DAT") + + def get_begin_end(self,) -> list: + # 读取配置文件 + for i in range( len(self.raw_wavelength)): + if self.raw_wavelength[i]self.cfg['retrieve']['beginWL']: + self.begin = i+1 + pass + if self.raw_wavelength[i]self.cfg['retrieve']['endWL']: + self.end = i+2 + break + self.get_output_wavelength() + msg = "起始波长 : "+ str(self.output_wavelength[0]) +" , 结束波长 : "+ str(self.output_wavelength[-1]) + log.info(msg, __name__, '','') + self.__set_msg ("notice", msg ) + pub.sendMessage(self.msg) + + + def get_output_wavelength(self,) : + self.output_wavelength = self.raw_wavelength[self.begin:self.end] + pass + + # def __deal_file_lst(self,func): + # for fl in self.file_lst: + # log.info(f"-> {fl} ",__name__,"deal_file_lst") + # # 判断序列号是否一致file_lst + # if not self.__check_sn_from_datafile(fl): + # raise MyException( "文件的序列号和系统设置不一致" ) + + # # 判断原始波长是否为空 + # if self.raw_wavelength == []: + # self.__get_raw_wl_from_datafile(self.file_lst[0]) + + # # 获得截取的开始 结束点 + # self.get_begin_end() + + # # 纯水插值 + # self.interpo_pure_water() + + # # 准备储存数据文件 + # self.__prepare_for_save() + # ReadCal.read_columns_sets_by_mark_callback( + # fl, FILE_MARK, self.deal_measure_time_data, 1) + # print("beign to func.....") + # func( self.measure_time, self.data ) + # self.__set_msg( "notice", "文件处理完毕" ) + # pub.sendMessage( "update", msg = self.msg ) + + def deal_file_lst(self, ): + for fl in self.file_lst: + log.info(f"-> {fl} ",__name__,"deal_file_lst") + # 判断序列号是否一致file_lst + if not self.__check_sn_from_datafile(fl): + raise MyException( "文件的序列号和系统设置不一致" ) + + # 判断原始波长是否为空 + if self.raw_wavelength == []: + self.__get_raw_wl_from_datafile(self.file_lst[0]) + + # 获得截取的开始 结束点 + self.get_begin_end() + + # 纯水插值 + self.interpo_pure_water() + + # 准备储存数据文件 + self.__prepare_for_save() + ReadCal.read_columns_sets_by_mark_callback( + fl, FILE_MARK, self.deal_measure_time_data, 1) + self.__set_msg( "notice", "文件处理完毕" ) + pub.sendMessage( "update", msg = self.msg ) + + def deal_measure_time_data(self, sn, res_time, res_data): + log.info(f" -> time : {res_time}",__name__, "deal_one_measure_time_data") + log.info(f" -> datalen : {len(res_data)} ",__name__, "deal_one_measure_time_data") + for i in range(len(res_time)): + data = self.convert_str_2_float_list( res_data[i][0][self.begin:self.end] ) + # 浊度校正 + data = self.correction_turbidity( np.array(data) ) + # 纯水校正 + + data = self.correction_pure_water( data ) + + # 取对数,光程归一 ?? 纯水校正,是吸光度校正还是系数校正 + data = ( data * (1000 * math.log(10,math.e)))/self.cfg['device']['UIPath'] + data = data.tolist() + # print(data) + + self.mydir.setContent( data , TOKEN, res_time[i] ) + self.mydir.writeContent() + self.measure_time = res_time[i] + self.data = data + self.__set_msg( "data", {"time":res_time[i], "data":data } ) + pub.sendMessage("update", msg=self.msg) + # pub.sendMessage("update", msg=res_data[i][0][self.begin:self.end]) + + def __check_sn_from_datafile(self, fpath) -> bool: + # 读取配置文件 + sn = ReadCal.readFileSNbyIDDevice(fpath) + if sn == self.ui_sn: + return True + return False + + def __get_raw_wl_from_datafile(self, fpath) -> None: + # 读取配置文件 + _, raw_wl = ReadCal.read_columns_set_by_mark(fpath, FILE_MARK, 0) + self.raw_wavelength = self.convert_str_2_float_list (raw_wl[0]) + self.raw_wavelength_np = np.array(raw_wl[0]) + return None + + def __prepare_for_save(self,) -> bool: + self.mydir.setBaseDir(self.output_dir) + self.mydir.newDirIfNot() + self.mydir.newFileIfNot(self.ui_sn+SAVE_EXT_NAME) + + self.mydir.setHeader(self.output_wavelength, TOKEN, self.ui_sn) + if self.mydir.checkHeader() == 0: + self.mydir.writeHeader() + if self.mydir.checkHeader() == -1: + # self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + + def interpo_pure_water(self): + self.purewater_after_interp = np.interp( + np.array(self.output_wavelength) + , np.array(self.purewater_wavelength) + , np.array(self.purewater_attenuation) + ) + pass + + def correction_turbidity(self, data:np.ndarray ): + '''浊度校正, 吸光度 + 0 : 默认11项平均 + 1 : 720 + 2 : 不浊度校正 + ''' + log.debug( "correction_turbidity .....",__name__, 'correction_turbidity' ) + if self.cfg['algorithm']['A720'] == 0: + count = data.shape[0] + tmp = 0.0 + for i in range(count-11,count,1): + tmp = tmp + data[i] + tmp = tmp/11 + return data - tmp + pass + if self.cfg['algorithm']['A720'] == 1: + count = data.shape[0] + tmp = data[count] - (self.output_wavelength[count]-720) * (data[count] -data[count-1]) \ + / (self.output_wavelength[count]-self.output_wavelength[count-1]) + print(f"tmp .... {tmp}") + return data-tmp + pass + if self.cfg['algorithm']['A720'] == 2: + return data + return data + pass + + def correction_pure_water(self, data:np.ndarray ): + '''浊度校正 + 0 : 不变 + 1 : 减去纯水 + ''' + if self.cfg['algorithm']['PureWater'] == 0: + return data + pass + if self.cfg['algorithm']['PureWater'] == 1: + return data - self.purewater_after_interp + pass + return data + pass + + + + def __get_purewater_wl_and_data(self ): + log.info(f" == ",__name__,'__get_purewater_wl_and_data') + caldir = self.dir.joinpath(CAL_DIR ) + cal_fpath = caldir.joinpath( PURE_WATER_FNAME) + if cal_fpath.exists(): + _, res_data = ReadCal.read_columns_sets_by_mark( + cal_fpath, FILE_MARK, 0, 1) + self.purewater_wavelength = self.convert_str_2_float_list( res_data[0][0]) + self.purewater_attenuation = self.convert_str_2_float_list(res_data[0][1]) + + def set_serial(self, )-> None: + self.uart.set_serial_para( + self.cfg['comsetting']['port'] + ,self.cfg['comsetting']['baudrate'] + ,self.cfg['comsetting']['bytesize'] + ,self.cfg['comsetting']['parity'] + ,self.cfg['comsetting']['stopbit'] + ) + + def set_modbus(self, beginaddress, step)-> None: + self.uart.set_modbus( + self.cfg['register']['slaveaddress'] + ,self.cfg['register']['functioncode'] + ,beginaddress + ,step + ) + + def sn_uart_thread(self, func)-> None: + self.set_serial() + self.uart_thread.remove_tasks() + self.set_modbus( self.cfg['register']['SNAddress'], self.cfg['register']['SNLen'] ) + self.uart_thread.add_task( self.device_sn, args=(func,) ) + self.uart_thread.sequently_execute_tasks() + pass + + def wl_uart_thread(self, func)-> None: + self.res = b'' + self.set_serial() + self.uart_thread.remove_tasks() + for i in range(self.cfg['register']['count']): + log.debug(f" -> i {i}", __name__,"wl_uart_thread") + self.set_modbus( self.cfg['register']['WLBeginAddress'] + i*120, 120 ) + log.debug(f" command -> {self.uart.command.hex()} ") + self.uart_thread.add_task( self.device_wl, args=() ) + self.uart_thread.sequently_execute_tasks() + self.uart_thread.remove_tasks() + # self.uart_thread.add_task_2_act( ) + # self.uart_thread.execute_one_act() + self.raw_wavelength = self.convert_buf_2_float(self.res) + # 获得截取的开始 结束点 + self.get_begin_end() + self.get_output_wavelength() + msg = "起始波长 : "+str(self.output_wavelength[0]) +" , 结束波长 : "+ str(self.output_wavelength[-1]) + log.info(msg) + self.__set_msg ("notice", msg ) + pub.sendMessage(self.msg) + func( self.output_wavelength ) + # self.__set_msg( "wl", {} ) + # pub.sendMessage("update", msg= self.msg) + + def log_uart_thread(self, func)-> None: + self.res = b'' + self.set_serial() + self.uart_thread.remove_tasks() + for i in range(self.cfg['register']['count']): + self.set_modbus( self.cfg['register']['DataBeginAddress'] + i * 120, 120 ) + self.uart_thread.add_task( self.device_log, args=( ) ) + self.uart_thread.sequently_execute_tasks() + self.uart_thread.remove_tasks() + pass + data = self.convert_buf_2_float(self.res) + data = data[self.begin:self.end] + func(data) + + def device_sn(self, func)-> None: + self.res =b'' + self.uart.disconnect() + self.uart.connect() + self.uart.write() + self.res = self.uart.OneMeasure() + sn = self.res[-6:-2].decode() + self.res = b'' + func( sn ) + # pub.sendMessage("update",msg=self.msg) + + def device_wl(self, )-> None: + # self.res =b'' + # log.warning(" -->", __name__, "device_wl") + self.uart.disconnect() + self.uart.connect() + self.uart.write() + tmp = self.uart.OneMeasure() + self.res = self.res + tmp[3:len(tmp)-2] + + def device_log(self, )-> None: + # self.res =b'' + self.uart.disconnect() + self.uart.connect() + self.uart.write() + tmp = self.uart.OneMeasure() + self.res = self.res + tmp[3:len(tmp)-2] + + def convert_buf_2_float(self, buff, byteOrder= "big" )-> None: + res = [] + log.debug(f" === {len(buff)}== {buff}", __name__, 'convert_buf_2_float') + len_ = len(buff) + if len_%4 != 0: + return res + if byteOrder == "big": + for i in range( int(len_/4) ): + tmp = struct.unpack(">f", buff[i*4: i*4+4] ) + res.append( round(tmp[0],3) ) + else: + for i in range( int(len_/4) ): + tmp = struct.unpack(">f", buff[i*4: i*4+4] ) + res.append(round(tmp[0],3)) + return res + pass + + def convert_str_2_float_list(self, lst )-> None: + res = [] + for l in lst: + res.append(float(l)) + return res + pass + + def set_raw_wavelength_from_device(self, lst): + self.raw_wavelength = lst + pass + + + + + +if __name__ == '__main__': + data = np.array([3,4,5,6]) + print(data.shape[0]) + print(data[3]) + print(data-1) + + + + + + + + # if self.syscfg['retrieve']['enable'] == 0: + # self.mydir.setHeader(self.raw_wavelength,TOKEN,self.ui_sn) + # if self.mydir.checkHeader()==0: + # self.mydir.writeHeader() + # if self.mydir.checkHeader()==-1: + # self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + # raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + # res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 ) + # for i in range( len(res_time) ): + # self.__deal_one_measure_time_data(res_time[i], res_data[i]) + # pass + # pass + # # 需要插值处理波长 + # if self.syscfg['retrieve']['enable'] == 1: + # self.mydir.setHeader(self.new_wavelength.tolist(),TOKEN,self.ui_sn) + # if self.mydir.checkHeader()==0: + # self.mydir.writeHeader() + # if self.mydir.checkHeader()==-1: + # self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + # raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + + # # res_data 不用带回调的函数callback 会导致多组数据拼接?? + # res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 ) + + # log.warning(f" ==== {len(res_time)}" ) + # log.warning(res_time) + # log.warning(f" ==== {len(res_data[0])}" ) + # log.warning(f" ==== { res_data[0] }" ) + + # for i in range( len(res_time) ): + # self.__deal_one_measure_time_data(res_time[i], res_data[0][i]) + # pass + # pass \ No newline at end of file diff --git a/yiwinframe.py b/yiwinframe.py new file mode 100644 index 0000000..1482487 --- /dev/null +++ b/yiwinframe.py @@ -0,0 +1,766 @@ +import wx +import os +import time +import threading +import numpy as np +from pathlib import Path,PurePath +from wx.lib.pubsub import pub +# from configobj import ConfigObj + +from listctrl import Listctrl +# from mypanel import MyPanel +from mypanel import Plot + +from uiconfig.ui_com_setting import UI_Com_Setting +from uiconfig.ui_filepath_setting import UI_Filepath_Setting +from uiconfig.ui_pathsn_setting import UI_PathSN_Setting +from uiconfig.ui_plot_setting import UI_Plot_Setting +from uiconfig.ui_log_setting import UI_Log_Setting +from uiconfig.uiabout import About +from uiconfig.uihelp import Help + +from myconfig import DeviceType,YAML_FILE_NAME,RETRIEVE_CFG_FILE +from myconfig import TOKEN,DATA_DIR,FILE_MARK,OUTPUT_DIR,SAVE_EXT_NAME +from myconfig import MyConfig +from configuration import Configuration +# from awrams import AWRAMS,HandHeldBuf + +from myexception import MyException +from mylogger import log +from mypath import MyDir +from mythread import Mythead +from readcal import ReadCal +from uart import Uart +from viper import Viper +from dataplot import DataPlot + +# -定义菜单ID,关联Event------------------------- +""" +# 菜单 文件 -- 处理文件 + 设备 -- 序列 波长 测量 + 设置 -- 串口 光程 文件路径 绘图参数 采集设置 + 作图 -- 最后一条曲线 最后七条 指定位置七条 + 帮助 +""" + +ID_MEASURE = 1 +ID_DEAL_FILE = 2 +ID_DEVICE_SN = 3 +ID_DEVICE_WL = 4 +ID_DEVICE_LOG = 5 +ID_COM_SETTING = 6 +ID_PATH_SN = 7 +ID_FILE_PATH = 8 +ID_PLOT_SETTING = 9 +ID_LOG_SETTING = 10 + +ID_DEVICE_STOP = 11 + +ID_PLOT_ONE = 15 +ID_PLOT_SEVEN = 16 +ID_PLOT_RULE = 17 + +ID_HELP = 21 +ID_ABOUT = 22 + +class YiwinFrame( wx.Frame ): + '''将buf类传进来''' + def __init__(self, title, parent, size=(900, 750)): + self.device_id = 2 + self.device_type = DeviceType.VIPER.name + self.raw_wavelength = [] + self.new_wavelength = [] + self.device_wavelength = [] + self.device_data = [] + self.output_wavelength = [] + self.output_wl_ndarray = np.array([]) + self.syscfg = {} + self.sensor_cfg = {} + self.retrieve = {} + self.calinfo_is_ok = False + self.title = title + self.dir :Path = Path() + self.datadir :Path = self.dir.joinpath(DATA_DIR) + self.output_dir:Path = self.datadir.joinpath(OUTPUT_DIR) + self.save_fname :Path = Path() + self.result = '' + self.displayData:list = [] + self.interval = 0 + self.measure_time = time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) + + super(YiwinFrame, self).__init__( parent, title=self.title, size = size ) + + self.BoxSizer = wx.BoxSizer(wx.HORIZONTAL) # 建立一个Boxsizer + self.SetSizer(self.BoxSizer) + self.Centre(wx.BOTH) + + # 建立 listctrl panel 放到BoxSizer + self.listctrl_panel = Listctrl( self ) # 调用自己建立的 Listctrl panel 类 + self.BoxSizer.Add( self.listctrl_panel, proportion =-10, border = 2, flag = wx.ALL | wx.EXPAND) + self.list_ctrl = self.listctrl_panel.list_ctrl + # 隐藏 等待show + self.listctrl_panel.Hide() + + self.plotpanel = Plot( self ) # 调用自己建立的 Listctrl panel 类 + self.BoxSizer.Add( self.plotpanel, proportion =-10, border = 0, flag = wx.ALL | wx.EXPAND) + # self.static_text = self.plotpanel.staticText1 + # 隐藏 等待show + self.plotpanel.Show() + + self.statusBar = self.CreateStatusBar() # 创建状态栏 + self.statusBar.SetFieldsCount(2) # 状态栏分成3个区域 + self.statusBar.SetStatusWidths([-1, -1]) # 区域宽度比列,用负数 + self.statusBar.SetStatusText(u" 等待接收消息......", 0) + + self.__set_menu() # 添加菜单 + self.__attach_events() # 菜单事件 + self.__set_properties() + # self.__read_config() + self.__setTimer() + log.info(f"system init....",__name__, "__init__") + self.mycfg = MyConfig() + self.mydir = MyDir() + self.mycfg.set_retrieve() + self.__read_config() + self.ui_sn = self.syscfg['device']['UISN'] + self.device_sn = '' + self.file_sn = '' + self.interval = self.syscfg['logsetting']['LogInterval'] + self.port = self.syscfg['comsetting']['port'] + + self.uart = Uart() + self.viper = Viper() + self.dataplot = DataPlot() + self.plot_pure_water() + + pub.subscribe( self.updateDisplay, "update") + pass + + def __set_menu(self): + ''' + # 设置菜单 + ''' + self.menubar = wx.MenuBar() + + fileMenu = wx.Menu() + fileMenu.Append(ID_DEAL_FILE, u'&处理文件', '...') + self.menubar.Append(fileMenu, u'&文件 ') + + deviceMenu = wx.Menu() + deviceMenu.Append(ID_DEVICE_SN, u'&序列号', '...') + deviceMenu.AppendSeparator() + deviceMenu.Append(ID_DEVICE_WL, u'&波长', '...') + deviceMenu.AppendSeparator() + deviceMenu.Append(ID_DEVICE_LOG, u'&采集数据', '...') + deviceMenu.AppendSeparator() + deviceMenu.Append(ID_DEVICE_STOP, u'&停止采集', '...') + self.menubar.Append(deviceMenu, u'&设备 ') + + settingMenu = wx.Menu() + settingMenu.Append(ID_COM_SETTING, u'&串口设置', '...') + settingMenu.AppendSeparator() + settingMenu.Append(ID_PATH_SN, u'&光程&序列号', ' ') + settingMenu.AppendSeparator() + settingMenu.Append(ID_FILE_PATH, u'&文件路径', ' ') + settingMenu.AppendSeparator() + settingMenu.Append(ID_PLOT_SETTING, u'&绘图设置', ' ') + settingMenu.AppendSeparator() + settingMenu.Append(ID_LOG_SETTING, u'&采集设置', ' ') + self.menubar.Append(settingMenu, u'&系统设置') + + plotMenu = wx.Menu() + plotMenu.Append( ID_PLOT_ONE, u'&最后一条', '...' ) + plotMenu.AppendSeparator() + plotMenu.Append( ID_PLOT_SEVEN, u'&最后七条', '...' ) + plotMenu.AppendSeparator() + plotMenu.Append( ID_PLOT_RULE, u'&指定七条', '...' ) + self.menubar.Append(plotMenu, u'&绘图 ') + + aboutMenu = wx.Menu() + aboutMenu.Append( ID_HELP, u'&帮助', 'help...' ) + aboutMenu.AppendSeparator() + aboutMenu.Append( ID_ABOUT, u'&关于我们', '关于我们...' ) + self.menubar.Append( aboutMenu, u'&帮助') + + self.SetMenuBar(self.menubar) + pass + + def __set_properties(self): + self.SetSize((800, 600)) + # self.SetTitle(u'传感器数据采集--上海奕枫仪器设备有限公司') + self.Centre() + + def __attach_events(self): + ''' + # 绑定菜单事件 + ''' + self.Bind(wx.EVT_MENU, self.OnDealFile, id = ID_DEAL_FILE) + + self.Bind(wx.EVT_MENU, self.OnDeviceSN, id = ID_DEVICE_SN) + self.Bind(wx.EVT_MENU, self.OnDeviceWL, id = ID_DEVICE_WL) + self.Bind(wx.EVT_MENU, self.OnDeviceLog, id = ID_DEVICE_LOG) + self.Bind(wx.EVT_MENU, self.OnDeviceStop, id = ID_DEVICE_STOP) + self.Bind(wx.EVT_MENU, self.OnComSetting, id = ID_COM_SETTING) + self.Bind(wx.EVT_MENU, self.OnPathSNSetting, id = ID_PATH_SN) + self.Bind(wx.EVT_MENU, self.OnFilePathSetting, id = ID_FILE_PATH) + self.Bind(wx.EVT_MENU, self.OnPlotSetting, id = ID_PLOT_SETTING) + self.Bind(wx.EVT_MENU, self.OnLogSetting, id = ID_LOG_SETTING) + + self.Bind(wx.EVT_MENU, self.OnPlotOne, id = ID_PLOT_ONE) + self.Bind(wx.EVT_MENU, self.OnPlotSeven, id = ID_PLOT_SEVEN) + self.Bind(wx.EVT_MENU, self.OnPlotRule, id = ID_PLOT_RULE) + + self.Bind(wx.EVT_MENU, self.OnHelpConfig, id = ID_HELP) + self.Bind(wx.EVT_MENU, self.OnAboutConfig, id = ID_ABOUT) + pass + + def __setTimer(self): + self.timer = wx.Timer(self) #创建定时器,菜单以后 + self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) #绑定一个定时器事件 + pass + + def updateDisplay(self,msg): + log.debug(f" updateDisplay 。。 {msg['data']}") + if msg['type'] == "notice": + self.__update_notice(msg['data']) + pass + if msg['type'] == "sn": + self.__update_sn(msg['data']) + pass + if msg['type'] == "wl": + self.__update_wl(msg['data']) + pass + if msg['type'] == "log": + self.__update_log(msg['data'] ) + print(f" ...log update ...{msg['data']} " ) + pass + if msg['type'] == "data": + # log.info(f" ... update .{msg['data']}........... " ) + self.__update_data(msg['data']) + pass + pass + + def __update_sn(self,sn): + if sn != self.ui_sn: + self.alterStatus_0(f" sn: {sn} 与系统sn {self.ui_sn} 一致") + self.popDialog(f" sn: {sn} 与系统sn {self.ui_sn} 一致") + raise MyException(f" sn: {sn} 与系统sn {self.ui_sn} 一致") + else: + self.alterStatus_0(f" sn: {sn} 与系统sn {self.ui_sn} 不一致") + pass + + def __update_notice(self,msg): + log.debug(f" msg : {msg}") + self.alterStatus_0(msg) + pass + + def __update_wl(self,wl): + log.debug(f" 获得的波长成功 : {wl}") + self.output_wavelength = wl + self.alterStatus_0( f" 获得的波长成功 " ) + pass + + def __update_log(self,d): + log.info(f" 获得的数据 {d}") + self.alterStatus_0( d) + + def __update_data( self, d ): + '''对于文件过来的数据''' + log.debug(f" ", __name__," __update_data") + self.plotpanel.clear_past() + self.plotpanel.plot_one( + d['time'] + ,np.array(self.viper.output_wavelength) + ,np.array(d['data']) + ) + pass + + def OnStart( self, event ): + log.info( f" OnStart....interval: { self.interval } minutes, port: { self.port} " ) + interval_ms = int(self.interval) * 60 * 1000 + self.timer.Start( interval_ms ) # 开始监测 + + def OnStop( self ,event ): + self.timer.Stop() + pass + + def OnTimer(self, event): + ''' 定时器实现 ''' + # log.info( f"OnTimer .... " ) + self.__OnDeviceLog(event) + pass + + def __read_config(self,): + # 读取配置文件 + self.syscfg = self.mycfg.read_yaml() + retrieve = self.mycfg.read_rtv_yaml() + self.syscfg.update( { "retrieve" : retrieve } ) + + def OnDealFile(self, e)-> None: + self.__OnDeviceStop() + log.info( f"OnDealFile: 处理测量文件", __name__, "", "" ) + # 线程守护 + self.mt = Mythead() + self.viper.set_cfg(self.syscfg) + try: + self.viper.get_data_files() + self.mt.set_task( self.viper.deal_file_lst ) + self.mt.start() + self.alterStatus_0(" 处理完所有文件" ) + except Exception as e: + self.alterStatus_0(e ) + self.popDialog( e ) + pass + + def OnDeviceSN(self, e)-> None: + self.__OnDeviceStop() + log.info(f"OnDeviceSN: 获取device sn ", __name__, "", "") + # self.mt = Mythead() + self.viper.set_cfg(self.syscfg) + self.viper.set_serial() + # self.viper.set_modbus(self.syscfg['register']['SNAddress'], self.syscfg['register']['SNLen']) + try: + self.viper.sn_uart_thread( self.get_device_sn ) + except Exception as e: + self.alterStatus_0(e ) + self.popDialog( e ) + self.alterStatus_0(" SN 匹配一致" ) + pass + + def get_device_sn(self,sn): + self.device_sn = sn + if self.device_sn != self.ui_sn: + log.error( " 设备SN 与系统设置不一致 错误 " ) + pass + else: + log.info(" sn 匹配成功 ! ") + pass + + def OnDeviceWL(self, e)-> None: + self.__OnDeviceStop() + log.info(f"OnDeviceWL: 获得device wavelength ... ", __name__, "", "") + if self.device_sn != '': + self.viper.set_cfg( self.syscfg ) + self.viper.set_serial() + try: + self.viper.wl_uart_thread( self.get_device_wl ) + except Exception as e: + self.alterStatus_0(e ) + self.popDialog( e ) + self.alterStatus_0(" 获取波长成功!" ) + else: + self.popDialog('请获取设备序列号SN信息再试') + pass + + def get_device_wl(self, wl_buf): + if len(wl_buf) != 0: + self.output_wavelength = wl_buf + self.output_wl_ndarray = np.array(self.output_wavelength) + else: + log.error( " 获取设备波长出错 " ) + raise MyException( " 获取设备波长出错 " ) + pass + + def OnDeviceLog(self, e)-> None: + self.__OnDeviceStop() + log.info( f"OnDeviceLog: 采集数据 定时器采集", __name__, "", "" ) + # !!!! 判断是否有波长和sn + if self.output_wavelength == []: + self.alterStatus_0( " 没有设备波长信息,请获取设备波长") + self.popDialog( " 没有设备波长信息,请获取设备波长") + raise MyException(" 没有设备波长信息,请获取设备波长") + self.__OnDeviceLog() + + # 如何整点获取,如何快速获取 + self.timer.Start( int(self.interval) * 60 * 1000 ) + pass + + def __OnDeviceLog(self,)-> None: + self.device_data = b'' + self.mt = Mythead() + self.viper.set_cfg( self.syscfg ) + self.viper.set_serial() + try: + self.viper.log_uart_thread( self.get_device_data ) + except Exception as e: + self.alterStatus_0(e ) + self.popDialog( e ) + pass + + def get_device_data( self, data_buf ): + if len(data_buf) != 0: + self.device_data = self.viper.convert_buf_2_float( data_buf ) + self.plotpanel.clear_past() + self.plotpanel.plot_one( + time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) + , self.output_wl_ndarray + ,np.array(data_buf) + ) + else: + log.error( " 采集设备数据出错 " ) + raise MyException(" 采集设备数据出错 ") + pass + + def OnDeviceStop(self, e)-> None: + self.__OnDeviceStop() + pass + + def __OnDeviceStop(self, )-> None: + if self.timer.IsRunning(): + self.timer.Stop() + pass + + + def plot_pure_water(self,): + # self.dataplot.set_file_path() + self.__OnDeviceStop() + self.plotpanel.set_title_x_y( *self.plotpanel.purewater_legend ) + time_ = time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) + + wl = np.array(self.viper.purewater_wavelength) + att = np.array(self.viper.purewater_attenuation) + self.plotpanel.plot_one(time_, wl, att) + pass + + def OnPlotOne(self,e): + self.dataplot.set_file_path( self.output_dir.joinpath(self.ui_sn+SAVE_EXT_NAME) ) + self.dataplot.set_token(TOKEN) + # !! 判断波长,获得波长 + wavelength:str = self.dataplot.get_first_line().strip('\n').strip('\r') + self.output_wavelength = wavelength.split(TOKEN)[1:] + self.output_wl_ndarray = np.array(self.output_wavelength).astype(np.float64) + + line = self.dataplot.get_multi_by_x_m_n(1,1,1) + line = line[0].strip('\n').strip('\r').split(TOKEN) + tm = line[0] + line = np.array(line[1:]).astype(np.float64) + self.plotpanel.axes.clear() + self.plotpanel.plot_one( tm, self.output_wl_ndarray, line ) + self.alterStatus_0( f" plot {tm}") + pass + + def OnPlotSeven(self,e): + self.__OnDeviceStop() + times = [] + lines = [] + log.debug( f'+++ ',__name__, 'OnPlotSeven' ) + self.dataplot.set_file_path( self.output_dir.joinpath( self.ui_sn+SAVE_EXT_NAME ) ) + self.dataplot.set_token(TOKEN) + # !! 判断波长,获得波长 + wavelength:str = self.dataplot.get_first_line().strip('\n').strip('\r') + self.output_wavelength = wavelength.split(TOKEN)[1:] + self.output_wl_ndarray = np.array(self.output_wavelength).astype(np.float64) + + line_7 = self.dataplot.get_multi_by_x_m_n(1,1,7) + # log.warning( f'+++ {line_7} ',__name__, 'OnPlotSeven' ) + for line in line_7: + line = line.strip('\n').strip('\r').split(TOKEN) + tm = line[0] + line = np.array(line[1:]).astype(np.float64) + times.append(tm) + lines.append( line ) + self.plotpanel.axes.clear() + self.plotpanel.plot_multi( times, self.output_wl_ndarray, lines ) + self.alterStatus_0( f" plot 7 ") + pass + + def OnPlotRule(self,e): + self.__OnDeviceStop() + times = [] + lines = [] + log.debug( f'+++ ',__name__, 'OnPlotSeven' ) + self.dataplot.set_file_path( self.output_dir.joinpath( self.ui_sn+SAVE_EXT_NAME ) ) + self.dataplot.set_token(TOKEN) + # !! 判断波长,获得波长 + wavelength:str = self.dataplot.get_first_line().strip('\n').strip('\r') + self.output_wavelength = wavelength.split(TOKEN)[1:] + self.output_wl_ndarray = np.array(self.output_wavelength).astype(np.float64) + + line_7 = self.dataplot.get_multi_by_x_m_n(1,1,7) + # log.warning( f'+++ {line_7} ',__name__, 'OnPlotSeven' ) + for line in line_7: + line = line.strip('\n').strip('\r').split(TOKEN) + tm = line[0] + line = np.array(line[1:]).astype(np.float64) + times.append( tm ) + lines.append( line ) + self.plotpanel.axes.clear() + self.plotpanel.plot_multi( times, self.output_wl_ndarray, lines ) + self.alterStatus_0( f" plot designated ") + pass + + def OnComSetting(self,e): + with UI_Com_Setting( + self, + -1 ) as Dialog_Sensor_Setting: + Dialog_Sensor_Setting.CenterOnParent() + resultLog = Dialog_Sensor_Setting.ShowModal() + + if resultLog == wx.ID_OK: + log.info( " COM config dialog confirm, call back " ) + self.__read_config() + pass + + def OnPathSNSetting(self,e): + with UI_PathSN_Setting( + self, + -1 ) as Dialog_Sensor_Setting: + Dialog_Sensor_Setting.CenterOnParent() + resultLog = Dialog_Sensor_Setting.ShowModal() + + if resultLog == wx.ID_OK: + log.info( " PathSN config dialog confirm, call back " ) + self.__read_config() + pass + + def OnFilePathSetting(self,e): + with UI_Filepath_Setting( + self, + -1 ) as Dialog_Sensor_Setting: + Dialog_Sensor_Setting.CenterOnParent() + resultLog = Dialog_Sensor_Setting.ShowModal() + + if resultLog == wx.ID_OK: + log.info( " FilePath config dialog confirm, call back " ) + self.__read_config() + pass + + def OnPlotSetting(self,e): + with UI_Plot_Setting( + self, + -1 ) as Dialog_Sensor_Setting: + Dialog_Sensor_Setting.CenterOnParent() + resultLog = Dialog_Sensor_Setting.ShowModal() + + if resultLog == wx.ID_OK: + log.info( " Plot config dialog confirm, call back " ) + self.__read_config() + pass + + def OnLogSetting(self,e): + with UI_Log_Setting( + self, + -1 ) as Dialog_Sensor_Setting: + Dialog_Sensor_Setting.CenterOnParent() + resultLog = Dialog_Sensor_Setting.ShowModal() + + if resultLog == wx.ID_OK: + log.info( " Log config dialog confirm, call back " ) + self.__read_config() + pass + + def OnHelpConfig(self, e): + with Help( + self, + -1, + "") as Dialog_Help: + resultLog = Dialog_Help.ShowModal() + if resultLog == wx.ID_OK: + log.info("Help info") + pass + + def OnAboutConfig(self, e): + with About( + self, + -1, + "") as Dialog_About: + resultLog = Dialog_About.ShowModal() + + if resultLog == wx.ID_OK: + log.info("Aboutus") + pass + + def OnOther(self, e): + pass + + def OnQuit(self, e): + self.Close() + + def alterStatus_0(self,msg): + self.statusBar.SetStatusText( msg, 0 ) + + def popDialog(self, msg, msg_type=u"错误提示"): + with wx.MessageDialog( self, msg, msg_type, wx.OK )as dlg: + dlg.ShowModal() + + +# class SerialThread(threading.Thread): +# """进度条类 """ +# def __init__(self, parent): +# """ +# :param parent: 主线程UI +# """ +# super(SerialThread, self).__init__() # 继承 +# self.parent = parent +# # log.info(f"SerialThread ... {self.parent.kh}") +# self.start() +# self.join() +# # self.setDaemon(True) # 设置为守护线程, 即子线程是守护进程,主线程结束子线程也随之结束。 + + +# def stop(self): +# self.parent.kh.disconnect() +# log.info(" Serial stop.... ") +# pass + + # def run(self): + # log.info(" Serial run.... ") + # wx.CallAfter(self.parent.OnRcv) + + # wx.CallAfter(self.parent.update_process_bar, count) # 调用parent的函数 + # wx.CallAfter(self.parent.close_process_bar) # destroy进度条 + + # def OnSerialThreadStart(self): + # self.m = SerialThread(self) + # pass + + # def OnSerialThreadStop(self): + # self.m.stop() + # pass + + # def OnDisplaySave(self): + # ''' + # 保存数据 self.result + # ''' + # log.info(f"OnDisplaySave ....") + # # self.m = SerialThread(self) + # # self.kh.flush() + # self.OnSerialThreadStart() + + + # def OnRcv( self ): + # log.info(f"OnRcv....") + # self.kh.setPort(self.port) + # if not self.OnDetectPort: + # MyException(f"Can not find port : {self.port}") + # log.info(f"{self.port} ok!") + # # if not self.kh: + # # self.kh = KH3000(self.port) + # # self.result = self.kh.OneMeasure() + # log.info( f"OnRcv success {self.result}", __class__.__name__ ) + # self.OnSave() + # self.OnDisplay() + # pass + + + # def __get_data_files(self,) -> list: + # # 读取配置文件 + # file_lst = [] + # self.mydir.setBaseDir( Path(self.datadir) ) + # file_lst = self.mydir.get_files_from_currentdir(fmt= "*/*.DAT") + # return file_lst + + # def __check_sn_from_datafile(self,fpath) -> bool: + # # 读取配置文件 + # sn = ReadCal.readFileSNbyIDDevice(fpath) + # if sn == self.ui_sn: + # return True + # return False + + # def __get_raw_wl_from_datafile(self,fpath) -> list: + # # 读取配置文件 + # _,raw_wl = ReadCal.read_columns_set_by_mark(fpath, FILE_MARK,0) + # return raw_wl + + # def __deal_file_lst(self,file_lst): + + # for fl in file_lst: + # # 判断序列号是否一致file_lst + # if not self.__check_sn_from_datafile(fl): + # self.onNotify("文件的序列号和系统设置不一致" ) + # self.popDialog(" 文件的序列号和系统设置不一致") + # raise MyException("文件的序列号和系统设置不一致") + + # # 判断原始波长是否为空 + # if self.raw_wavelength == []: + # res = self.__get_raw_wl_from_datafile(file_lst[0]) + # self.raw_wavelength = res[0] + + # # 处理输出文件 + # self.mydir.setBaseDir(self.output_dir) + # self.mydir.newDirIfNot() + # self.mydir.newFileIfNot(self.ui_sn+SAVE_EXT_NAME) + # if self.syscfg['retrieve']['enable'] == 0: + # self.mydir.setHeader(self.raw_wavelength,TOKEN,self.ui_sn) + # if self.mydir.checkHeader()==0: + # self.mydir.writeHeader() + # if self.mydir.checkHeader()==-1: + # self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + # raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + # res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 ) + # for i in range( len(res_time) ): + # self.__deal_one_measure_time_data(res_time[i], res_data[i]) + # pass + # pass + # # 需要插值处理波长 + # if self.syscfg['retrieve']['enable'] == 1: + # self.mydir.setHeader(self.new_wavelength.tolist(),TOKEN,self.ui_sn) + # if self.mydir.checkHeader()==0: + # self.mydir.writeHeader() + # if self.mydir.checkHeader()==-1: + # self.popDialog(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + # raise MyException(" 文件头不一致, 请备份到其他目录,并在该目录下删除") + + # # res_data 不用带回调的函数callback 会导致多组数据拼接?? + # res_time,res_data = ReadCal.read_columns_sets_by_mark( fl, FILE_MARK, 1 ) + + # log.warning(f" ==== {len(res_time)}" ) + # log.warning(res_time) + # log.warning(f" ==== {len(res_data[0])}" ) + # log.warning(f" ==== { res_data[0] }" ) + + # for i in range( len(res_time) ): + # self.__deal_one_measure_time_data(res_time[i], res_data[0][i]) + # pass + # pass + + # def __deal_one_measure_time_data(self,res_time,res_data): + # if self.syscfg['retrieve']['enable'] == 0: + # self.mydir.setContent(res_data ,TOKEN,res_time ) + # self.mydir.writeContent() + # # 插值处理 + # if self.syscfg['retrieve']['enable'] == 1: + # # tmp_data = np.interp( self.new_wavelength, np.array(self.raw_wavelength) , np.array(res_data) ) + + # x = self.new_wavelength + # xp = np.array(self.raw_wavelength).astype(np.float32) + # fp = np.array(res_data).astype(np.float32) + # log.warning(f" {x}") + # log.warning(f" {xp.shape }") + # log.warning(f" { fp.shape }") + # tmp_data = np.interp( x, xp , fp ) + # # tmp_data = np.interp( self.new_wavelength.tolist(), self.raw_wavelength , res_data[0] ) + # self.mydir.setContent( tmp_data ,TOKEN, res_time ) + # self.mydir.writeContent() + # pass + + + # def __deal_one_file(self,fpath): + # res_time,res_data = ReadCal.read_columns_sets_by_mark( fpath, FILE_MARK, 1 ) + # for i in range( len(res_time) ): + # if self.syscfg['retrieve']['enable'] == 0: + # self.mydir.setContent(res_data[i],TOKEN,res_time[i]) + # self.mydir.writeContent() + # # 插值处理 + # if self.syscfg['retrieve']['enable'] == 1: + # self.mydir.setContent(res_data[i],TOKEN,res_time[i]) + # self.mydir.writeContent() + # pass + # pass + + # def __set_serial(self, )-> None: + # self.uart.set_serial_para( + # self.syscfg['comsetting']['port'] + # ,self.syscfg['comsetting']['baudrate'] + # ,self.syscfg['comsetting']['bytesize'] + # ,self.syscfg['comsetting']['parity'] + # ,self.syscfg['comsetting']['stopbit'] + # ) + + # def __set_modbus(self, beginaddress, step)-> None: + # self.uart.set_modbus( + # self.syscfg['register']['slaveadress'] + # ,self.syscfg['register']['functioncode'] + # ,beginaddress + # ,step + # ) \ No newline at end of file