feat: add AS status feedback for both HMI sizes with verified v2.7 release
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
exec(open('tmp/accept_as_hardware.py',encoding='utf-8').read().split('with can.Bus(')[0])
|
||||
import numpy as np,pyautogui as pg
|
||||
from pywinauto import Desktop
|
||||
O=R/'docs/evidence/2026-10-07/small-as-status'
|
||||
W=526764
|
||||
w=Desktop(backend='win32').window(handle=W);u=Desktop(backend='uia').window(handle=W)
|
||||
w.set_focus()
|
||||
u.child_window(title='开始',control_type='Hyperlink').invoke();time.sleep(.4)
|
||||
canvas=w.child_window(handle=526860).rectangle()
|
||||
stop=threading.Event();payload=None;errors=[];checks=[];tx=[];frames=[]
|
||||
with can.Bus(interface='pcan',channel='PCAN_USBBUS1',bitrate=500000) as bus:
|
||||
assert bus.reset()
|
||||
q=subprocess.run([CLI,'-c','port=SWD','sn=37FF71064E573436188C1543','mode=HOTPLUG','freq=1000','-rst'],capture_output=True,timeout=15)
|
||||
assert q.returncode==0
|
||||
(O/'mcu-reset.log').write_bytes(q.stdout+q.stderr)
|
||||
time.sleep(.5)
|
||||
def sender():
|
||||
try:
|
||||
while not stop.is_set():
|
||||
msg=payload
|
||||
if msg:bus.send(msg,timeout=.15);tx.append(dict(id=hex(msg.arbitration_id),data=msg.data.hex(' ')))
|
||||
stop.wait(.1)
|
||||
except Exception as e:errors.append(repr(e))
|
||||
def receiver():
|
||||
try:
|
||||
while not stop.is_set():
|
||||
m=bus.recv(.1)
|
||||
if m:frames.append(dict(id=hex(m.arbitration_id),data=m.data.hex(' '),timestamp=m.timestamp))
|
||||
except Exception as e:errors.append(repr(e))
|
||||
ts=[threading.Thread(target=fn) for fn in (sender,receiver)]
|
||||
for t in ts:t.start()
|
||||
def feedback(state,flags=15,version=2):
|
||||
global payload
|
||||
payload=can.Message(arbitration_id=0x183,is_extended_id=False,data=bytes([2,1,1,flags,0,state,0,version]))
|
||||
def shotcheck(name,color,target=None):
|
||||
time.sleep(1.3)
|
||||
if target is not None:
|
||||
snap=memory('hmi-'+name);assert snap['states']==target,(name,snap,target)
|
||||
else:snap=None
|
||||
im=pg.screenshot(region=(canvas.left,canvas.top,720,408));im.save(str(O/('can-uart-hmi-'+name+'.png')))
|
||||
a=np.asarray(im)[int(215*1.5):int(245*1.5),int(194*1.5):int(302*1.5),:3].astype(np.int16)
|
||||
r,g,b=a[:,:,0],a[:,:,1],a[:,:,2]
|
||||
masks={'gray':(r>75)&(r<180)&(abs(r-g)<8)&(abs(r-b)<8),
|
||||
'white':(r>210)&(g>210)&(b>210),'yellow':(r>180)&(g>180)&(b<80),
|
||||
'blue':(b>180)&(g<80)&(r<80),'red':(r>180)&(g<80)&(b<80),
|
||||
'green':(g>180)&(r<80)&(b<80)}
|
||||
count=int(masks[color].sum());assert count>30,(name,color,count)
|
||||
assert bus.status()==0 and not errors
|
||||
checks.append(dict(name=name,color=color,pixels=count,ram=snap,passed=True));print(name,'display passed',flush=True)
|
||||
try:
|
||||
for state,label,color in [(0,'off','white'),(1,'ready','yellow'),(2,'driving','yellow'),(3,'finished','blue'),(4,'emergency','red'),(5,'manual','green')]:
|
||||
feedback(state);shotcheck(label,color,[2,1,1,state])
|
||||
feedback(1,7);shotcheck('as-invalid','gray',[2,1,1,6])
|
||||
feedback(1);shotcheck('before-legacy','yellow',[2,1,1,1])
|
||||
feedback(0,7,1);shotcheck('legacy-unknown','gray',[2,1,1,6])
|
||||
feedback(1);shotcheck('before-timeout','yellow',[2,1,1,1])
|
||||
payload=can.Message(arbitration_id=0x6a0,is_extended_id=False,data=bytes.fromhex('A1 01 00 00 00 00 00 00'))
|
||||
shotcheck('timeout-other-traffic','gray',[7,0,0,6])
|
||||
feedback(1);shotcheck('recovery','yellow',[2,1,1,1])
|
||||
# Actual simulated touch; all displayed feedback still comes through physical UART.
|
||||
def touch(x,y):
|
||||
pg.moveTo(canvas.left+x*1.5,canvas.top+y*1.5);pg.mouseDown();time.sleep(.15);pg.mouseUp();time.sleep(.2)
|
||||
props=json.loads((R/'tmp/migrate-8048/properties-before.json').read_text(encoding='utf-8'))
|
||||
def at(page,component):
|
||||
p=next(p for k,p in props[page].items() if k.startswith(component+'('))
|
||||
touch(int(p['x'])+int(p['w'])/2,int(p['y'])+int(p['h'])/2)
|
||||
at('dash','debug_entry');feedback(4);time.sleep(.8);at('debug','b0')
|
||||
shotcheck('cross-page-latest-emergency','red',[2,1,1,4])
|
||||
feedback(1);shotcheck('before-touch-request','yellow',[2,1,1,1])
|
||||
before=len(frames);at('dash','bt4');at('CONFIRM','b0')
|
||||
shotcheck('touch-request-keeps-as-ready','yellow',[2,1,1,1])
|
||||
request=next((m for m in frames[before:] if m['id']=='0x300' and bytes.fromhex(m['data'])[1]==5),None)
|
||||
assert request,('touch -> physical UART RX -> CAN request absent',frames[before:]);checks[-1]['request']=request
|
||||
payload=None;shotcheck('final-unknown','gray',[7,0,0,6])
|
||||
finally:
|
||||
payload=None;stop.set()
|
||||
for t in ts:t.join(timeout=2)
|
||||
logs={str(c.handle):c.window_text() for c in w.descendants() if 'RichEdit' in c.class_name()}
|
||||
(O/'can-uart-hmi-serial-panel.json').write_text(json.dumps(logs,ensure_ascii=False,indent=2),encoding='utf-8')
|
||||
result=dict(result='passed' if len(checks)==16 and not errors else 'partial',scope='physical CAN1 -> MCU RAM -> USART2/COM6 -> official HMI simulator; touch UART RX -> real CAN1 request; no physical screen download',checks=checks,errors=errors)
|
||||
(O/'can-uart-hmi-results.json').write_text(json.dumps(result,ensure_ascii=False,indent=2),encoding='utf-8')
|
||||
(O/'can-uart-hmi-can.json').write_text(json.dumps(dict(sent=tx,received=frames),indent=2),encoding='utf-8')
|
||||
u.child_window(title='停止',control_type='Hyperlink').invoke()
|
||||
print('CAN/UART/HMI checks completed:',len(checks),flush=True)
|
||||
Reference in New Issue
Block a user