From 3b1e7a70826baf550be8c93a9c66a0f554d032d5 Mon Sep 17 00:00:00 2001 From: xu <1012118331@qq.com> Date: Mon, 14 Sep 2026 14:15:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A02=E8=B7=AF=E6=8B=89=E6=B5=81?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=EF=BC=9B=E4=BF=AE=E6=94=B9=E4=B8=B2=E5=8F=A3?= =?UTF-8?q?=E8=BD=ACudp=E5=8C=85=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E4=BF=A1=E5=8F=B7=E5=AD=97=E8=8A=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mpp/sample/lc6600_uart/ctrl_pnl.c | 6 +- mpp/sample/rtsp_switch/rtsp_switch_2.c | 147 +++++++++++++++++++++++++ mpp/sample/uart2net_mesh/ctrl_pnl.c | 124 ++++++++++++++++----- mpp/sample/uart2net_mesh/uart2net | Bin 0 -> 22972 bytes 4 files changed, 244 insertions(+), 33 deletions(-) create mode 100644 mpp/sample/rtsp_switch/rtsp_switch_2.c create mode 100644 mpp/sample/uart2net_mesh/uart2net diff --git a/mpp/sample/lc6600_uart/ctrl_pnl.c b/mpp/sample/lc6600_uart/ctrl_pnl.c index b8acaf9..2351e8e 100644 --- a/mpp/sample/lc6600_uart/ctrl_pnl.c +++ b/mpp/sample/lc6600_uart/ctrl_pnl.c @@ -36,7 +36,7 @@ char freq2[10]; //char dbm1[5]; //char dbm2[5]; -#define RSSI_TIMEOUT_MS 4000 //超时时间 +#define RSSI_TIMEOUT_MS 3000 //超时时间 #define RSSI_NO_SIGNAL 0x55 //无信号值 @@ -309,9 +309,9 @@ int main (int argc, char *argv[]) int ip_len; int len; - n_read = uart_init(ROUTE_UART, "/dev/ttyAMA4", 115200, 'N'); + n_read = uart_init(ROUTE_UART, "/dev/ttyAMA2", 115200, 'N'); if(n_read <=0 ) { - printf("open /dev/ttyAMA4 failed\n"); + printf("open /dev/ttyAMA2 failed\n"); return -1; } diff --git a/mpp/sample/rtsp_switch/rtsp_switch_2.c b/mpp/sample/rtsp_switch/rtsp_switch_2.c new file mode 100644 index 0000000..ff35f98 --- /dev/null +++ b/mpp/sample/rtsp_switch/rtsp_switch_2.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +int switch_video; +unsigned char key_value; + + + + +int *switch_memory_open(void) { + char buf[128]; + int fd; + sprintf(buf, "/video_switch"); + fd = shm_open(buf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if(fd < 0) { perror("shm_open"); exit(1); } + if (ftruncate(fd, 4096) == -1) { perror("ftruncate"); exit(1); } + int *retval = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + return retval; +} + +int main(int argc, char **argv) +{ + + + int ret; + int *switch_mode; + + int switch_video=0; + int switch_video_pre=0; + unsigned char buf[1024]; + unsigned char buf_kill_rtsp[1024]; + + switch_mode = switch_memory_open(); + + switch_video = switch_mode[0]; + switch_video_pre = switch_video; + + + /* 0->1 双全屏, 1->2 左全屏, 2->3 右全屏, 3->4 左放大, 4->5 右放大 */ + sprintf(buf,"./start_rtsp.sh %d",switch_video+1); + system(buf); + + + while(1) + { + switch_video = switch_mode[0]; + + /* 双全屏:任一路无信号切该路备路(6=通道0备路, 7=通道1备路) */ + if(switch_video==0 && switch_video_pre==0){ + if(switch_mode[2] == 0x55){ + printf("+++++++++++++++++++++++++1 time out\n"); + sprintf(buf_kill_rtsp,"./kill_rtsp.sh %d",6); + system(buf_kill_rtsp); + sprintf(buf,"./start_rtsp.sh %d",6); + system(buf); + } + + if(switch_mode[3] == 0x55){ + printf("+++++++++++++++++++++++++2 time out\n"); + sprintf(buf_kill_rtsp,"./kill_rtsp.sh %d",7); + system(buf_kill_rtsp); + sprintf(buf,"./start_rtsp.sh %d",7); + system(buf); + } + + if((switch_mode[2] == 0x55) || (switch_mode[3] == 0x55)){ + printf("+++++++++++++++++++++++++time out\n"); + usleep(6000000); + } + }else if(switch_video == 1 && switch_video_pre==1){ /* 左屏通道0全屏 */ + if(switch_mode[2] == 0x55){ + printf("+++++++++++++++++++++++++11 time out\n"); + sprintf(buf_kill_rtsp,"./kill_rtsp.sh %d",2); + system(buf_kill_rtsp); + sprintf(buf,"./start_rtsp.sh %d",2); + system(buf); + } + } + else if(switch_video == 2 && switch_video_pre==2) /* 右屏通道1全屏 */ + { if(switch_mode[3] == 0x55){ + printf("+++++++++++++++++++++++++22 time out\n"); + sprintf(buf_kill_rtsp,"./kill_rtsp.sh %d",2); + system(buf_kill_rtsp); + sprintf(buf,"./start_rtsp.sh %d",3); + system(buf); + } + + } + else if(switch_video == 3 && switch_video_pre==3) /* 左放大右隐藏 */ + { if(switch_mode[2] == 0x55){ + printf("+++++++++++++++++++++++++33 time out\n"); + sprintf(buf_kill_rtsp,"./kill_rtsp.sh %d",2); + system(buf_kill_rtsp); + sprintf(buf,"./start_rtsp.sh %d",4); + system(buf); + } + } + else if(switch_video == 4 && switch_video_pre==4) /* 右放大左隐藏 */ + { if(switch_mode[3] == 0x55){ + printf("+++++++++++++++++++++++++44 time out\n"); + sprintf(buf_kill_rtsp,"./kill_rtsp.sh %d",2); + system(buf_kill_rtsp); + sprintf(buf,"./start_rtsp.sh %d",5); + system(buf); + } + } + + + + if((switch_video != switch_video_pre )){ + + switch_video_pre = switch_video; + sprintf(buf_kill_rtsp,"./kill_rtsp.sh %d",1); + system(buf_kill_rtsp); + sprintf(buf,"./start_rtsp.sh %d",switch_video+1); + printf("+++++++++++++++video %s\n",buf); + + + system(buf); + + } + + usleep(3000000); + + } + +} diff --git a/mpp/sample/uart2net_mesh/ctrl_pnl.c b/mpp/sample/uart2net_mesh/ctrl_pnl.c index 4dc0764..57cfad7 100644 --- a/mpp/sample/uart2net_mesh/ctrl_pnl.c +++ b/mpp/sample/uart2net_mesh/ctrl_pnl.c @@ -32,6 +32,17 @@ #define CHECKSUM_END 30 /* 校验和覆盖 byte0..byte30(含) */ #define NET_FRAME_MAX_LEN 256 /* recvfrom 缓冲大小 */ +#define BYTE_NOSIG0 25 /* byte25 = 视频流0无信号标志(1=无信号,0=有信号) */ +#define BYTE_NOSIG1 26 /* byte26 = 视频流1无信号标志(1=无信号,0=有信号) */ +#define BYTE_RSSI1 28 /* 信号包=RSSI1;设备包=哨兵 */ +#define BYTE_RSSI2 29 /* 信号包=RSSI2;设备包=哨兵 */ +#define SIG_MARK 0x5A /* 设备包 byte28/29 哨兵值 */ +#define SIGNAL_INTERVAL_MS 100 /* 独立信号包发送间隔(ms) */ +#define FRAME_HEAD 0x11 /* 上行帧帧头(byte0),面板校验要求 */ +#define FRAME_TAIL 0x22 /* 上行帧帧尾(byte30),面板校验要求 */ +#define FRAME_HEAD_TX 0xAA /* 下行帧帧头(byte0),设备→面板 */ + + /* ===================== 共享内存 ===================== */ #define SHM_MSG_NAME "/video_switch" #define SHM_MODE_IDX 0 /* switch_mode -> shm[0](即 switch_video[0]) */ @@ -94,6 +105,11 @@ static int read_gpio72(void) return (val == '0') ? 1 : 0; /* 反相:GPIO=1 → 0,GPIO=0 → 1 */ } +static long elapsed_ms(struct timeval *start, struct timeval *end) +{ + return (end->tv_sec - start->tv_sec) * 1000L + + (end->tv_usec - start->tv_usec) / 1000L; +} int init_net_recv(int port){ @@ -229,16 +245,18 @@ void *net_recv(void *arg) } - /* 2) 校验和 = byte0..byte30 求和取低8位 */ + /* 构造下行帧:byte0=0xAA 帧头,byte1..29 原样,byte30=0xBB 帧尾 */ + frame_out[0] = FRAME_HEAD_TX; /* [0] 帧头 0xAA */ + memcpy(frame_out + 1, buffer_cmd + 1, PAYLOAD_LEN - 1); /* [1..29] 原样 */ + frame_out[PAYLOAD_LEN] = NET_TAIL; /* [30] 帧尾 0xBB */ + + /* 校验和 = byte0..byte30 求和取低8位,写入 byte31 */ sum = 0; for (k = 0; k <= CHECKSUM_END; k++) - sum += (unsigned char)buffer_cmd[k]; + sum += (unsigned char)frame_out[k]; checksum = sum & 0xFF; + frame_out[PAYLOAD_LEN + 1] = checksum; /* [31] 校验和 */ - /* 3) 转发:去掉 byte30/31,byte0..29 原样 + 帧尾 + 校验和(仍 32 字节) */ - memcpy(frame_out, buffer_cmd, PAYLOAD_LEN); /* 0..29,共 30 字节 */ - frame_out[PAYLOAD_LEN] = NET_TAIL; /* [30] 帧尾 */ - frame_out[PAYLOAD_LEN + 1] = checksum; /* [31] 校验和 */ #if 0 /* 打印发出的包 */ @@ -287,9 +305,12 @@ int main (int argc, char *argv[]) char buffer_send[100]; int buffer_len; - n_read = uart_init(ROUTE_UART, "/dev/ttyAMA2", 115200, 'N'); + struct timeval tv_sig = {0, 0}, tv_now; + char sig_frame[NET_FRAME_LEN]; + + n_read = uart_init(ROUTE_UART, "/dev/ttyAMA4", 115200, 'N'); if(n_read <=0 ) { - printf("open /dev/ttyAMA2 failed\n"); + printf("open /dev/ttyAMA4 failed\n"); return -1; } @@ -307,31 +328,74 @@ int main (int argc, char *argv[]) pthread_init(); - while(1){ - n_read = uart_read(ROUTE_UART, _rx_data); - if(n_read > 0 ){ - if (n_read >= 32) { /* 完整 32 字节帧才处理 */ - int k, sum = 0; + while(1){ + n_read = uart_read(ROUTE_UART, _rx_data); + if(n_read > 0 ){ + int k, sum = 0; - _rx_data[27] = (char)read_gpio72(); /* byte27 = GPIO9_0 反相值 */ - - if (buffer_param) { /* 写入:byte28/29 = RSSI 信号强度 */ - _rx_data[28] = (char)buffer_param[1]; - _rx_data[29] = (char)buffer_param[2]; - printf("RSSI1 =%d RSSI2 =%d",buffer_param[1],buffer_param[2]); + /* 收包校验:完整 32 字节帧,帧头 0x11、帧尾 0x22、byte31 校验和正确,否则丢弃 */ + if (n_read < NET_FRAME_LEN) { + printf("drop bad frame: len=%d\n", n_read); + continue; + } + if ((unsigned char)_rx_data[0] != FRAME_HEAD || + (unsigned char)_rx_data[CHECKSUM_END] != FRAME_TAIL) { + printf("drop bad frame: head=%02x tail=%02x\n", + (unsigned char)_rx_data[0], (unsigned char)_rx_data[CHECKSUM_END]); + continue; + } + for (k = 0; k <= CHECKSUM_END; k++) + sum += (unsigned char)_rx_data[k]; + if ((unsigned char)_rx_data[31] != (sum & 0xFF)) { + printf("drop bad frame: checksum=%02x expect=%02x\n", + (unsigned char)_rx_data[31], (unsigned char)(sum & 0xFF)); + continue; + } + + /* byte28/29 固定哨兵值,RSSI 改由独立信号包承载 */ + _rx_data[BYTE_RSSI1] = (char)SIG_MARK; + _rx_data[BYTE_RSSI2] = (char)SIG_MARK; + + + /* 和校验:byte0..byte30 求和取低 8 位,写入 byte31 */ + sum = 0; + for (k = 0; k <= CHECKSUM_END; k++) + sum += (unsigned char)_rx_data[k]; + _rx_data[31] = (char)(sum & 0xFF); + + sendto(socket_descriptor, _rx_data, NET_FRAME_LEN, 0, (struct sockaddr *)&address, sizeof(address)); + } + + + /* 独立信号包:与串口数据无关,每 SIGNAL_INTERVAL_MS 发一次;其余字节填 0 */ + gettimeofday(&tv_now, NULL); + if (tv_sig.tv_sec == 0 || elapsed_ms(&tv_sig, &tv_now) >= SIGNAL_INTERVAL_MS) { + int k, sum = 0; + + memset(sig_frame, 0, NET_FRAME_LEN); + sig_frame[0] = (char)FRAME_HEAD; /* byte0 = 0x11 */ + + /* byte25/26 = 视频流0/1无信号,byte27 = GPIO */ + sig_frame[BYTE_NOSIG0] = (shm_msg && shm_msg[2] == 0x55) ? 1 : 0; + sig_frame[BYTE_NOSIG1] = (shm_msg && shm_msg[3] == 0x55) ? 1 : 0; + sig_frame[27] = (char)read_gpio72(); + + if (buffer_param) { + sig_frame[BYTE_RSSI1] = (char)buffer_param[1]; + sig_frame[BYTE_RSSI2] = (char)buffer_param[2]; + //打印发出的信号值 + printf("signal: RSSI1=%d RSSI2=%d\n", buffer_param[1], buffer_param[2]); + } + sig_frame[PAYLOAD_LEN] = (char)FRAME_TAIL; /* byte30 = 0x22 */ + + for (k = 0; k <= CHECKSUM_END; k++) + sum += (unsigned char)sig_frame[k]; + sig_frame[CHECKSUM_END + 1] = (char)(sum & 0xFF); + + sendto(socket_descriptor, sig_frame, NET_FRAME_LEN, 0, (struct sockaddr *)&address, sizeof(address)); + tv_sig = tv_now; } - /* 和校验:byte0..byte30 求和取低 8 位,写入 byte31 */ - for (k = 0; k <= 30; k++) - sum += (unsigned char)_rx_data[k]; - _rx_data[31] = (char)(sum & 0xFF); } - sendto(socket_descriptor, _rx_data, n_read, 0, (struct sockaddr *)&address, sizeof(address)); - } -} - - - - } diff --git a/mpp/sample/uart2net_mesh/uart2net b/mpp/sample/uart2net_mesh/uart2net new file mode 100644 index 0000000000000000000000000000000000000000..00c3f04b2b056747ebe34aafe3b3a447eedea453 GIT binary patch literal 22972 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 literal 0 HcmV?d00001