dealOneMeasurement_Profiler

server
esea_info 3 years ago
parent d9604c4483
commit 51609549e0
  1. 1
      .gitignore
  2. 3
      README.md
  3. 200
      Ramses.py
  4. 115
      app.py
  5. 132
      atest.py
  6. 237
      configuration.py
  7. 322
      myconfig.py
  8. 1090
      profiler.py
  9. 1008
      readcal.py
  10. 476
      receive.py
  11. 234
      tcp_profiler.py
  12. 0
      tools/__init__.py
  13. 11
      tools/myexception.py
  14. 285
      tools/mylogger.py
  15. 265
      tools/mypath.py
  16. 66
      tools/mytime.py

1
.gitignore vendored

@ -1,6 +1,7 @@
/__pycache__/
/dist/
/build/
/tools/__pycache__/
/*/__pycache__/
/data/output/
*.log

@ -0,0 +1,3 @@
HANDHELD 接收及数据处理程序
分支:server desktop

@ -0,0 +1,200 @@
#! python3
# -*- encoding: utf-8 -*-
'''
@File : Ramses.py
@Time : 2023/03/03 11:09:50
@Author : Jim @ Yiwin
@Version : 1.0
@Contact : jim@yi-win.com
@Desc :
@para : 23 ..07 .... 06 05 04 03 02 01 00
ip信息不包含
'''
import struct
import numpy as np
from pathlib import Path
from tools.mylogger import log
from myconfig import RamsesAWRAMS, RamsesSURFACE, RamsesPROFILE, DeviceType
class Ramses(object):
def __init__(self,):
"""
@description :处理Ramses的数据标定 Hex -- realWavelength Intensity
@param : 23 ..07 .... 06 05 04 03 02 01 00
ip信息不包含
@Returns : realWavelength Intensity
"""
self.buf = b''
self.it = None
self.light_int = None # 未标定的整数值
self.spectrum = None # 光谱强度
# self.current_buf = ""
# self.current_buf_seq = 0
# self.current_it_int = {"it": 0, "light_int": []} # 积分时间及换算的整数值
# self.res = {"wavelength": [], "light": []}
self.cal_cfg = {}
# self.current_cal = {} # 当前传感器的序列号
pass
def setBuf(self, buf: bytes):
self.buf = buf
pass
def setCalCfg(self, d: dict):
self.cal_cfg = d
pass
def getRealWavelength(self, d: dict):
self.cal_cfg = d
pass
def getSpectrum(self):
return self.spectrum
def resetPara(self, ):
self.buf = b''
self.it = None
self.light_int = None
self.spectrum = None # 光谱强度
self.cal_cfg = {}
pass
def resetItSpectrum(self, ):
self.it = None
self.spectrum = None # 光谱强度
pass
def printPara(self, ):
print(f"**************Ramses printPara*******************")
print(f"{self.buf}")
print(f"{self.cal_cfg}")
print(f"{self.it}")
print(f"{self.light_int}")
print(f"{self.spectrum}")
print(f"**************Ramses printPara*******************")
pass
def dealBuf(self, ip_included:bool=False):
"""多个传感器的数据处理, 头部是否包含Ip帧的信息"""
log.info(f" dealBuf ", __name__)
res = {}
len_ = len(self.buf)
if len_ < 576:
return
if ip_included:
self.buf = self.buf[26:]
len_ = len_ - 26
if len_ % 576 != 0:
return
for i in range(int(len_/576)):
res.update({i+1: {}})
temp_buf = self.buf[7:71] + self.buf[79:143] + \
self.buf[151:215] + self.buf[223:287] + \
self.buf[295:359] + self.buf[367:431] + \
self.buf[439:503] + self.buf[511:575]
self.ConvertAndCalibrate( temp_buf )
# print(len(temp_buf))
temp = self.__ConvertBytesToInt(temp_buf)
res.update( { i+1: temp } )
# print(res)
pass
def ConvertAndCalibrate(self,) -> None:
log.debug(f" ConvertAndCalibrate ", __name__)
temp = self.__ConvertBytesToInt( )
self.__CalibrateSpectrumData( )
pass
# 转换一个传感器的部分
def __ConvertBytesToInt(self ) -> None:
res = {}
d = [] # List [ Tuple[ it:int, sing_set:tuple[int] ] ]
self.it = 2 << int(self.buf[1]) # integrated time
self.light_int = struct.unpack(
"<HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH \
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH \
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH \
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH", self.buf[2:])
def __CalibrateSpectrumData(self ,) :
t0 = 8092
log.debug(f" __CalibrateSpectrumData ..... ", __name__)
raw = np.asarray(self.light_int, dtype=float)
B0 = np.asarray(self.cal_cfg["b0"], dtype=float)
B1 = np.asarray(self.cal_cfg["b1"], dtype=float)
Mn = raw/65535
Bn = B0 + B1 * (self.it/t0)
Cn = Mn-Bn
Offset = self.getOffset(
Cn, int(self.cal_cfg['DarkPixelStart']), int(self.cal_cfg['DarkPixelStop']))
Dn = Cn-Offset
En = Dn * (t0/self.it)
Fn = En/np.asarray(self.cal_cfg["cal"], dtype=float) # 空气或水中的标定文件
self.spectrum = Fn
def getOffset(self, data: np.ndarray, start: int, stop: int):
ret = 0.0
for i in range(start-1, stop, 1):
ret = ret + data[i]
return ret / (stop - start + 1)
pass
# def read_bin(self,fpath: Path):
# log.debug(f" readbin: ", __name__, "", "" )
# ret = None
# if not fpath.exists() :
# log.info(f"not find file: {fpath} ")
# return ret
# with open(fpath, 'rb') as file:
# ret = file.read()
# return ret
# log.debug(f" readbin: {ret} ", __name__, "", "" )
# return ret
# pass
if __name__ == "__main__":
log.info(f"******** Awarms server initiate *********", __name__, "", "")
r = Ramses()
buf_str = "\
23a0000007fefe0a0781067d067d068e0693069c069c06b006b506cb06e40619076607e1076c081509cd09bb0a7d0bee0b1d0c6d0cca0ca40ddc0f30135b18b4224d320e43f852c8\
23a0000006fefe17639c71c97c9484bb89358be98e5d98b1a37eadccb66abd26be31b97db124aa18a3f29c0499349735968e93a48eea8a028bc28cec8d048f1c92c096de9ab99d43\
23a0000005fefee0a157a9ecb1b1b97dc034c507c741c7d2c65ec550c20dbde9b535ae56a60a9e2296cd8ee887278129798170c669b16503632e61605f3a5def5a8e5862561154be\
23a0000004fefe3c51f54dda4a0c48634595426a3f5a3cc539903767362b36cc351f356634b633fc32c4310630fb2ec32fe63199349037e03ac03dc03eae3c303a9639d13a413da7\
23a0000003fefe97412746bc49404caa4dc54d374ca646d63bde326b332739e43c503d2b3c363aca37ef342d32c22f782d1d2bd328ec250222101e691b2b1a7119d3184018fa174d\
23a0000002fefed3177a17e3160616f81423149313f11233126711d8103b10a40f160f8a0efb0d580d660c6f0bd80aa10a580a000ab4099b0994097109e2082c087a0736072c077d\
23a0000001fefe2a071e071607140718071e073c074d076a076e076b076007670763076c0760075c073d07350724071207fb06ef06d706cc06b706a506960684067b0672066306a2\
23a0000000fefe58065406500642064e064306470642063f064806410644064306430641064206460640063c063e063e063d064406430644063c063c063c063c06400640064906ed\
23a0000007fefe0a071b071c07260737073e0749075907650774078b07c0072c08e3082b0ada0be80d9c107b147318931ae51add1a271a77192f1bfb1d99207c265c30c738f03d53\
23a0000006fefe07438f489d4d8452d957945cff639171a5832a97deab7fbe09c86cc5acb9d5ab299e90915287de7f8b7ae275ed6f056aff664f662665bc63936335655767926879\
23a0000005fefec269206d3e724377fe7b7a8050831f85b68637881689e4884787008580823d7f887bee773d7496702a6cde654c5f895a1f570d5416514d4e9d4bde4897468c44c3\
23a0000004fefe71421640db3dc83bbb39533777346c31b92e912c152b5b2aff292129e727cb26d925fd249223b4214020da1fe91ff41f28209420dc201520071e671c221c8d1cfe\
23a0000003fefecd1dd31fe72164235924cb24b924f72331211e1ca018ef19221d121f621fe91e081ed51c761b311a2f193c18651788166015a013de11d1106e1041101810e80f2e\
23a0000002fefee50fd90fbc0f6d0ff70e610ee00d930d460de40c900c450c010cbd0b7c0b480bfc0aab0a2c0a9e094d092b09fb08d008a208990881087d083908e6078d07660747\
23a0000001fefe5b075a07500751074d074e0751075d076807730788077e077c077c07810777077a076c0765075c075607480740073607270723070d070d070b07ff06fd06f0062f\
23a0000000fefef606f106ed06f506ef06eb06f106ec06f006e906e806ed06e606ef06e506ea06ec06ee06eb06e906ee06f006ef06ea06e906e606e606e606ec06ea06ea06f506f2\
23a0000007fefe0605830479047d047e04810482048204850487048b048c04850487048c049304950498049c04a804a904b604b804c604d004e104f104190546059805ff059a06bb\
23a0000006fefe90073209ea0b7610c117cc22b2324a487b645e8798acf2c927d28dc1f2a1ac809664804e543d7a308327a321d81dab1b0f1bca1bb41dba2098243329382e773335\
23a0000005fefeca38213e544329486f4c1c500653335592564f577d573b57a556b4557e540a534451424f004d714a9b47994458410e3e9c3af8368c33b630982eca2c052b3429ae\
23a0000004fefe632763255a234821321f0e1d061b291983171e16d814a91379124b1138104b0f610e990dd80c240c880bfc0a7b0af8097709020990082508de07c507ba07a50762\
23a0000003fefe950781076407460727070007d306ab066e06270605060d0614061306fe05e805d105b405a00586057105630549053d0528051105fd04f304ee04e404dc04dd04c3\
23a0000002fefed804d904d004c604bf04b904b904b104a804a604a6049d04980496048f04970491048c04880486047e0484047a047d047b047c0478047a04760476047004700430\
23a0000001fefe6f0474046c046d0472046d047304750470046e04760472046f047604700473046f04730470047504700470046d046b047004710470046e046d046a046b046904e4\
23a0000000fefe690470046e046b046c04680468046e0466046a046a0469046b046d04640466046c046c046b046a04660466046b046c046a046a0468046f046804740471048d0417\
"
buf = bytearray.fromhex(buf_str)
one_senor = buf[:576]
r.setHex(one_senor)
r.ConvertBytesToInt()
# print(len(buf))
# # print(buf[:576])
# print(buf[:576].hex())
# print(buf[576:578].hex() )

115
app.py

@ -0,0 +1,115 @@
from pathlib import *
from tools.mylogger import log
from configuration import Configuration
from receive import MyServer,MyThreadingTCPServer
from myconfig import MyConfig,DeviceType
from myconfig import DEVICE_ID ,FILE_MARK,YAML_FILE_NAME,CURRENT_DIR,DATA_DIR,CAL_DIR
from myconfig import BEGIN_WAVELENGTH,END_WAVELENGTH,INTERVAL,ROWFACTOR
from Ramses import Ramses
IP = ""
PORT = 7887
ADDRESS = (IP, PORT) # 绑定地址
if __name__ == "__main__":
log.info(f"******** HandHeld server initiate.... *********", __name__, "", "")
#######################################
device_id = DEVICE_ID # 多个设备
device_type = DeviceType.AWRAMS.name
mycfg = MyConfig()
# 配置反演需要的参数 波长 间隔
retrieve = mycfg.get_retrieve()
log.info(f"Retrieve: {retrieve}", __name__, "", "")
# log.info(f"syscfg: {device}", __name__, "", "")
mycfg.setDeviceType(DeviceType.AWRAMS)
init_para = mycfg.read_yaml()
log.info(f"Current Device: {device_type} ", __name__, "", "")
log.info(f"Sensor: {init_para}", __name__, "", "")
cal_cfg = {}
cfgr = Configuration( )
cfgr.setDeviceType(device_type)
cfgr.setSystemCfgDict(init_para)
for k,v in init_para.items():
cfgr.setSystemCfgDict(v)
try:
cfgr.getCalConfiguration()
except Exception as e:
log.error(f"读取配置文件失败. \n {e}",__name__, "", "" )
raise
log.info(f"v: {cfgr.configuration}", __name__, "", "")
cal_cfg.update({k:cfgr.cal_configuration})
# log.warning(f"cal_cfg: {cal_cfg}", __name__, "", "")
log.warning(f"cal_cfg 2: {cal_cfg[2].keys()}", __name__, "", "")
log.warning(f"cal_cfg 3: {cal_cfg[3].keys()}", __name__, "", "")
log.info(f"传感器配置文件读取成功", __name__, "", "")
# ????????????
# 不同设备类型接收不同,修改receive.py
# 不同数据裂隙数据处理不同,修改AWRAMS.py
# 分支:服务器:处理不同的文件夹 awramse surface profile c
# 桌面: 服务器的, 读取标准trios文件处理的 -- 暂不考虑
# 启动接受服务器
log.info(f"启动接受服务器, IP: {IP} , Port:{PORT} ", __name__, "", "")
server_ = MyThreadingTCPServer(ADDRESS, MyServer, cfg=cal_cfg, retrieve = retrieve )
try:
server_.serve_forever()
except KeyboardInterrupt:
log.warning(" Ctrl+C 退出主程序 ",__name__, "", "")
server_.server_close()
except Exception as e:
log.info(" 系统异常, 如下: \n ",__name__, "", "")
log.info(e)
# r= Ramses()
# p = Path("0.bin")
# buf = r.read_bin(p)
# print(buf.hex())
# buf_str= "\
# 23a0000007fefe0a0781067d067d068e0693069c069c06b006b506cb06e40619076607e1076c081509cd09bb0a7d0bee0b1d0c6d0cca0ca40ddc0f30135b18b4224d320e43f852c8\
# 23a0000006fefe17639c71c97c9484bb89358be98e5d98b1a37eadccb66abd26be31b97db124aa18a3f29c0499349735968e93a48eea8a028bc28cec8d048f1c92c096de9ab99d43\
# 23a0000005fefee0a157a9ecb1b1b97dc034c507c741c7d2c65ec550c20dbde9b535ae56a60a9e2296cd8ee887278129798170c669b16503632e61605f3a5def5a8e5862561154be\
# 23a0000004fefe3c51f54dda4a0c48634595426a3f5a3cc539903767362b36cc351f356634b633fc32c4310630fb2ec32fe63199349037e03ac03dc03eae3c303a9639d13a413da7\
# 23a0000003fefe97412746bc49404caa4dc54d374ca646d63bde326b332739e43c503d2b3c363aca37ef342d32c22f782d1d2bd328ec250222101e691b2b1a7119d3184018fa174d\
# 23a0000002fefed3177a17e3160616f81423149313f11233126711d8103b10a40f160f8a0efb0d580d660c6f0bd80aa10a580a000ab4099b0994097109e2082c087a0736072c077d\
# 23a0000001fefe2a071e071607140718071e073c074d076a076e076b076007670763076c0760075c073d07350724071207fb06ef06d706cc06b706a506960684067b0672066306a2\
# 23a0000000fefe58065406500642064e064306470642063f064806410644064306430641064206460640063c063e063e063d064406430644063c063c063c063c06400640064906ed\
# 23a0000007fefe0a071b071c07260737073e0749075907650774078b07c0072c08e3082b0ada0be80d9c107b147318931ae51add1a271a77192f1bfb1d99207c265c30c738f03d53\
# 23a0000006fefe07438f489d4d8452d957945cff639171a5832a97deab7fbe09c86cc5acb9d5ab299e90915287de7f8b7ae275ed6f056aff664f662665bc63936335655767926879\
# 23a0000005fefec269206d3e724377fe7b7a8050831f85b68637881689e4884787008580823d7f887bee773d7496702a6cde654c5f895a1f570d5416514d4e9d4bde4897468c44c3\
# 23a0000004fefe71421640db3dc83bbb39533777346c31b92e912c152b5b2aff292129e727cb26d925fd249223b4214020da1fe91ff41f28209420dc201520071e671c221c8d1cfe\
# 23a0000003fefecd1dd31fe72164235924cb24b924f72331211e1ca018ef19221d121f621fe91e081ed51c761b311a2f193c18651788166015a013de11d1106e1041101810e80f2e\
# 23a0000002fefee50fd90fbc0f6d0ff70e610ee00d930d460de40c900c450c010cbd0b7c0b480bfc0aab0a2c0a9e094d092b09fb08d008a208990881087d083908e6078d07660747\
# 23a0000001fefe5b075a07500751074d074e0751075d076807730788077e077c077c07810777077a076c0765075c075607480740073607270723070d070d070b07ff06fd06f0062f\
# 23a0000000fefef606f106ed06f506ef06eb06f106ec06f006e906e806ed06e606ef06e506ea06ec06ee06eb06e906ee06f006ef06ea06e906e606e606e606ec06ea06ea06f506f2\
# 23a0000007fefe0605830479047d047e04810482048204850487048b048c04850487048c049304950498049c04a804a904b604b804c604d004e104f104190546059805ff059a06bb\
# 23a0000006fefe90073209ea0b7610c117cc22b2324a487b645e8798acf2c927d28dc1f2a1ac809664804e543d7a308327a321d81dab1b0f1bca1bb41dba2098243329382e773335\
# 23a0000005fefeca38213e544329486f4c1c500653335592564f577d573b57a556b4557e540a534451424f004d714a9b47994458410e3e9c3af8368c33b630982eca2c052b3429ae\
# 23a0000004fefe632763255a234821321f0e1d061b291983171e16d814a91379124b1138104b0f610e990dd80c240c880bfc0a7b0af8097709020990082508de07c507ba07a50762\
# 23a0000003fefe950781076407460727070007d306ab066e06270605060d0614061306fe05e805d105b405a00586057105630549053d0528051105fd04f304ee04e404dc04dd04c3\
# 23a0000002fefed804d904d004c604bf04b904b904b104a804a604a6049d04980496048f04970491048c04880486047e0484047a047d047b047c0478047a04760476047004700430\
# 23a0000001fefe6f0474046c046d0472046d047304750470046e04760472046f047604700473046f04730470047504700470046d046b047004710470046e046d046a046b046904e4\
# 23a0000000fefe690470046e046b046c04680468046e0466046a046a0469046b046d04640466046c046c046b046a04660466046b046c046a046a0468046f046804740471048d0417\
# "
# buf = bytearray.fromhex(buf_str)
# one_senor = buf
# r.setBuf(one_senor)
# r.setCalCfg(cal_cfg[2]["Lsky"])
# r.dealBuf()
# print(r.cal_cfg)

@ -0,0 +1,132 @@
from pathlib import *
from mylogger import log
# from awrams.readfile import Readfile
# from awrams.AWRAMS import AWRAMS
from configuration import Configuration
# import struct
# import threading
# import socketserver
# from socketserver import ThreadingTCPServer,TCPServer,ThreadingMixIn
# from myserver import MyThreadingTCPServer,MyTCPServer
from receive import MyServer, MyThreadingTCPServer
from myconfig import MyConfig, DeviceType
from myconfig import DEVICE_ID, FILE_MARK, YAML_FILE_NAME, CURRENT_DIR, DATA_DIR, CAL_DIR
from myconfig import BEGIN_WAVELENGTH, END_WAVELENGTH, INTERVAL, ROWFACTOR
from Ramses import Ramses
from AWRAMS import AWRAMS
IP = ""
PORT = 7887
ADDRESS = (IP, PORT) # 绑定地址
if __name__ == "__main__":
log.info(f"******** Awarms server initiate *********", __name__, "", "")
#######################################
device_id = DEVICE_ID # 多个设备
device_type = DeviceType.AWRAMS.name
mycfg = MyConfig()
mycfg.setDeviceType(DeviceType.AWRAMS)
init_para = mycfg.read_yaml()
log.info(f"Current Device: {device_type} ", __name__, "", "")
log.info(f"Sensor: {init_para}", __name__, "", "")
mycfg.setRetrieveCfg("retrieve.yml")
retrieve = mycfg.read_rtv_yaml()
log.warning(f"Retrieve 反演参数设置: {retrieve}", __name__, "", "")
cal_cfg = {}
# ddd = {"1": {'FUNC': 'Lsky', 'SN': '85B5'}, "2": {'FUNC': 'Esky', 'SN': ['50ED']}, "3": {'FUNC': 'Lwater', 'SN': ['852F']}}
cfgr = Configuration()
cfgr.setDeviceType(device_type)
cfgr.setSystemCfgDict(init_para)
for k, v in init_para.items():
cfgr.setSystemCfgDict(v)
try:
cfgr.getCalConfiguration()
except Exception as e:
log.error(f"读取配置文件失败. \n {e}", __name__, "", "")
raise
log.info(f"v: {cfgr.configuration}", __name__, "", "")
cal_cfg.update({k: cfgr.cal_configuration})
a = AWRAMS()
a.setCfg(cal_cfg)
a.setRetrieve(retrieve)
p = ("data","2","17")
a.setOldFolder(p)
a.readOneFolder( )
# 将参数 begin
# log.warning(f"cal_cfg: {cal_cfg}", __name__, "", "")
# log.warning(f"cal_cfg 2: {cal_cfg[2].keys()}", __name__, "", "")
# log.warning(f"cal_cfg 3: {cal_cfg[3].keys()}", __name__, "", "")
# log.info(f"传感器配置文件读取成功", __name__, "", "")
# ????????????
# 不同设备类型接收不同,修改receive.py
# 不同数据裂隙数据处理不同,修改AWRAMS.py
# 分支:服务器:处理不同的文件夹 awramse surface profile c
# 桌面: 服务器的, 读取标准trios文件处理的 -- 暂不考虑
# # 启动接受服务器
# log.info(f"启动接受服务器, IP: {IP} , Port:{PORT} ", __name__, "", "")
# server_ = MyThreadingTCPServer(ADDRESS, MyServer, cfg=cal_cfg, retrieve=retrieve )
# try:
# server_.serve_forever()
# except KeyboardInterrupt:
# log.info(" Ctrl+C 退出主程序 ")
# server_.server_close()
# except Exception as e:
# log.info(" 系统异常, 如下: \n ")
# log.info(e)
# r= Ramses()
# p = Path("0.bin")
# buf = r.read_bin(p)
# print(buf.hex())
# buf_str= "\
# 23a0000007fefe0a0781067d067d068e0693069c069c06b006b506cb06e40619076607e1076c081509cd09bb0a7d0bee0b1d0c6d0cca0ca40ddc0f30135b18b4224d320e43f852c8\
# 23a0000006fefe17639c71c97c9484bb89358be98e5d98b1a37eadccb66abd26be31b97db124aa18a3f29c0499349735968e93a48eea8a028bc28cec8d048f1c92c096de9ab99d43\
# 23a0000005fefee0a157a9ecb1b1b97dc034c507c741c7d2c65ec550c20dbde9b535ae56a60a9e2296cd8ee887278129798170c669b16503632e61605f3a5def5a8e5862561154be\
# 23a0000004fefe3c51f54dda4a0c48634595426a3f5a3cc539903767362b36cc351f356634b633fc32c4310630fb2ec32fe63199349037e03ac03dc03eae3c303a9639d13a413da7\
# 23a0000003fefe97412746bc49404caa4dc54d374ca646d63bde326b332739e43c503d2b3c363aca37ef342d32c22f782d1d2bd328ec250222101e691b2b1a7119d3184018fa174d\
# 23a0000002fefed3177a17e3160616f81423149313f11233126711d8103b10a40f160f8a0efb0d580d660c6f0bd80aa10a580a000ab4099b0994097109e2082c087a0736072c077d\
# 23a0000001fefe2a071e071607140718071e073c074d076a076e076b076007670763076c0760075c073d07350724071207fb06ef06d706cc06b706a506960684067b0672066306a2\
# 23a0000000fefe58065406500642064e064306470642063f064806410644064306430641064206460640063c063e063e063d064406430644063c063c063c063c06400640064906ed\
# 23a0000007fefe0a071b071c07260737073e0749075907650774078b07c0072c08e3082b0ada0be80d9c107b147318931ae51add1a271a77192f1bfb1d99207c265c30c738f03d53\
# 23a0000006fefe07438f489d4d8452d957945cff639171a5832a97deab7fbe09c86cc5acb9d5ab299e90915287de7f8b7ae275ed6f056aff664f662665bc63936335655767926879\
# 23a0000005fefec269206d3e724377fe7b7a8050831f85b68637881689e4884787008580823d7f887bee773d7496702a6cde654c5f895a1f570d5416514d4e9d4bde4897468c44c3\
# 23a0000004fefe71421640db3dc83bbb39533777346c31b92e912c152b5b2aff292129e727cb26d925fd249223b4214020da1fe91ff41f28209420dc201520071e671c221c8d1cfe\
# 23a0000003fefecd1dd31fe72164235924cb24b924f72331211e1ca018ef19221d121f621fe91e081ed51c761b311a2f193c18651788166015a013de11d1106e1041101810e80f2e\
# 23a0000002fefee50fd90fbc0f6d0ff70e610ee00d930d460de40c900c450c010cbd0b7c0b480bfc0aab0a2c0a9e094d092b09fb08d008a208990881087d083908e6078d07660747\
# 23a0000001fefe5b075a07500751074d074e0751075d076807730788077e077c077c07810777077a076c0765075c075607480740073607270723070d070d070b07ff06fd06f0062f\
# 23a0000000fefef606f106ed06f506ef06eb06f106ec06f006e906e806ed06e606ef06e506ea06ec06ee06eb06e906ee06f006ef06ea06e906e606e606e606ec06ea06ea06f506f2\
# 23a0000007fefe0605830479047d047e04810482048204850487048b048c04850487048c049304950498049c04a804a904b604b804c604d004e104f104190546059805ff059a06bb\
# 23a0000006fefe90073209ea0b7610c117cc22b2324a487b645e8798acf2c927d28dc1f2a1ac809664804e543d7a308327a321d81dab1b0f1bca1bb41dba2098243329382e773335\
# 23a0000005fefeca38213e544329486f4c1c500653335592564f577d573b57a556b4557e540a534451424f004d714a9b47994458410e3e9c3af8368c33b630982eca2c052b3429ae\
# 23a0000004fefe632763255a234821321f0e1d061b291983171e16d814a91379124b1138104b0f610e990dd80c240c880bfc0a7b0af8097709020990082508de07c507ba07a50762\
# 23a0000003fefe950781076407460727070007d306ab066e06270605060d0614061306fe05e805d105b405a00586057105630549053d0528051105fd04f304ee04e404dc04dd04c3\
# 23a0000002fefed804d904d004c604bf04b904b904b104a804a604a6049d04980496048f04970491048c04880486047e0484047a047d047b047c0478047a04760476047004700430\
# 23a0000001fefe6f0474046c046d0472046d047304750470046e04760472046f047604700473046f04730470047504700470046d046b047004710470046e046d046a046b046904e4\
# 23a0000000fefe690470046e046b046c04680468046e0466046a046a0469046b046d04640466046c046c046b046a04660466046b046c046a046a0468046f046804740471048d0417\
# "
# buf = bytearray.fromhex(buf_str)
# one_senor = buf
# r.setBuf(one_senor)
# r.setCalCfg(cal_cfg[2]["Lsky"])
# r.dealBuf()
# print(r.cal_cfg)

@ -0,0 +1,237 @@
from pathlib import Path, PurePath
from tools.mylogger import log
from readcal import ReadCal
from myconfig import CAL_DIR, DATA_DIR, FILE_MARK, DeviceType, RamsesFunc
class Configuration:
def __init__(self, ) -> None:
log.info(f"ConfigAWRAMS init: ", __name__, "", "")
self.device_type = None
self.configuration =None
self.cal_configuration = {}
pass
def setDeviceType(self, device_type:str) -> None:
self.device_type = device_type.lower()
pass
def setSystemCfgDict(self, cfg:dict) -> None:
self.configuration = cfg
log.info(f"self.configuration : {self.configuration} ", __name__, "", "")
pass
def getCalConfiguration(self) -> None:
if self.device_type == None:
self.cal_configuration = None
if self.configuration == None:
self.cal_configuration =None
for k,v in self.configuration.items():
if v["SN"] == "" or v['FUNC']=="":
pass
else:
self.cal_configuration.update( {v["FUNC"]:{}} )
self.cal_configuration[v["FUNC"]].update( {"SN":v['SN']} )
self.cal_configuration[v["FUNC"]].update( {"FUNC":v['FUNC']} )
self.__init_configuration_basic()
self.__init_configuration_cal()
self.__init_configuration_IP_SAM()
pass
def __init_configuration_basic(self ) -> None:
# self.cfgtool = Config()
for k in self.cal_configuration.keys():
sn = self.cal_configuration[k]["SN"]
if self.__isSamIniExisted(sn):
self.cal_configuration[k].update({ "TYPE" : "SAM" })
self.cal_configuration[k].update({ "samsn" : sn })
self.cal_configuration[k].update({ "inifile" : "SAM_"+sn+".ini" })
self.cal_configuration[k].update({ "calfile" : "Cal_SAM_"+sn+".dat" })
self.cal_configuration[k].update({ "calaqfile" : "CalAQ_SAM_"+sn+".dat" })
self.cal_configuration[k].update({ "backfile" : "Back_SAM_"+sn+".dat" })
if self.__isSamIPIniExisted(sn):
self.cal_configuration[k].update({ "TYPE" : "SAMIP" })
samsn = self.__getSAMSN(sn)
if samsn== None:
log.warning(f"Cannot get samsn from Sensor: {sn}", __name__, "", "" )
raise Exception(f"Cannot get samsn from Sensor: {sn}")
self.cal_configuration[k].update({ "samsn" : samsn })
self.cal_configuration[k].update({ "inifile" : "SAMIP_"+sn+"_ALL.ini" })
self.cal_configuration[k].update({ "calfile" : "Cal_SAM_"+samsn+".dat" })
self.cal_configuration[k].update({ "calaqfile" : "CalAQ_SAM_"+samsn+".dat" })
self.cal_configuration[k].update({ "backfile" : "Back_SAM_"+samsn+".dat" })
if not self.__isSamIniExisted(sn) and not self.__isSamIPIniExisted(sn):
log.warning(f"Cannot find ini file for Sensor: {sn}", __name__, "", "" )
raise Exception(f"Cannot find ini file for Sensor: {sn}")
pass
def __init_configuration_cal(self ) -> None:
# self.cfgtool = Config()
for k in self.cal_configuration.keys():
sn = self.cal_configuration[k]["SN"]
# Device File
calpath = CAL_DIR.joinpath(self.device_type, self.cal_configuration[k]["calfile"])
if calpath.exists( ):
res = ReadCal.read_columns_set_by_mark( calpath, FILE_MARK, 1 )
self.cal_configuration[k].update({ "cal" : res[1][0] })
calaqpath = CAL_DIR.joinpath(self.device_type, self.cal_configuration[k]["calaqfile"])
if calaqpath.exists( ):
res = ReadCal.read_columns_set_by_mark( calaqpath, FILE_MARK, 1 )
self.cal_configuration[k].update({ "calaq" : res[1][0] })
backpath = CAL_DIR.joinpath(self.device_type, self.cal_configuration[k]["backfile"])
if calaqpath.exists( ):
res = ReadCal.read_columns_set_by_mark( backpath, FILE_MARK, 1,2 )
self.cal_configuration[k].update({ "b0" : res[1][0] })
self.cal_configuration[k].update({ "b1" : res[1][1] })
pass
def __init_configuration_IP_SAM(self ) -> None:
# self.cfgtool = Config()
for j in self.cal_configuration.keys():
# log.debug(f"__init_configuration_IP_SAM {j}", __name__, "", "" )
inipath = CAL_DIR.joinpath(self.device_type, self.cal_configuration[j]["inifile"])
# log.debug(f"__init_configuration_IP_SAM {inipath}", __name__, "", "" )
sam = ReadCal.readSAMCalFromIni(inipath)
# log.debug(f"__init_configuration_IP_SAM {sam}", __name__, "", "" )
for k,v in sam.items():
self.cal_configuration[j].update({ k : v })
if self.cal_configuration[j]["TYPE"] == "SAMIP":
ip = ReadCal.readIPCalFromIni(inipath)
for k,v in ip.items():
self.cal_configuration[j].update({ k : v })
def __isSamIniExisted(self,sn) ->bool:
sn_0 = "SAM_"+str(sn)+".ini"
path_ = CAL_DIR.joinpath(self.device_type.lower(), sn_0)
if path_.exists():
return True
return False
def __isSamIPIniExisted(self,sn) ->bool:
sn_0 = "SAMIP_"+str(sn)+"_ALL.ini"
path_ = CAL_DIR.joinpath(self.device_type.lower(), sn_0)
if path_.exists():
return True
return False
def __getSAMSN(self,sn) -> None:
sn_0 = "SAMIP_"+str(sn)+"_ALL.ini"
path_ = CAL_DIR.joinpath(self.device_type.lower(), sn_0)
# path_ = DATA_DIR.joinpath(self.device.lower(), CAL_DIR, sn_0)
samsn = ReadCal.readSamSNFromIni( path_ )
if samsn == None:
return None
return samsn
pass
# def __init2__(self, device:str, **kwargs) -> None:
# """
# get cal parameter for every sensor
# para : {"1":{"SN":"85B5","FUNC","Lsky"},"2":{},"3":{}}
# """
# # log.info(f"ProcessAWRAMS kwargs: {kwargs}", __name__, "", "")
# # log.info(f"len: { len(kwargs)}", __name__, "", "")
# if len(kwargs) != 3:
# log.warning(f" pass a wrong para to ProcessAWRAMS {kwargs}", __name__, "", "")
# self.device = device.lower() # surface profile awrams
# self.ramses = {}
# # 生成标定文件 { }
# for k,v in kwargs.items():
# self.ramses.update( {v["FUNC"]:{}} )
# self.ramses[v["FUNC"]].update( {"SN":v['SN']} )
# self.ramses[v["FUNC"]].update( {"FUNC":v['FUNC']} )
# pass
# log.debug(f" ===== {self.ramses}",__name__, "", "" )
# # if kwargs.__contains__("1"):
# # self.ramses.append( self.cfgtool.getDictByAttr("ramses"))
# # self.cfgtool.set_attr(self.ramses[1],kwargs['1']"SN",kwargs['1'])
# # if kwargs.__contains__("2"):
# # self.ramses.append( self.cfgtool.getDictByAttr("ramses"))
# # self.cfgtool.set_attr(self.ramses[2],"SN",kwargs['1'])
# # if kwargs.__contains__("3"):
# # self.ramses.append( self.cfgtool.getDictByAttr("ramses"))
# # self.cfgtool.set_attr(self.ramses[3],"SN",kwargs['1'])
# self.__init_configuration_basic()
# self.__init_configuration_cal()
# self.__init_configuration_IP_SAM()
# # log.info(f"ProcessAWRAMS after initiate: {kwargs}", __name__, "", "")
# def __init_configuration_basic2(self ) -> None:
# # self.cfgtool = Config()
# for k in self.ramses.keys():
# sn = self.ramses[k]["SN"]
# if self.__isSamIniExisted(sn):
# self.ramses[k].update({ "TYPE" : "SAM" })
# self.ramses[k].update({ "samsn" : sn })
# self.ramses[k].update({ "inifile" : "SAM_"+sn+".ini" })
# self.ramses[k].update({ "calfile" : "Cal_SAM_"+sn+".dat" })
# self.ramses[k].update({ "calaqfile" : "CalAQ_SAM_"+sn+".dat" })
# self.ramses[k].update({ "backfile" : "Back_SAM_"+sn+".dat" })
# if self.__isSamIPIniExisted(sn):
# self.ramses[k].update({ "TYPE" : "SAMIP" })
# samsn = self.__getSAMSN(sn)
# if samsn== None:
# log.warning(f"Cannot get samsn from Sensor: {sn}", __name__, "", "" )
# raise Exception(f"Cannot get samsn from Sensor: {sn}")
# self.ramses[k].update({ "samsn" : samsn })
# self.ramses[k].update({ "inifile" : "SAMIP_"+sn+"_ALL.ini" })
# self.ramses[k].update({ "calfile" : "Cal_SAM_"+samsn+".dat" })
# self.ramses[k].update({ "calaqfile" : "CalAQ_SAM_"+samsn+".dat" })
# self.ramses[k].update({ "backfile" : "Back_SAM_"+samsn+".dat" })
# if not self.__isSamIniExisted(sn) and not self.__isSamIPIniExisted(sn):
# log.warning(f"Cannot find ini file for Sensor: {sn}", __name__, "", "" )
# raise Exception(f"Cannot find ini file for Sensor: {sn}")
# pass
# def __init_configuration_cal2(self ) -> None:
# # self.cfgtool = Config()
# for k in self.ramses.keys():
# sn = self.ramses[k]["SN"]
# # Device File
# calpath = CAL_DIR.joinpath(self.device, self.ramses[k]["calfile"])
# if calpath.exists( ):
# res = Readfile.read_columns_set_by_mark( calpath, FILE_MARK, 1 )
# self.ramses[k].update({ "cal" : res[1][0] })
# calaqpath = CAL_DIR.joinpath(self.device, self.ramses[k]["calaqfile"])
# if calaqpath.exists( ):
# res = Readfile.read_columns_set_by_mark( calaqpath, FILE_MARK, 1 )
# self.ramses[k].update({ "calaq" : res[1][0] })
# backpath = CAL_DIR.joinpath(self.device, self.ramses[k]["backfile"])
# if calaqpath.exists( ):
# res = Readfile.read_columns_set_by_mark( backpath, FILE_MARK, 1,2 )
# self.ramses[k].update({ "b0" : res[1][0] })
# self.ramses[k].update({ "b1" : res[1][1] })
# pass
# def __init_configuration_IP_SAM2(self ) -> None:
# # self.cfgtool = Config()
# for j in self.ramses.keys():
# # log.debug(f"__init_configuration_IP_SAM {j}", __name__, "", "" )
# inipath = CAL_DIR.joinpath(self.device, self.ramses[j]["inifile"])
# # log.debug(f"__init_configuration_IP_SAM {inipath}", __name__, "", "" )
# sam = Readfile.readSAMCalFromIni(inipath)
# # log.debug(f"__init_configuration_IP_SAM {sam}", __name__, "", "" )
# for k,v in sam.items():
# self.ramses[j].update({ k : v })
# if self.ramses[j]["TYPE"] == "SAMIP":
# ip = Readfile.readIPCalFromIni(inipath)
# for k,v in ip.items():
# self.ramses[j].update({ k : v })

@ -0,0 +1,322 @@
#! 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
DEVICE_ID = [2]
CURRENT_DIR = Path()
DATA_DIR = Path("data")
CAL_DIR = Path("calfile")
OUTPUT_DIR = Path("data", "output")
YAML_FILE_NAME = "config.yml"
RETRIEVE_CFG_FILE = "retrieve.yml"
FILE_MARK = ['Spectrum', 'DATA']
BEGIN_WAVELENGTH = 350
END_WAVELENGTH = 950
SAVE_EXT_NAME = ".csv"
INTERVAL = 1.0
SEPARATOR = ";"
TOKEN = ";"
NEWLINE = "\n"
ROWFACTOR = 0.026
class DeviceType(Enum) :
AWRAMS = 1
SURFACE = 2
PROFILE = 3
class RamsesFunc(Enum):
Lsky = 1
Esky = 2
Lwater = 3
Lw = 4
Rs = 5
class RamsesAWRAMS(Enum):
Lsky = 1
Esky = 2
Lwater = 3
Lw = 4
Rs = 5
class RamsesSURFACE(Enum):
Lsky = 1
Esky = 2
Lwater = 3
Lw = 4
Rs = 5
class RamsesPROFILE(Enum):
Ed = 1
Esky = 2
Lu = 3 #upwelling
Lw = 4
Rs = 5
IP_CAL = {
"Incl_Orientation": "up",
"Incl_Xgain": 1.0,
"Incl_Xoffset": 125,
"Incl_Ygain": 0.9375,
"Incl_Yoffset": 126,
"Incl_KBG": 1.2073,
"Incl_Kref": 0.1275,
"Press_Current_mA": 1.08,
"Press_Surface_bar": 5.57,
"Press_Gain": 2.7,
"WithIncl": 1,
"WithPress": 1,
"Press_Sens_mV_bar_4mA": 71.36,
"Press_Sens_mV_bar_1mA": 17.84,
"Press_Type": "PA-10/TAB/10bar",
"CalibrationDate": "08.06.2018",
}
RAMSES_CAL = {
"SN": "",
"TYPE": "SAM", # SAMIP or SAM
"FUNC": "Lsky",
"inifile": "",
"calfile": "",
"calaqfile": "",
"backfile": "",
"samsn": "",
"b0": [],
"b1": [],
"cal": [],
"calaq": [],
"DarkPixelStart": 237,
"DarkPixelStop": 254,
"Firmware": 2.06,
"IDDataBack": "DLAB_2016-11-29_14-47-59_729_812",
"IDDataCal": "DLAB_2016-12-07_12-00-24_364_510",
"IDDataCalAQ": "DLAB_2016-12-07_12-02-43_591_545",
"IntegrationTime": 0,
"Reverse": 0,
"SerialNo_MMS": 103307,
"WavelengthRange": "310..1100",
"c0s": 299.895,
"c1s": 3.31161,
"c2s": 0.00031652,
"c3s": -1.73194e-06,
"c4s": +0.000000000E+00,
"cs": 102842,
"savefile": ""
}
class MyConfig(object):
"""
设置 ID对应的传感器
"""
def __init__(self) -> None:
self.device_id = []
self.device_type = None
self.current_device_id = None
self.system_cfg = {}
self.cfg_path = Path()
self.yml_cfg_file = YAML_FILE_NAME
self.retrieve_cfg_file = Path(RETRIEVE_CFG_FILE)
self.system_cal_cfg = {}
self.validate = { }
def addDeviceID(self, id:int) -> None: #
self.device_id.append(id)
pass
def setDeviceID(self, id:int) -> bool: #
if id in self.device_id:
self.current_device_id = id
return True
else:
self.current_device_id = None
return False
pass
def setDeviceType(self, device_type:DeviceType) -> None:
self.device_type = device_type
pass
def setRetrieveCfg(self, rtv_yml:str="") -> None:
if rtv_yml =="":
return None
self.retrieve_cfg_file = Path(rtv_yml)
pass
def getSystemCfg(self,)->None:
'''
不同系统修改此函数或添加函数 getSystemCfg***()供调用
'''
if self.current_device_id == None:
self.system_cfg = None
if self.device_type == None:
self.system_cfg = None
temp_cfg = {}
if self.device_type == DeviceType.AWRAMS:
temp_cfg = {
1: {"SN": "85B5", "FUNC": RamsesAWRAMS(1).name},
2: {"SN": "50ED", "FUNC": RamsesAWRAMS(2).name},
3: {"SN": "852F", "FUNC": RamsesAWRAMS(3).name}
}
if self.device_type == DeviceType.SURFACE:
temp_cfg = {
1: {"SN": "85B5", "FUNC": RamsesSURFACE(1).name},
2: {"SN": "50ED", "FUNC": RamsesSURFACE(2).name},
3: {"SN": "852F", "FUNC": RamsesSURFACE(3).name}
}
if self.device_type == DeviceType.PROFILE:
temp_cfg = {
1: {"SN": "85B5", "FUNC": RamsesPROFILE(1).name},
2: {"SN": "50ED", "FUNC": RamsesPROFILE(2).name},
3: {"SN": "852F", "FUNC": RamsesPROFILE(3).name}
}
self.system_cfg.update( { self.current_device_id : temp_cfg } )
pass
def setCfgRamsesSN(self, sn_cfg: dict)->None:
if len(sn_cfg) == 0:
return None
for k in self.system_cfg[self.current_device_id].keys():
if str(k) in sn_cfg.keys() :
self.system_cfg[self.current_device_id][k]["SN"] = sn_cfg[str(k)]
else:
self.system_cfg[self.current_device_id][k]["SN"] = None
# if k in sn_cfg.keys() :
# self.system_cfg[self.current_device_id][k]["SN"] = sn_cfg[k]
pass
def setSystemCalCfg(self, sn_cfg: dict)->None:
if len(sn_cfg) == 0:
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]):
# print(f"------------{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:
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 get_retrieve(self) -> dict:
retrieve = {}
retrieve.update({"beginWL": BEGIN_WAVELENGTH})
retrieve.update({"endWL": END_WAVELENGTH})
retrieve.update({"interval": INTERVAL})
retrieve.update({"rowFactor": ROWFACTOR})
return retrieve
pass
ramses_buf_str= "\
23a0000007fefe0a0781067d067d068e0693069c069c06b006b506cb06e40619076607e1076c081509cd09bb0a7d0bee0b1d0c6d0cca0ca40ddc0f30135b18b4224d320e43f852c8\
23a0000006fefe17639c71c97c9484bb89358be98e5d98b1a37eadccb66abd26be31b97db124aa18a3f29c0499349735968e93a48eea8a028bc28cec8d048f1c92c096de9ab99d43\
23a0000005fefee0a157a9ecb1b1b97dc034c507c741c7d2c65ec550c20dbde9b535ae56a60a9e2296cd8ee887278129798170c669b16503632e61605f3a5def5a8e5862561154be\
23a0000004fefe3c51f54dda4a0c48634595426a3f5a3cc539903767362b36cc351f356634b633fc32c4310630fb2ec32fe63199349037e03ac03dc03eae3c303a9639d13a413da7\
23a0000003fefe97412746bc49404caa4dc54d374ca646d63bde326b332739e43c503d2b3c363aca37ef342d32c22f782d1d2bd328ec250222101e691b2b1a7119d3184018fa174d\
23a0000002fefed3177a17e3160616f81423149313f11233126711d8103b10a40f160f8a0efb0d580d660c6f0bd80aa10a580a000ab4099b0994097109e2082c087a0736072c077d\
23a0000001fefe2a071e071607140718071e073c074d076a076e076b076007670763076c0760075c073d07350724071207fb06ef06d706cc06b706a506960684067b0672066306a2\
23a0000000fefe58065406500642064e064306470642063f064806410644064306430641064206460640063c063e063e063d064406430644063c063c063c063c06400640064906ed\
23a0000007fefe0a071b071c07260737073e0749075907650774078b07c0072c08e3082b0ada0be80d9c107b147318931ae51add1a271a77192f1bfb1d99207c265c30c738f03d53\
23a0000006fefe07438f489d4d8452d957945cff639171a5832a97deab7fbe09c86cc5acb9d5ab299e90915287de7f8b7ae275ed6f056aff664f662665bc63936335655767926879\
23a0000005fefec269206d3e724377fe7b7a8050831f85b68637881689e4884787008580823d7f887bee773d7496702a6cde654c5f895a1f570d5416514d4e9d4bde4897468c44c3\
23a0000004fefe71421640db3dc83bbb39533777346c31b92e912c152b5b2aff292129e727cb26d925fd249223b4214020da1fe91ff41f28209420dc201520071e671c221c8d1cfe\
23a0000003fefecd1dd31fe72164235924cb24b924f72331211e1ca018ef19221d121f621fe91e081ed51c761b311a2f193c18651788166015a013de11d1106e1041101810e80f2e\
23a0000002fefee50fd90fbc0f6d0ff70e610ee00d930d460de40c900c450c010cbd0b7c0b480bfc0aab0a2c0a9e094d092b09fb08d008a208990881087d083908e6078d07660747\
23a0000001fefe5b075a07500751074d074e0751075d076807730788077e077c077c07810777077a076c0765075c075607480740073607270723070d070d070b07ff06fd06f0062f\
23a0000000fefef606f106ed06f506ef06eb06f106ec06f006e906e806ed06e606ef06e506ea06ec06ee06eb06e906ee06f006ef06ea06e906e606e606e606ec06ea06ea06f506f2\
23a0000007fefe0605830479047d047e04810482048204850487048b048c04850487048c049304950498049c04a804a904b604b804c604d004e104f104190546059805ff059a06bb\
23a0000006fefe90073209ea0b7610c117cc22b2324a487b645e8798acf2c927d28dc1f2a1ac809664804e543d7a308327a321d81dab1b0f1bca1bb41dba2098243329382e773335\
23a0000005fefeca38213e544329486f4c1c500653335592564f577d573b57a556b4557e540a534451424f004d714a9b47994458410e3e9c3af8368c33b630982eca2c052b3429ae\
23a0000004fefe632763255a234821321f0e1d061b291983171e16d814a91379124b1138104b0f610e990dd80c240c880bfc0a7b0af8097709020990082508de07c507ba07a50762\
23a0000003fefe950781076407460727070007d306ab066e06270605060d0614061306fe05e805d105b405a00586057105630549053d0528051105fd04f304ee04e404dc04dd04c3\
23a0000002fefed804d904d004c604bf04b904b904b104a804a604a6049d04980496048f04970491048c04880486047e0484047a047d047b047c0478047a04760476047004700430\
23a0000001fefe6f0474046c046d0472046d047304750470046e04760472046f047604700473046f04730470047504700470046d046b047004710470046e046d046a046b046904e4\
23a0000000fefe690470046e046b046c04680468046e0466046a046a0469046b046d04640466046c046c046b046a04660466046b046c046a046a0468046f046804740471048d0417\
"
if __name__ == "__main__":
cfg = MyConfig()
cfg.addDeviceID(2)
cfg.addDeviceID(3)
cfg.setDeviceType(DeviceType.AWRAMS)
cfg.setDeviceID(2)
cfg.getSystemCfg()
print(cfg.system_cfg)
d = {"1":"8888","2":["7777"],"3":["9999"]}
cfg.setCfgRamsesSN(d)
print("修改后。。。。。\n")
print(cfg.system_cfg)
# cfg.write_yaml( cfg.system_cfg)
dd = cfg.read_yaml()
# dd 作为cfg.system_cfg 使用
for k,v in dd.items():
print(k)
print(type(k))
retrieve = {
"beginWL": 350,
"endWL": 950,
"interval": 1,
"rowFactor": 0.026
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,476 @@
#!/usr/bin/env python
# coding:utf-8
'''
# 因为图片帧不是必须,必须按帧处理数据。 可能摄像头坏掉,没有传感器数据??
# 按帧处理数据,必须在每帧接收完毕判断,数据是否完整, 完整则进一步处理 !!!!!!!!!!!!
# 时间作为目录
'''
import socket
import socketserver
from socketserver import TCPServer,ThreadingMixIn
import threading
# import datetime
import time
# import os
import struct
from tools.mypath import MyDir
from tools.mylogger import log
from pathlib import Path,PurePath
from myconfig import DATA_DIR,DeviceType
from profiler import Profiler
IP = ""
PORT = 7887
ADDRESS = (IP, PORT) # 绑定地址
# LOGGING_LEVEL = logging.DEBUG
# LOGGING_LEVEL = logging.INFO
# LOGGING_LEVEL = logging.WARNING
DATA_FRAME_HEAD = b'\x11\x13\x55\xaa'
DATA_FRAME_TAIL = b'\xff\xd9'
PIC_BEGIN_BYTES = b'\xff\xd8'
# 连接超时
TIMEOUT_SECOND = 8 * 3600
# 连接线程池
conn_pool = []
# save_path = Path
class MyTCPServer(TCPServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, cfg=None, retrieve=None):
self.cfg = cfg
self.retrieve = retrieve
TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=True )
class MyThreadingTCPServer(ThreadingMixIn, MyTCPServer): pass
class MyException(Exception):
def __init__(self, message="自定义异常"):
self.message = message
class illumination_sensor:
def __init__(self, socket: socket.socket) -> None:
self.__buf = b''
self.__head = {
# "id" : -1, # 设备id
# 'type' : -1, # 类型 信息 传感器 图片
# 'num' : -1, # 光学传感器的第几次测量
# 'con' : -1, # 总的测量序号
# 'size' : -1, # 字节大小
# 'packet_con' : -1, # 第几帧
# 'packet_all' : -1, # 总帧数
# 'head' : b'', # 帧头
# 'payload' : b'' # 具体内容
}
self.state = 0
self.socket = socket
self.id = 0
# self.is_data_complete = {
# "info_frame": False,
# 'sensor_frame': False,
# 'pic_frame': False
# }
# self.data = {
# "info_frame": {},
# 'sensor_frame': {},
# 'pic_frame': {}
# }
self.timeout_base = int(time.time())
def set_id(self, id) -> None: # 对应设备ID
self.id = id
# def set_socket(self,socket:socket.socket) -> socket.socket:
# tmp = self.socket
# self.socket=socket
# return tmp
def read_buf(self, size: int) -> bytes:
if size > self.__buf.__len__():
return b''
ret = self.__buf[0:size]
self.__buf = self.__buf[size:]
return ret
def write_buf(self, buf: bytes) -> None:
id = self.id
len = buf.__len__()
# logging.info(f'Received ID:{id} Size:{len}')
self.__buf = self.__buf+buf
def get_buf_size(self) -> int:
return self.__buf.__len__()
def back_bytes(self, buf: bytes) -> None:
self.__buf = buf+self.__buf
def reset_head(self) -> None:
self.__head = {}
# self.__head['id'] = -1
# self.__head['type'] = -1
# self.__head['num'] = -1
# self.__head['con'] = -1
# self.__head['size'] = -1
# self.__head['packet_con'] = -1
# self.__head['packet_all'] = -1
# self.__head['head'] = b''
# self.__head['payload'] = b''
def reset_data(self) -> None:
self.data['info_frame']: dict = {}
self.data['sensor_frame']: dict = {}
self.data['pic_frame']: dict = {}
def decode(self) -> dict:
if self.__head == {}:
while self.get_buf_size() >= 15:
if self.read_buf(1) != b'\x11':
continue
c = self.read_buf(1)
if c != b'\x13':
self.back_bytes(c)
continue
c = self.read_buf(1)
if c != b'\x55':
self.back_bytes(c)
continue
c = self.read_buf(1)
if c != b'\xaa':
self.back_bytes(c)
continue
head = self.read_buf(11)
head_list = struct.unpack('<HBIHBB', head)
self.__head['id'] = head_list[0]
self.__head['type'] = head_list[1] >> 4
self.__head['num'] = head_list[1] & 0x0f
self.__head['con'] = head_list[2]
self.__head['size'] = head_list[3]
self.__head['packet_con'] = head_list[4]
self.__head['packet_all'] = head_list[5]
self.__head['head'] = b'\x11\x13\x55\xaa'+head
break
if self.__head != {}:
# 判断是否是测量结束标志
if self.__head['type'] == 15:
log.info(f" end frame recieved! ")
self.__head['payload'] = b'\xff\xff'
data = self.__head.copy()
self.__head = {}
self.id = data['id']
return data
pass
payload = self.read_buf(self.__head['size'])
if payload != b'':
self.__head['payload'] = payload
data = self.__head.copy()
self.__head = {}
self.id = data['id']
return data
return {}
class DealData:
"""
@description : 调用AWRAMS类处理数据
@param :
@Returns :
"""
def __init__(self) -> None:
self.device_id = None
self.devie_type = DeviceType.SURFACE.name
self.measure_id = None
self.cfg = {}
self.profiler = None
pass
def deal(self, id: int, con: int, cfg:dict , retrieve) -> None: # 取字典中的 payload
log.info(f" 接收到数据开始处理数据 device_id {id} ")
self.device_id = id
self.measure_id = con
if self.device_id is None:
self.device_id = id
if self.cfg == {}:
self.cfg = cfg
# self.cfg = cfg.get(self.device_id)
if self.profiler is None:
self.profiler = Profiler() ##处理数据
self.profiler.setSyscfg(self.cfg)
self.profiler.setRetrieve(retrieve)
self.profiler.setDeviceID(self.device_id)
self.profiler.setMeasureID(self.measure_id)
path_tuple = ( "data", str(id), str(con) )
self.profiler.setOldFolder( path_tuple )
self.profiler.getInfoDict( )
self.profiler.transferFromOldFolder()
self.profiler.deleteOldFolder()
self.profiler.dealOneMeasurement_Profiler(self.profiler.new_folder)
log.info(f" Complete Dealing one group.")
# self.profiler.readOneFolder( )
@staticmethod
def read_bin(fpath:Path):
ret = None
if fpath.exists() == False:
log.warning(f"not find file: {fpath} ")
return ret
ret = fpath.read_bytes()
# with open( fpath, 'rb') as file:
# ret = file.read()
# return ret
return ret
pass
@staticmethod
def decode_info(info: bytes) -> dict:
ret = {}
try:
temp = struct.unpack( "<BBBBBBHHHHHHIIHHHHHBBBHHIfffIIIII", info )
except Exception as e:
log.info( "decode info 有误, 收到info frame 字节有误" )
return ret
time_ = "20"+f"{temp[0]:02d}" + "-" + f"{temp[1]:02d}" + "-" + f"{temp[2]:02d}" + " " \
+ f"{temp[3]:02d}" + ":" + f"{temp[4]:02d}" + ":" + f"{temp[5]:02d}"
ret.update({"time": time_})
ret.update({"year": temp[0]})
ret.update({"month": temp[1]})
ret.update({"day": temp[2]})
ret.update({"hour": temp[3]})
ret.update({"minute": temp[4]})
ret.update({"second": temp[5]})
ret.update({"Roll": temp[6]})
ret.update({"Pitch": temp[7]})
ret.update({"Yaw": temp[8]})
ret.update({"Hx": temp[9]})
ret.update({"Hy": temp[10]})
ret.update({"Hz": temp[11]})
ret.update({"lon": temp[12]})
ret.update({"lat": temp[13]})
ret.update({"satelite_num": temp[14]})
ret.update({"PDOP": temp[15]})
ret.update({"HDOP": temp[16]})
ret.update({"VDOP": temp[17]})
ret.update({"Temperature": temp[18]})
ret.update({"Humidity": temp[19]})
ret.update({"Battery": temp[20]})
ret.update({"ErrorCode": temp[21]})
ret.update({"Azimuth": temp[22]})
ret.update({"RunAngle": temp[23]})
ret.update({"MeasuyeGroupNum": temp[24]})
ret.update({"Tiltx": temp[25]})
ret.update({"Tilty": temp[26]})
ret.update({"Depth": temp[27]})
ret.update({"Sensor1": hex(temp[28])[2:].upper()}) # 28 27 转16进制
ret.update({"Sensor2": hex(temp[29])[2:].upper()}) # 30 29
ret.update({"Sensor3": hex(temp[30])[2:].upper()}) # 32 31
ret.update({"Measure_Num": temp[31]}) # 33
ret.update({"Measure_Interval": temp[32]}) # 34
ret.update({"Measure_Repeat": temp[33]}) # 35
return ret
pass
@staticmethod
def save_dict_to_file(info_dict:dict, fpath:Path) ->None:
temp_str = ""
for key, value in info_dict.items():
temp_str = temp_str + key + " : " + str(value) + "\n"
with open(fpath, "w+") as f:
f.write(temp_str)
ret = None
if fpath.exists() == False:
log.info(f"not find file: {fpath} ")
return ret
with open(fpath, 'rb') as file:
ret = file.read()
return ret
return ret
pass
@staticmethod
def check_spectrum_data(dst_dir:Path):
# 判断目录下是否有 0.bin ...15.bin 文件
sensor_file_list = dst_dir.glob( '*[0-9].bin' )
fname_without_ext = []
for fl in sensor_file_list:
temp = fl.stem
if not temp.isdigit:
log.warning( f" {dst_dir} 目录光谱文件的文件名 {temp} 不为数字,type:{type(temp)},请检查异常" )
return False
fname_without_ext.append( int(temp) )
if len(fname_without_ext) ==0:
log.warning( f" {dst_dir} 目录没有发现光谱文件,请检查异常" )
return False
# 排序,然后检查是否有遗漏项
fname_without_ext.sort()
for i in fname_without_ext:
if fname_without_ext[i] !=i:
log.warning( f" {dst_dir} 目录,序号{i}光谱文件的文件名没有发现,请检查异常" )
return False
return False
pass
@staticmethod
def calibrate_spectrum_data(dst_dir):
'''
用ini back 等文件获得标定后数据
'''
log.info("calibrate_spectrum_data.... ")
pass
@staticmethod
def retrieve_data(dst_dir):
'''
反演遥感反射率等参数
'''
log.info(" retrieve_data.... ")
pass
# 收到的全部扔到 sensor.bin, 追加保存
def save(self,data: dict) -> None:
log.info(f"save .....to first dir {str(data['con'])} - type:{data['type']} - num {data['num']}")
# 路径 传感器id/测量序号(唯一) -- 处理数据时候改时间
saveDir = DATA_DIR.joinpath(str(data['id']), str(data['con']) )
if saveDir.exists() == False:
saveDir.mkdir(parents=True)
if data['type'] == 0:
log.debug( f" {data['type']} - {data['num']}")
fpath = saveDir.joinpath("info.bin")
fpath.write_bytes( data['payload'] )
elif data['type'] == 1:
log.debug( f" {data['type']} - {data['num']}")
senor_path = saveDir.joinpath( "sensor.bin" )
with open( senor_path, "ab+") as f:
f.write(data['payload'])
pass
elif data['type'] == 2:
pass
else:
pass
# class MyServer(socketserver.BaseRequestHandler):
class MyServer(socketserver.BaseRequestHandler):
def setup(self) -> None:
log.debug(f"retrieve {self.server.retrieve}",__name__, "", "" )
self.cfg =self.server.cfg
self.retrieve =self.server.retrieve
self.sk: socket.socket = self.request
self.sensor = illumination_sensor(self.request)
self.dealData = DealData()
self.begin_time = time.time()
conn_pool.append(self.client_address)
pass
def handle(self) -> None:
log.info('... connected from {}'.format(self.client_address),'__name__')
while True:
# self.request.recv 方法接收客户端发来的消息
try:
data_byte = self.sk.recv(1000)
except ConnectionResetError as e:
log.warning(
f"recv ConnectionResetError, client {self.client_address} had close .....")
break
except:
log.warning(" sk.recv(1000) exception .....")
pass
log.debug(len(data_byte))
# 客户端主动关闭连接后,会不断接收b'', 所以跳出循环,运行到程序结尾,自动关闭线程
if data_byte == b'':
log.info(
" b'' is received , maybe client {self.client_address} had close. ")
self.sk.close()
if hasattr(self, "sensor"):
del self.sensor # 销毁对象
break
else:
break
continue
else:
self.sensor.write_buf(data_byte)
data_byte = b'' # 客户端掉线后以前数据不长居内存
try:
data_ = self.sensor.decode()
except MyException as e:
log.warning(e)
break
except Exception as e:
log.warning("decode data 出现异常 ")
log.warning(e)
break
if data_ != {}:
id = data_['id']
data_code = data_['type']
log.info(f'Received From ID:{id} DATA CODE:{data_code}')
# 保存当前数据
self.dealData.save(data_)
head = data_['head']
log.info(f'Head :{head}')
# 返回head给服务器
self.sk.send(data_['head'])
# 判断是否是最后一帧, 修改目录为时间格式并
if data_["packet_con"] == data_["packet_all"]:
log.info(f'最后一帧数据已经收到并保存')
# id 为传感器测量id ,con 测量序号
self.dealData.deal(data_['id'], data_["con"], self.cfg, self.retrieve)
pass
if time.time() - self.begin_time > TIMEOUT_SECOND:
log.info(f'Received data timeout')
break
def finish(self) -> None:
# 什么时候执行 finish
# 执行handle 出现意外错误时执行 finish,或handle break时执行 finish
# 关闭连接
if self.sk:
self.sk.close()
# conn_pool 连接池销毁
if self.client_address in conn_pool:
conn_pool.remove(self.client_address)
log.info(
f"finish(): stop one socket from client {self.client_address} ")
if __name__ == '__main__':
server_ = socketserver.ThreadingTCPServer(ADDRESS, MyServer)
log.info('listening...........')
try:
server_.serve_forever()
except KeyboardInterrupt:
log.info(" Ctrl+C 退出主程序 ")
server_.server_close()
except Exception as e:
log.info(" 系统异常, 如下: \n ")
log.info(e)
# 有闪退,可以用线程将server_.serve_forever 包起来
# threading.Thread(target=server_.serve_forever).start()

@ -0,0 +1,234 @@
# tcp Handheld 客户端 模拟 ,模拟数据打包
# 直接平一个小包测试数据 直接写tou
import socket
import time
# IP = "39.96.0.224"
IP = "127.0.0.1"
PORT = 7887
ADDRESS = ( IP, PORT ) # 绑定地址
INFO_HEADER = "111355AA020000250000004F000107"
DATA_HEADER = "11 13 55 AA 02 00 10 25 00 00 00 DA 06 02 07"
END_FRAME = "11 13 55 AA 02 00 FF 25 00 00 00 00 00 00 00"
# 改数据
class DataContent:
# 11 13 55 AA 0200 00 11 00 00 00 4F00 01 07
# id type-num 序号 17 字节数 包号 总
info_frame = "1703140E313518565D1E51D55605CCE812068CDDC347D0239515000000000000000000000064000000000000000000000000000000000000000000F450F450F4500600000300000000000000000000"
sensor_frame =[
# 11 13 55 AA 02 00 10 11 00 00 00 DA 06 02 07
'131123600020000000524844557691E700CB054C054A05A10001\
23A000300700000A07FD062A073707440750074D074C07530759075A07610765076A07720790079107A407C3070709BE0AAC0ABF080F080808270849089E0880094F0BB70F2A1901\
23A000300600005223CD28242B3830E235813BE9401B46675A3181C68D5C7916715D74C676617658742E71B26C9C674363DA5F1C5E0160F164DF66A262F85AD153764E4F4C014D01\
23A00030050000EA4D8C4D314DF44D3C4FC250E453BA5E4486B8C5BCECC4D29A96436BFA56734E4B4A55473446364A845140582A5A9C55A54D91465440303C1B3FDE5783718E7001\
23A00030040000DC565046C140F63D21392E32D12B5B28A226F3253525662366219E20DD1FB11E971DC51C2F1C901B921A6419C21882185818E418181B401DEC1C1D1A3917F71501\
23A00030030000EE153316F516CA176E18B218CA18B118701845186A1730155913E51314153015E1146C1420147D13C11208128C1128113011BF121614DB12F70F3B0EE50D320E01\
23A00030020000FD0D3C0D930C470C0D0CB80B710B1E0BCD0A920A560A1F0A000A140A460A3E0AD0097A096C095F092109B60870085F0834082B081C0808080B08DD07B907950701\
23A000300100007007620755074A0740074C074607460748074A07500758075D0757074F0743075F0756075F0758074F073F07240745076207770756073F072A070907E606D60601\
23A00030000000F3060F07250722072E07200703070B07EC06FF0619073E07590734071807190719070A07E106DD06F006EC061B072F073E073E07220725070B07F806C806DE0601\
23A000300700000A07FD062A073707440750074D074C07530759075A07610765076A07720790079107A407C3070709BE0AAC0ABF080F080808270849089E0880094F0BB70F2A1901\
23A000300600005223CD28242B3830E235813BE9401B46675A3181C68D5C7916715D74C676617658742E71B26C9C674363DA5F1C5E0160F164DF66A262F85AD153764E4F4C014D01\
23A00030050000EA4D8C4D314DF44D3C4FC250E453BA5E4486B8C5BCECC4D29A96436BFA56734E4B4A55473446364A845140582A5A9C55A54D91465440303C1B3FDE5783718E7001\
23A00030040000DC565046C140F63D21392E32D12B5B28A226F3253525662366219E20DD1FB11E971DC51C2F1C901B921A6419C21882185818E418181B401DEC1C1D1A3917F71501\
23A00030030000EE153316F516CA176E18B218CA18B118701845186A1730155913E51314153015E1146C1420147D13C11208128C1128113011BF121614DB12F70F3B0EE50D320E01\
23A00030020000FD0D3C0D930C470C0D0CB80B710B1E0BCD0A920A560A1F0A000A140A460A3E0AD0097A096C095F092109B60870085F0834082B081C0808080B08DD07B907950701\
23A000300100007007620755074A0740074C074607460748074A07500758075D0757074F0743075F0756075F0758074F073F07240745076207770756073F072A070907E606D60601\
23A00030000000F3060F07250722072E07200703070B07EC06FF0619073E07590734071807190719070A07E106DD06F006EC061B072F073E073E07220725070B07F806C806DE0601\
23A000300700000A07FD062A073707440750074D074C07530759075A07610765076A07720790079107A407C3070709BE0AAC0ABF080F080808270849089E0880094F0BB70F2A1901\
23A000300600005223CD28242B3830E235813BE9401B46675A3181C68D5C7916715D74C676617658742E71B26C9C674363DA5F1C5E0160F164DF66A262F85AD153764E4F4C014D01\
23A00030050000EA4D8C4D314DF44D3C4FC250E453BA5E4486B8C5BCECC4D29A96436BFA56734E4B4A55473446364A845140582A5A9C55A54D91465440303C1B3FDE5783718E7001\
23A00030040000DC565046C140F63D21392E32D12B5B28A226F3253525662366219E20DD1FB11E971DC51C2F1C901B921A6419C21882185818E418181B401DEC1C1D1A3917F71501\
23A00030030000EE153316F516CA176E18B218CA18B118701845186A1730155913E51314153015E1146C1420147D13C11208128C1128113011BF121614DB12F70F3B0EE50D320E01\
23A00030020000FD0D3C0D930C470C0D0CB80B710B1E0BCD0A920A560A1F0A000A140A460A3E0AD0097A096C095F092109B60870085F0834082B081C0808080B08DD07B907950701\
23A000300100007007620755074A0740074C074607460748074A07500758075D0757074F0743075F0756075F0758074F073F07240745076207770756073F072A070907E606D60601\
23A00030000000F3060F07250722072E07200703070B07EC06FF0619073E07590734071807190719070A07E106DD06F006EC061B072F073E073E07220725070B07F806C806DE0601',
]
end_frame = "11 13 55 AA 02 00 FF 25 00 00 00 00 00 00 00" #0xFF
class MyBuf:
'''一次测量三个传感器数据打一个包'''
def __init__(self,) -> None:
self.__buf = b''
self.__head = {}
self.__begin_sign = b'\x23'
self.__end_sign = b'\x0D'
self.send_head = b'\x11\x13\x55\xAA'
self.send_id = 2 # 2byte 地位在前
self.send_type = 0 # info 0 data 1 pic 2
self.send_num = 0 # 一次测量最多十六次平均
self.send_con = 0 # 总的测量序号 4byte ,16次平均算几次?每次算一个
self.send_size = 0 #字节数 2byte
self.send_packet_con = 0
self.send_packet_all = 0
self.repeat = 0 # 依据这个拆包
self.groups = 0
self.state = 0
def readFile2Buf(self, fpath) -> None:
with open(fpath,"rb") as f:
self.__buf = f.read()
pass
pass
def read_buf(self, size: int) -> bytes:
if size > self.__buf.__len__():
return b''
ret = self.__buf[0:size]
self.__buf = self.__buf[size:]
return ret
def write_buf(self, buf: bytes) -> None:
len = buf.__len__()
# logging.info(f'Received ID:{id} Size:{len}')
self.__buf = self.__buf+buf
def get_buf_size(self) -> int:
return self.__buf.__len__()
def back_bytes(self, buf: bytes) -> None:
self.__buf = buf+self.__buf
def reset_head(self) -> None:
self.__head = {}
def reset_buf(self) -> None:
self.__buf = b''
def pack_info_send(self,):
length = 26
ret = self.read_buf(length)
id = self.send_id.to_bytes(2, byteorder='little')
self.send_type = 0
type_num = (self.send_type *16 + self.send_num).to_bytes(1,byteorder='little' ) # ??
con = self.send_con.to_bytes(4, byteorder='little')
size = length.to_bytes(2, byteorder='little')
packet_con = self.send_packet_con.to_bytes(1,byteorder='little' )
packet_all = self.send_packet_all.to_bytes(1,byteorder='little' )
ret = self.send_head + id + type_num + con + size + packet_con + packet_all +ret
self.send_packet_con += 1
# 取重复次数和测量间隔
return ret
def pack_handheld_send(self,):
length = 26+576+576+576
ret = self.read_buf(length)
id = self.send_id.to_bytes(2, byteorder='little')
self.send_type = 1
type_num = self.send_type << 4 + self.send_num # ??
con = self.send_con.to_bytes(4, byteorder='little')
size = length.to_bytes(2, byteorder='little')
packet_con = self.send_packet_con.to_bytes(1,byteorder='little' )
packet_all = self.send_packet_all.to_bytes(1,byteorder='little' )
ret = self.send_head + id + type_num + con + size + packet_con + packet_all +ret
self.send_con+=1 # 总测量序号+1
self.send_num += 1 # 是平均中的第几次
self.send_packet_con += 1
return ret
pass
def pack_end_send(self,):
ret = b'\x11\x13\x55\xAA\x02\x00\xFF\x11\x00\x00\x00\x00\x00\x00\x00'
return ret
pass
class TcpProfiler(object):
def __init__(self ):
super(TcpProfiler, self).__init__()
self.flag = True
self.delay_time = 15
self.recv_times = 10
self.head = b''
self.socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
self.socket.setblocking(True)
def connect(self,):
print(f"== connect to server : {ADDRESS}")
self.socket.connect( ADDRESS )
def disconnect(self,):
self.socket.close( )
def rcv(self,):
recv_data = self.socket.recv( 1024 )
if recv_data == self.head:
self.flag =True
time.sleep( 0.01 )
def send_rcv(self,buf):
self.socket.send( buf )
self.flag = False
self.head = buf[:15]
# 当前接收到数据就不阻塞了,后加数据不对继续阻塞
try:
data = self.socket.recv(1024)
if data != b'':
print("not empty")
print(data)
if data==self.head:
print(f"recv.... {data}" )
self.flag = True
self.head = b''
time.sleep( 0.1 )
except BlockingIOError as e:
print(f" 阻塞 中断 ....")
except KeyboardInterrupt as e:
print(f" == ctrl +c , exit")
def send_info(self,):
buf = bytes.fromhex (INFO_HEADER+ DataContent.info_frame)
self.flag = False
self.head = buf[:15]
print(f"head ....{self.head.hex()}")
self.send_rcv(buf)
def send_data(self,):
buf = b''
buf = bytes.fromhex (DATA_HEADER+ DataContent.sensor_frame[0])
self.flag = False
self.head = buf[:15]
print(f"head ....{self.head.hex()}")
self.send_rcv(buf)
# for i in range( len( DataContent.sensor_frame) ):
# print( "sensorframe..." )
# buf = bytes.fromhex ( DataContent.sensor_frame[i] )
# self.flag = False
# self.head = buf[:15]
# print(f"head ....{self.head.hex()} ")
# self.send_rcv(buf)
def send_end_frame(self,):
buf = bytes.fromhex (DataContent.end_frame)
self.flag = False
self.head = buf[:15]
print(f"head ....{self.head.hex()}")
self.send_rcv(buf)
if __name__ == '__main__':
# print( bytes.fromhex (DataContent.info_frame) )
tp = TcpProfiler()
tp.connect()
try :
while True:
tp.send_info()
tp.send_data()
tp.send_end_frame()
time.sleep( 10)
except KeyboardInterrupt as e:
print(e)
tp.disconnect( )

@ -0,0 +1,11 @@
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

@ -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函数意义相同指定日志文件的打开模式wa
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__
"""

@ -0,0 +1,265 @@
from pathlib import PurePath, Path
# from myconfig import NEWLINE,TOKEN,SEPARATOR
"""
"""
class MyDir(object):
"""
操作方法:设置base tuple_dir header
设置的是路径, 文件名要 ifNotNewFile 传入
"""
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 )

@ -0,0 +1,66 @@
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
"""
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
Loading…
Cancel
Save