penguin/homekey-relay

homekey-relay

esp32/tools/ld2410s-c3-calib/tests/test_protocol.c

raw ยท 3354 bytes

#include "protocol.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
static unsigned frames[3]; static ld_reading latest; static uint16_t progress;
static void got(ld_frame_kind kind,const uint8_t *data,size_t size,void *ctx) {
    (void)ctx; frames[kind]++;
    ld_reading r; if(ld_decode_reading(kind,data,size,&r)) latest=r;
    uint16_t p; if(ld_decode_progress(kind,data,size,&p)) progress=p;
}
int main(void) {
    uint8_t out[140],payload[96]={0};
    assert(ld_command(0xff,(uint8_t[]){1,0},2,out,sizeof(out))==14);
    assert(!memcmp(out,(uint8_t[]){0xfd,0xfc,0xfb,0xfa,4,0,0xff,0,1,0,4,3,2,1},14));
    assert(ld_command(0x72,payload,96,out,sizeof(out))==108);
    assert(ld_command(0x72,payload,96,out,100)==0);
    uint8_t standard[80]={0xf4,0xf3,0xf2,0xf1,70,0,1,3,150,0,0,0};
    for(unsigned i=0;i<16;i++) ld_put32(standard+12+i*4,i+10);
    memcpy(standard+76,(uint8_t[]){0xf8,0xf7,0xf6,0xf5},4);
    const uint8_t minimal[]={0x6e,0,80,0,0x62};
    for(unsigned split=1;split<90;split++) {
        ld_parser p={0}; memset(frames,0,sizeof(frames));
        ld_feed(&p,(uint8_t *)"noise",5,got,NULL);
        ld_feed(&p,minimal,5,got,NULL); assert(latest.state==0 && latest.distance_cm==80);
        for(size_t i=0;i<80;i+=split) ld_feed(&p,standard+i,80-i<split?80-i:split,got,NULL);
        assert(frames[LD_DATA]==1 && frames[LD_MINIMAL]==1);
        assert(latest.state==3 && latest.distance_cm==150 && latest.energy_valid && latest.energy[15]==25);
        assert(p.bad_bytes==5);
        uint8_t calibration[]={0xf4,0xf3,0xf2,0xf1,3,0,3,0x64,0,0xf8,0xf7,0xf6,0xf5};
        for(size_t i=0;i<sizeof(calibration);i+=split)
            ld_feed(&p,calibration+i,sizeof(calibration)-i<split?sizeof(calibration)-i:split,got,NULL);
        assert(progress==10000);
        out[0]=0xfd; out[1]=0xfc; out[2]=0xfb; out[3]=0xfa;out[4]=255;out[5]=255;
        ld_feed(&p,out,6,got,NULL); ld_feed(&p,minimal,5,got,NULL); assert(frames[LD_MINIMAL]==2);
        /* Header bytes inside a valid energy payload must not be mistaken for frames. */
        memcpy(standard+20,(uint8_t[]){0xfd,0xfc,0xfb,0xfa},4);
        ld_feed(&p,standard,80,got,NULL); assert(frames[LD_DATA]==3);
    }
    /* Device percentages 0..100 become the dashboard's hundredths, not 0..1%. */
    for(unsigned percent=0;percent<=100;percent++) {
        uint8_t body[]={3,(uint8_t)percent,0}; uint16_t decoded=65535;
        assert(ld_decode_progress(LD_DATA,body,3,&decoded));
        assert(decoded==percent*100);
    }
    uint16_t decoded=1234;
    assert(!ld_decode_progress(LD_DATA,(uint8_t[]){3,101,0},3,&decoded));
    assert(!ld_decode_progress(LD_DATA,(uint8_t[]){3,0x10,0x27},3,&decoded));
    assert(!ld_decode_progress(LD_DATA,(uint8_t[]){3,100},2,&decoded));
    assert(!ld_decode_progress(LD_ACK,(uint8_t[]){3,100,0},3,&decoded));
    ld_settings s={.far_gate=2,.near_gate=0,.absence_s=10,.status_hz_x10=5,.distance_hz_x10=10,.response=5};
    for(unsigned i=0;i<16;i++) {s.trigger[i]=40;s.hold[i]=30;}
    assert(!ld_validate(&s));s.near_gate=3;assert(ld_validate(&s));s.near_gate=0;
    s.distance_hz_x10=6;assert(ld_validate(&s));s.distance_hz_x10=10;s.trigger[0]=100;assert(ld_validate(&s));
    puts("Protocol checks passed: framing, every fragmentation size, telemetry, progress, corrupt lengths, header bytes in payload, settings limits");
}