parent
d9604c4483
commit
51609549e0
@ -1,6 +1,7 @@ |
||||
/__pycache__/ |
||||
/dist/ |
||||
/build/ |
||||
/tools/__pycache__/ |
||||
/*/__pycache__/ |
||||
/data/output/ |
||||
*.log |
||||
@ -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() ) |
||||
@ -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函数意义相同,指定日志文件的打开模式,’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__ |
||||
""" |
||||
@ -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…
Reference in new issue