pomiary
This commit is contained in:
parent
24b3a90520
commit
e10661be5e
|
|
@ -0,0 +1,22 @@
|
||||||
|
from datetime import datetime
|
||||||
|
from colorist import Color
|
||||||
|
|
||||||
|
STYLE_DEFAULT = Color.WHITE
|
||||||
|
|
||||||
|
|
||||||
|
def log_time():
|
||||||
|
return datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
||||||
|
|
||||||
|
def log_time_name():
|
||||||
|
return datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
|
||||||
|
|
||||||
|
log_file = open(f'logs/L-{log_time_name()}.txt', 'a')
|
||||||
|
|
||||||
|
def spr(x, style=STYLE_DEFAULT):
|
||||||
|
print(f"[{log_time()}] {style}{x}{Color.OFF}")
|
||||||
|
log_file.write(f'[{log_time()}] {x}\n')
|
||||||
|
|
||||||
|
def prefixed_spr(prefix, pr=spr):
|
||||||
|
def ret(x, *args):
|
||||||
|
pr(f"{prefix}: {x}", *args)
|
||||||
|
return ret
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
import asyncio
|
||||||
|
from collections.abc import Iterable, Sequence
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from logging import debug
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from logger import spr
|
||||||
|
import thrust_stand
|
||||||
|
import norsonic
|
||||||
|
|
||||||
|
from norsonic_fetcher import nor_get_reports, recording_path
|
||||||
|
from thrust_stand import ThrustStand, ThrustStandMeasurement
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class OpPointData:
|
||||||
|
data_thrust_stand: Sequence[ThrustStandMeasurement]
|
||||||
|
data_accustic: dict
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data_thrust_stand_avg(self):
|
||||||
|
return sum(self.data_thrust_stand, ThrustStandMeasurement.zero())/len(self.data_thrust_stand)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data_accustic_avg(self):
|
||||||
|
return {k: sum(map(float, (row[k] for row in self.data_accustic)))/len(self.data_accustic) for k in self.data_accustic[0].keys() if k != 'Date'}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ConnectionParams:
|
||||||
|
stand_tty: str
|
||||||
|
nor_addr: str
|
||||||
|
nor_ftp_user: str
|
||||||
|
nor_ftp_pass: str
|
||||||
|
nor_recordings_dir: str
|
||||||
|
|
||||||
|
CONN_PARAMS = ConnectionParams(
|
||||||
|
stand_tty='/dev/ttyUSB0',
|
||||||
|
nor_addr='10.145.1.1',
|
||||||
|
nor_ftp_user='AAAA',
|
||||||
|
nor_ftp_pass='1234',
|
||||||
|
nor_recordings_dir='/SD Card/NorMeas/Nor14530408/TEST'
|
||||||
|
)
|
||||||
|
|
||||||
|
async def meas_series(params: ConnectionParams, pwms: Iterable[int]):
|
||||||
|
stand = await ThrustStand.open_connection(params.stand_tty)
|
||||||
|
nor = await norsonic.open_connection(params.nor_addr)
|
||||||
|
|
||||||
|
results_stand = {}
|
||||||
|
files_nor = {}
|
||||||
|
|
||||||
|
# TODO TARA
|
||||||
|
sample, = stand.get_samples_raw(1)
|
||||||
|
stand.tare_thrust = thrust_stand.raw_thrust(sample.load_thrust)
|
||||||
|
stand.tare_torque = thrust_stand.raw_torque(sample.load_left, sample.load_right)
|
||||||
|
|
||||||
|
for pwm in pwms:
|
||||||
|
stand.mot_pwm = pwm
|
||||||
|
spr(f'Output: {pwm}PWM')
|
||||||
|
await stand.stabilize_rpm(5, 1)
|
||||||
|
spr(f'Starting measurement')
|
||||||
|
stand_series_pending = stand.start_meas_series()
|
||||||
|
files_nor[pwm] = await norsonic.record(nor)
|
||||||
|
spr(f'Done')
|
||||||
|
results_stand[pwm] = stand.finish_meas_series(stand_series_pending)
|
||||||
|
|
||||||
|
stand.mot_pwm = 1000
|
||||||
|
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
|
||||||
|
spr('Downlaoding reports')
|
||||||
|
|
||||||
|
|
||||||
|
nor_reports = await nor_get_reports(params.nor_addr, params.nor_ftp_user, params.nor_ftp_pass, [files_nor[pwm] for pwm in pwms])
|
||||||
|
spr('Done')
|
||||||
|
|
||||||
|
ret = {
|
||||||
|
pwm: OpPointData(
|
||||||
|
data_thrust_stand=results_stand[pwm],
|
||||||
|
data_accustic=nor_reports[i]
|
||||||
|
) for i, pwm in enumerate(pwms)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
global x
|
||||||
|
x = await meas_series(CONN_PARAMS, range(1100, 1950, 30))
|
||||||
|
|
||||||
|
# logging.basicConfig(level=logging.INFO)
|
||||||
|
# asyncio.run(main(), debug=True)
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
import asyncio
|
||||||
|
from collections.abc import Callable, Iterable, Sequence
|
||||||
|
from typing import Optional
|
||||||
|
from urllib import parse
|
||||||
|
import aioftp
|
||||||
|
import websockets
|
||||||
|
from websockets.asyncio.client import ClientConnection
|
||||||
|
|
||||||
|
from logger import spr
|
||||||
|
import norsonic_fetcher
|
||||||
|
|
||||||
|
MSG_OUT_NEW = "NewMeasurement"
|
||||||
|
MSG_OUT_START = "StartMeasurement"
|
||||||
|
|
||||||
|
KEY_STATE = 'State'
|
||||||
|
KEY_FILENAME = 'GraphHeader'
|
||||||
|
VAL_STATE_NEW = ''
|
||||||
|
VAL_STATE_RECORDING = "<span title='Running' class='icon-play4 greenFg'></span>"
|
||||||
|
VAL_STATE_WAITING = "<span title='Waiting' class='icon-busy'></span>"
|
||||||
|
VAL_STATE_DONE = "<span title='Saved' class='icon-disk'></span>"
|
||||||
|
|
||||||
|
def parse_msg(msg: str) -> dict[str, str]:
|
||||||
|
ret = {}
|
||||||
|
for l in msg.splitlines():
|
||||||
|
# print(f'par "{l}"')
|
||||||
|
if len(l) == 0:
|
||||||
|
continue
|
||||||
|
if l == 'clear':
|
||||||
|
break
|
||||||
|
if ':' not in l:
|
||||||
|
print(f'W: Unexpected line in message: {l}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
k, v = l.split(':', 1)
|
||||||
|
if k in ret:
|
||||||
|
if ret[k] == v:
|
||||||
|
continue
|
||||||
|
if len(v) == 0:
|
||||||
|
continue
|
||||||
|
print(f'W: Duplicate key detected ({k}: {v})')
|
||||||
|
raise RuntimeError()
|
||||||
|
ret[k] = v
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
class NSWSConnection:
|
||||||
|
# def __init__(self, ws: Web)
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
async def recv_msg(sock: ClientConnection) -> dict[str, str]:
|
||||||
|
recv = await sock.recv()
|
||||||
|
if not isinstance(recv, str):
|
||||||
|
raise RuntimeError('Invalid message received')
|
||||||
|
msg = parse_msg(recv)
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
async def wait_for_state(sock: ClientConnection, state: str, expected_states: Iterable[str] = []) -> dict[str, str]:
|
||||||
|
while True:
|
||||||
|
msg = await recv_msg(sock)
|
||||||
|
# spr(msg)
|
||||||
|
if KEY_STATE in msg:
|
||||||
|
if msg[KEY_STATE] == state:
|
||||||
|
return msg
|
||||||
|
elif msg[KEY_STATE] not in expected_states:
|
||||||
|
spr(f'W: Unexpected state received: {msg[KEY_STATE]}')
|
||||||
|
|
||||||
|
|
||||||
|
async def record(sock: ClientConnection, start_callback: Optional[Callable[[], None]] = None):
|
||||||
|
await sock.send(MSG_OUT_NEW)
|
||||||
|
spr('Initializing measurement')
|
||||||
|
await wait_for_state(sock, VAL_STATE_NEW, (VAL_STATE_DONE, ))
|
||||||
|
|
||||||
|
await sock.send(MSG_OUT_START)
|
||||||
|
spr('Starting measurement')
|
||||||
|
await wait_for_state(sock, VAL_STATE_WAITING, (VAL_STATE_NEW, ))
|
||||||
|
spr('Waiting for start')
|
||||||
|
await wait_for_state(sock, VAL_STATE_RECORDING)
|
||||||
|
|
||||||
|
if start_callback is not None:
|
||||||
|
start_callback()
|
||||||
|
|
||||||
|
spr('Waiting for finish')
|
||||||
|
msg = await wait_for_state(sock, VAL_STATE_DONE)
|
||||||
|
return msg[KEY_FILENAME]
|
||||||
|
|
||||||
|
async def open_connection(address: str) -> ClientConnection:
|
||||||
|
return await websockets.connect(f'ws://{address}/live', ping_interval=None)
|
||||||
|
|
||||||
|
|
||||||
|
# async def main():
|
||||||
|
# sock = await websockets.connect('ws://10.145.1.1/live')
|
||||||
|
# spr('Connected to server')
|
||||||
|
# name = await record(sock)
|
||||||
|
# spr(f'finished {name}')
|
||||||
|
# c = aioftp.Client(parse_list_line_custom=norsonic_fetcher.ftp_parse_line)
|
||||||
|
# res = await c.connect('10.145.1.1')
|
||||||
|
# res = await c.login('AAAA', '1234')
|
||||||
|
# global x
|
||||||
|
# # x = norsonic_fetcher.parse_report(await norsonic_fetcher.ftp_fetch(c, norsonic_fetcher.recording_path(name)))
|
||||||
|
# x = norsonic_fetcher.parse_report(await norsonic_fetcher.ftp_fetch(c, norsonic_fetcher.FNAME))
|
||||||
|
# print(x)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
import asyncio
|
||||||
|
from pathlib import Path
|
||||||
|
from re import split
|
||||||
|
from typing import Iterable, Sequence
|
||||||
|
import aioftp
|
||||||
|
|
||||||
|
from logger import spr
|
||||||
|
|
||||||
|
FNAME = '/SD Card/NorMeas/Nor14530408/TEST/VIP 124 2024-12-10 15-31-19/VIP 124 2024-12-10 15-31-19.txt'
|
||||||
|
DNAME = '/SD Card/NorMeas/Nor14530408/TEST/VIP 124 2024-12-10 15-31-19/'
|
||||||
|
RECORDINGS_PATH = '/SD Card/NorMeas/Nor14530408/TEST'
|
||||||
|
CRLF = '\r\n'
|
||||||
|
COL_SEPARATOR = '\t'
|
||||||
|
STR_DIR = '<DIR>'
|
||||||
|
|
||||||
|
def recording_path(rec_name: str) -> str:
|
||||||
|
return f'{RECORDINGS_PATH}/{rec_name}/{rec_name}.txt'
|
||||||
|
|
||||||
|
def ftp_parse_line(line: bytes):
|
||||||
|
l = line.decode()
|
||||||
|
date, time, size, name = l.split(None, 3)
|
||||||
|
_ = date
|
||||||
|
_ = time
|
||||||
|
attrdict = {'modify': None, 'size': 0, 'type': 'dir'}
|
||||||
|
if size != STR_DIR:
|
||||||
|
attrdict['type'] = 'file'
|
||||||
|
attrdict['size'] = int(size)
|
||||||
|
|
||||||
|
if not name.endswith(CRLF):
|
||||||
|
raise ValueError()
|
||||||
|
name = name[:-2]
|
||||||
|
path = Path(name)
|
||||||
|
return path, attrdict
|
||||||
|
|
||||||
|
async def ftp_fetch(client: aioftp.Client, path: str) -> bytes:
|
||||||
|
spr(f'fetching {path}')
|
||||||
|
stream = await client.download_stream(path)
|
||||||
|
file = b''.join([block async for block in stream.iter_by_block()])
|
||||||
|
await stream.finish()
|
||||||
|
stream.close()
|
||||||
|
return file
|
||||||
|
|
||||||
|
def parse_report_table(table: str):
|
||||||
|
_, head_cols, *rows = table.split(CRLF)
|
||||||
|
cols = head_cols.split(COL_SEPARATOR)
|
||||||
|
|
||||||
|
def parse_row(row: str):
|
||||||
|
vals = row.split(COL_SEPARATOR)
|
||||||
|
if len(vals) != len(cols):
|
||||||
|
print(vals)
|
||||||
|
print(cols)
|
||||||
|
print(len(cols))
|
||||||
|
print(len(vals))
|
||||||
|
raise ValueError('NorPaeser: Invalid row read')
|
||||||
|
return {cols[i]: vals[i] for i in range(len(cols))}
|
||||||
|
|
||||||
|
return [parse_row(r) for r in rows if len(r) > 0]
|
||||||
|
|
||||||
|
def parse_report(report: bytes):
|
||||||
|
*header, glob, prof = report.decode().split(2*CRLF)
|
||||||
|
t_prof = parse_report_table(prof)
|
||||||
|
# t_glob = parse_report_table(glob)
|
||||||
|
# return t_glob, t_prof
|
||||||
|
return t_prof
|
||||||
|
|
||||||
|
async def nor_get_reports(addr: str, user: str, password: str, recs: Iterable[str]) -> Sequence:
|
||||||
|
async with aioftp.Client.context(addr, user=user, password=password, parse_list_line_custom=ftp_parse_line) as ftp:
|
||||||
|
return [parse_report(await ftp_fetch(ftp, recording_path(p))) for p in recs]
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
c = aioftp.Client(parse_list_line_custom=ftp_parse_line)
|
||||||
|
res = await c.connect('10.145.1.1')
|
||||||
|
res = await c.login('AAAA', '1234')
|
||||||
|
global x
|
||||||
|
ns = [
|
||||||
|
'VIP 197 2024-12-13 11-48-21',
|
||||||
|
'VIP 198 2024-12-13 11-48-28',
|
||||||
|
'VIP 199 2024-12-13 11-48-35',
|
||||||
|
]
|
||||||
|
|
||||||
|
x = await nor_get_reports('10.145.1.1', 'AAAA', '1234', ns)
|
||||||
|
print(x)
|
||||||
|
|
||||||
|
|
||||||
|
# for n in ns:
|
||||||
|
# x = parse_report(await ftp_fetch(c, n))
|
||||||
|
# print(x)
|
||||||
|
|
||||||
|
# asyncio.run(main())
|
||||||
Loading…
Reference in New Issue