语音模块摄像头模块阿里云结合,实现垃圾的智能识别

语音模块&摄像头模块&阿里云结合

文章目录

  • 语音模块&摄像头模块&阿里云结合
    • 1、实现的功能
    • 2、配置
      • 2.1 软件环境
      • 2.2 硬件配置
    • 3、程序介绍
      • 3.1 程序概况
      • 3.2 语言模块SDK配置介绍
      • 3.3 程序文件
        • 3.3.1 开启摄像头的程序
        • 3.3.2 云端识别函数( `Py ==> C` ) & 串口程序
        • 3.3.3 结合 `main.c`
      • 3.4 程序运行结果

1、实现的功能

  • 可以通过语音模块使摄像头在抓拍垃圾图片,程序自动将垃圾传到云端识别,判断出是什么垃圾类型(干垃圾、湿垃圾、可回收垃圾、有害垃圾)(无法识别) 最后由语音模块输出相关信息

2、配置

2.1 软件环境

  • VS Code
  • MobaXterm

2.2 硬件配置

  • 全志H616

  • SU-03T LD3320

    • 语言模块要配置SDK,大家可以到网上搜一下,很简单的;我用的是智能公元的语音模块;我把我用的分享给大家;

    • 语言模块SDK:链接: https://pan.baidu.com/s/1CjgIhW0AWQjXdEhXZiBIzw?pwd=2222 提取码: 2222 复制这段内容后打开百度网盘手机App,操作更方便哦

      烧入工具:链接: https://pan.baidu.com/s/1JF2K_TbS_lg74YInBCCI2g?pwd=2222 提取码: 2222 复制这段内容后打开百度网盘手机App,操作更方便哦

在这里插入图片描述

  • USB摄像头模块

在某宝随便每个USB摄像头模块就ok。

3、程序介绍

3.1 程序概况

garbage.py //云端提供的py程序,不用自己编写,改改参数,看得懂就ok
garbage.c & garbage.h  //利用C语言调用py文件,并且进行了封装,方便main函数调用
>>> https://blog.csdn.net/Super_Fisher_man/article/details/137055641
uartTool.c & uartTool.h //串口通信程序
>>> https://blog.csdn.net/Super_Fisher_man/article/details/136662787

main.c //主函数,将两者结合

garbage.c & uartTool.c 在前面的文章都已经介绍过了,这边就不多加赘述

3.2 语言模块SDK配置介绍

在这里插入图片描述
在这里插入图片描述

3.3 程序文件

3.3.1 开启摄像头的程序
  • 可以看看之前的blog

基于香橙派 调用USB摄像头 的两种方法(命令&脚本)-CSDN博客

# start.sh
# /home/orangepi/mjpg-streamer/mjpg-streamer-experimental
export LD_LIBRARY_PATH="$(pwd)"
#./mjpg_streamer -i "input_uvc.so --help"

./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -u -f 30" -o "./output_http.so -w ./www"
# mjpg.sh
# /home/orangepi
#!/bin/bash

cd /home/orangepi/mjpg-streamer/mjpg-streamer-experimental
./start.sh 
  • 在清除了mjpg进程的前提下命令

  • >>> ps ax | grep mjpg
    >>> kill -9 ×××
    >>> ./mjpg.sh
    
3.3.2 云端识别函数( Py ==> C ) & 串口程序
  • 云端调用的程序,只需改 #场景二 就ok
//garbage.py
# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_imagerecog20190930

import os
import io
from urllib.request import urlopen
from alibabacloud_imagerecog20190930.client import Client
from alibabacloud_imagerecog20190930.models import ClassifyingRubbishAdvanceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_tea_util.models import RuntimeOptions

config = Config(
  # 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。
  # 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html
  # 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
  access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
  access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
  # 访问的域名
  endpoint='imagerecog.cn-shanghai.aliyuncs.com',
  # 访问的域名对应的region
  region_id='cn-shanghai'
)

def alibaba_garbage(): # 封装成一个函数,方便其他文件调用
  #场景一:文件在本地
  # img = open(r'/home/orangepi/garbage/lj/test2.jpg','rb')
  img = open(r'/tmp/garbage.jpg','rb')
  #场景二:使用任意可访问的url
  # url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/imagerecog/ClassifyingRubbish/ClassifyingRubbish1.jpg'
  # img = io.BytesIO(urlopen(url).read())
  classifying_rubbish_request = ClassifyingRubbishAdvanceRequest()
  classifying_rubbish_request.image_urlobject = img
  runtime = RuntimeOptions()
  try:
    # 初始化Client
    client = Client(config)
    response = client.classifying_rubbish_advance(classifying_rubbish_request, runtime)
    # 获取整体结果
    # print(response.body) # 默认
    # print(response.body.to_map()) # 打印出body的类型
    print(response.body.to_map()['Data']['Elements'][0]['Category']) # 打印出body的类型
    return response.body.to_map()['Data']['Elements'][0]['Category']
    # 提供调用方便
  except Exception as error:
    # 获取整体报错信息
    # print(error)
    # 获取单个字段
    # print(error.code)
    return '获取失败'

if __name__== "__main__":
  alibaba_garbage()
  • Py ==> c
//garbage.h
#ifndef __GARBAGE__H
#define __GARBAGE__H
void garbage_init(void);//第一步做初始化,初始python的编译器包括导入当前路劲到sys.path里面
void garbage_final(void);
char *garbage_category(char *category);

//127.0.0.1
//通常被称为"本地回环地址"或"localhost";
//这个地址经常用于测试网络应用程序和诊断网络问题
//因为它确保数据能够在同一台计算机上进行循环传输,而无需真正通过网络传输。

#define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -O /tmp/garbage.jpg" //抓拍命令
#define GARBAGE_FILE "/tmp/garbage.jpg"

#endif
// C语言引用Python文件
#if 0
1、包含Python.h头文件,以便使用Python API。
2、使用void Py_Initialize()初始化Python解释器,
3、使用PyObject *PyImport_ImportModule(const char *name)和PyObject
*PyObject_GetAttrString(PyObject *o, const char *attr_name)获取sys.path对象,并利用
int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,以便加载
当前的Python模块(Python文件即python模块)4、使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否
有错误。
5、使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取
Python函数对象,并检查是否可调用。
+6、使用PyObject *Py_BuildValue(const char *format, ...)函数将C类型的数据结构转换成
Python对象,作为Python函数的参数,没有参数不需要调用
7、使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用
Python函数,并获取返回值。
+8、使用int PyArg_Parse(PyObject *args, const char *format, ...)函数将返回值转换为C类
型,并检查是否有错误,没有返回值时不需要调用。
9、使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。
10、结束时调用void Py_Finalize()函数关闭Python解释器。
相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索):
https://docs.python.org/zh-cn/3/c-api/import.html
#endif

#include <Python.h>
#include "garbage.h"


void garbage_init(void)
{
    Py_Initialize();
    // 将当前路径添加到sys.path中
    PyObject *sys = PyImport_ImportModule("sys");//初始化python解释器
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString("."));
}

void garbage_final(void)
{
    //释放所有引用的Python对象
    Py_Finalize();
}
char *garbage_category(char *category)
{
    // 导入para模块
    PyObject *pModule = PyImport_ImportModule("garbage");//引用的是本目录底下的garbage.py文件
    if (!pModule)
    {
        PyErr_Print();
        printf("Error: failed to load para.py\n");
        goto FAILED_MODULE;
    }
    //获取 alibaba_garbage 函数对象
    PyObject *pFunc = PyObject_GetAttrString(pModule, "alibaba_garbage");//garbage.py文件里的这个函数 alibaba_garbage
    if (!pFunc)
    {
        PyErr_Print();
        printf("Error: failed to load say_funny\n");
        goto FAILED_FUNC;
    }

    //调用alibaba_garbage函数并获取返回值
    PyObject *pValue = PyObject_CallObject(pFunc, NULL);
    if (!pValue)
    {
        PyErr_Print();
        printf("Error: function call failed\n");
        goto FAILED_VALUE;
    } 
    //将返回值转换为C类型
    char *result = NULL;  //pValue(py) --> result(c)
    if (!PyArg_Parse(pValue, "s", &result))//PyArg_Parse根据指定的格式字符串将 Python 对象转换为 C 变量
    {
        PyErr_Print();
        printf("Error: parse failed\n");
        goto FAILED_RESULT;
    }
    //打印返回值
    //printf("pValue=%s\n", result);
    category = (char*)malloc(sizeof(char)*(strlen(result)+1));//要留一个字节给 \0
    memset(category, 0, (strlen(result)+1));
    strncpy(category, result,(strlen(result)+1));//复制字符串
    

//会用来标识某个测试案例、任务或计划未能通过或达到预期的标准或目标;失败后跳转
FAILED_RESULT:
    Py_DECREF(pValue);
FAILED_VALUE:
    Py_DECREF(pFunc);
FAILED_FUNC:
    Py_DECREF(pModule);
FAILED_MODULE:

    return category;
}
  • 串口函数
//uartTool.h
#ifndef __UARTTOOL_H
#define __UARTTOOL_H
int myserialOpen (const char *device, const int baud);
void serialSendstring (const int fd, unsigned const char *s, int len); //写数据
int serialGetstring (const int fd, unsigned char *buffer); //读数据

#define SERIAL_DEV "/dev/ttyS5" // 可代替设备节点
#define BAUD 115200             // 代替波特率

#endif
//防止头文件中的声明反复区声明
//uartTool.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "uartTool.h"//先到当前文件夹查看
#include "wiringSerial.h"

int myserialOpen (const char *device, const int baud)
{
	struct termios options ;//这个结构体
  speed_t myBaud ;
  int status, fd ;
  
  switch (baud)
  {
  	case    9600:	myBaud =    B9600 ; break ;
  	case  115200:	myBaud =  B115200 ; break ;
  	default:
  }
  
  if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
  return -1 ;
  
  fcntl (fd, F_SETFL, O_RDWR) ;

// Get and modify current options:

  tcgetattr (fd, &options) ;//get

  //标准化的操作 一般都是固定的
  cfmakeraw   (&options) ;
  cfsetispeed (&options, myBaud) ;
  cfsetospeed (&options, myBaud) ;//波特率的设置 

  options.c_cflag |= (CLOCAL | CREAD) ;
  options.c_cflag &= ~PARENB ;//奇偶校验位 
  options.c_cflag &= ~CSTOPB ;//ͣ停止位 一般都是一位的
  options.c_cflag &= ~CSIZE ;
  options.c_cflag |= CS8 ;//数据位 基本都是八位的
  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
  options.c_oflag &= ~OPOST ;

  options.c_cc [VMIN]  =   0 ;
  options.c_cc [VTIME] = 100 ;	// Ten seconds (100 deciseconds)
  //标准化的操作
  tcsetattr (fd, TCSANOW, &options) ;//写入内核


  ioctl (fd, TIOCMGET, &status);//获得整型控制字TIOCMGET get出来
  status |= TIOCM_DTR ;
  status |= TIOCM_RTS ;//控制字加上标志位
  ioctl (fd, TIOCMSET, &status);//写入内核

  usleep (10000) ;	// 10mS
  return fd ;
}

//0XAA 0X55 0X46 0X00 0X55 0XAA
void serialSendstring (const int fd, const unsigned char *s, int len)//去写数据
{
	int ret;
  ret = write (fd, s, len);
  if (ret < 0)
 		printf("Serial Putchar Error\n");
}

int serialGetstring (const int fd, unsigned char *buffer)
{
	int n_read;
	n_read = read(fd,buffer,6);
  // printf("%d\n",fd); 
	return n_read;
}
3.3.3 结合 main.c
//main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include "uartTool.h"
#include "garbage.h"

int main(int argc, char *argv[])
{
    int serial_fd = -1;
    int len = 0;
    char *category = NULL;
    unsigned char buffer[6] = {0xAA,0x55,0x00,0x00,0x55,0xAA};//AA 55 ** 00 55 AA

    //初始化
    garbage_init();

    //打开设备
    serial_fd = myserialOpen(SERIAL_DEV,BAUD);//可代替设备节点 & 波特率   返回值fd
    if(serial_fd == -1)//是否打开成功
    {
        goto END;    
    }
 
    while(1)
    {
        //获取(读)传过来的数据
        len = serialGetstring(serial_fd,buffer); //P8 & P10 ==> TXD.5 & RXD.5 

     
        if(len>0 && buffer[2]==0x46) //0x46命令:识别垃圾类型
        {
            buffer[2]==0x00;
            //define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -O /tmp/garbage.jpg" //抓拍命令
            system(WGET_CMD);//宏定义:拍照命令,garbage.h 文件中
            // access函数是一个用于测试文件访问权限的函数,它通常用于检查某个文件是否可以被当前用户读取、写入或执行。
            // 包括F_OK(检查文件是否存在)、R_OK(检查读权限)、W_OK(检查写权限)和X_OK(检查执行权限)
            // 该函数返回值为0表示有权限,-1表示无权限或发生错误。
            if(0 == access(GARBAGE_FILE, F_OK))//GARBAGE_FILE 宏定义 识别到的垃圾图片是否存在
            {
                category = garbage_category(category);//调用阿里云接口判断垃圾类型
                if(strstr(category,"干垃圾"))
                {
                    buffer[2] = 0x41;//赋值
                }
                else if(strstr(category,"湿垃圾"))
                {
                    buffer[2] = 0x42;
                }
                else if(strstr(category,"可回收垃圾"))
                {
                    buffer[2] = 0x43;
                }
                else if(strstr(category,"有害垃圾"))
                {
                    buffer[2] = 0x44;
                }
                else
                {
                    buffer[2] = 0x45;// 未识别成功
                }
            }
            else
            {
                buffer[2] = 0x45;
            }

            serialSendstring(serial_fd,buffer,6);//写数据,回传给语音模块
            buffer[2]=0x00;//将buffer[2]清零
            remove(GARBAGE_FILE);//garbage.h 的宏定义 把识别到的垃圾的图片清除掉
        }
    }
    
END:
    garbage_final; //释放所有引用的Python对象
    return 0;  
}

3.4 程序运行结果

  • 先杀进程

在这里插入图片描述

  • 打开摄像头

在这里插入图片描述

  • 显示视频内容、抓拍
    在这里插入图片描述
    在这里插入图片描述

  • 执行结果

在这里插入图片描述

语言会自动回复,该垃圾是什么类型



欢迎大家一起交流讨论

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/497461.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FebHost:什么是哈萨克斯坦.KZ域名?

哈萨克斯坦&#xff0c;作为中亚地区重要的一员,其国家域名”.kz”正成为这个独立国家在网络世界中的代表。作为一个经济快速发展的国家,哈萨克斯坦的互联网基础设施和网络应用也在蓬勃发展。而.kz域名正是哈萨克斯坦网络身份的重要体现。 作为注册和管理.kz域名的主要机构,哈…

helm 部署 Kube-Prometheus + Grafana + 钉钉告警部署 Kube-Prometheus

背景 角色IPK8S 版本容器运行时k8s-master-1172.16.16.108v1.24.1containerd://1.6.8k8s-node-1172.16.16.109v1.24.1containerd://1.6.8k8s-node-2172.16.16.110v1.24.1containerd://1.6.8 安装 kube-prometheus mkdir -p /data/yaml/kube-prometheus/prometheus &&…

【Web应用技术基础】CSS(6)——使用 HTML/CSS 实现 Educoder 顶部导航栏

第一题&#xff1a;使用flex布局实现Educoder顶部导航栏容器布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Educoder</title><script src"https://cdn.staticfile.org/jquery/1.1…

语音陪玩交友软件系统程序-app小程序H5三端源码交付,支持二开!

电竞行业的发展带动其周边产业的发展&#xff0c;绘制着游戏人物图画的抱枕、鼠标垫、海报销量极大&#xff0c;电竞游戏直播、游戏教程短视频也备受人们喜爱&#xff0c;自然&#xff0c;像游戏陪练、代练行业也随之生长起来&#xff0c;本文就来讲讲&#xff0c;从软件开发角…

Starrocks基于主机和容器的读写测试

背景介绍 在云原生时代&#xff0c;存算分离架构显然已经是当下大数据架构的必备选型&#xff0c;但是在不同的虚拟化计算资源&#xff08;主机、容器&#xff09;之上&#xff0c;是否能有差异点以及对于不同服务的性能损耗程度如何&#xff1f;来判断应该在什么样的场景下选…

react+vite+antD+reduce+echarts项目完整记录

reactviteantDreduceecharts项目完整记录 之前写前端项目&#xff0c;都是用的vue&#xff0c;从最开始的vue2到后来的vue3&#xff0c;断断续续写了3年&#xff0c;打包工具也从webpack转到了vite&#xff0c;全局数据管理工具从vuex转到了pinia。总体而言&#xff0c;vue3对…

软件工程学习笔记12——运行维护篇

运行维护篇 一、版本发布1、关于软件版本2、版本发布前&#xff0c;做好版本发布的规划3、规范好发布流程&#xff0c;保障发布质量 二、DevOps工程师1、什么是 DevOps 三、线上故障1、遇到线上故障&#xff0c;新手和高手的差距在哪里2、大厂都是怎么处理线上故障的 四、日志管…

自然语言处理(NLP)全面指南

自然语言处理&#xff08;NLP&#xff09;是人工智能领域中最热门的技术之一&#xff0c;它通过构建能够理解和生成人类语言的机器&#xff0c;正在不断推动技术的发展。本文将为您提供NLP的全面介绍&#xff0c;包括其定义、重要性、应用场景、工作原理以及面临的挑战和争议。…

JavaEE之网络初识(网络中的一些基本概念)详解

&#x1f63d;博主CSDN主页: 小源_&#x1f63d; &#x1f58b;️个人专栏: JavaEE &#x1f600;努力追逐大佬们的步伐~ 目录 1. 前言 2. 网络中的一些基本概念 2.1 IP地址 2.2 端口号 2.3 网络协议 2.4 协议分层 2.5 封装 2.6 分用 (封装的逆向过程) 2.7 客户端 vs …

uniApp使用XR-Frame创建3D场景(7)加入点击交互

上篇文章讲述了如何将XR-Frame作为子组件集成到uniApp中使用 这篇我们讲解如何与场景中的模型交互&#xff08;点击识别&#xff09; 先看源码 <xr-scene render-system"alpha:true" bind:ready"handleReady"><xr-node><xr-mesh id"…

连续信号离散信号的功率谱密度--用MATLAB求功率谱密度

连续信号&离散信号的功率谱密度--用MATLAB求功率谱密度 目录 前言 一、能量及功率定义 1、连续信号 2、离散信号 二、功率谱密度计算公式 三、MATLAB仿真 1、源代码 2、仿真结果分析 总结 前言 一直对数字信号处理中的功率谱密度计算有点好奇&#xff0c;虽然MATLAB有提供现…

【MySQL】15. 事务管理(重点) -- 1

1. CURD不加控制&#xff0c;会有什么问题&#xff1f; 2. CURD满足什么属性&#xff0c;能解决上述问题&#xff1f; 买票的过程得是原子的 ?买票互相应该不能影响 ?买完票应该要永久有效 ?买前&#xff0c;和买后都要是确定的状态? 3. 什么是事务&#xff1f; 事务就是…

探索 2024 年 Web 开发最佳前端框架

前端框架通过简化和结构化的网站开发过程改变了 Web 开发人员设计和实现用户界面的方法。随着 Web 应用程序变得越来越复杂&#xff0c;交互和动画功能越来越多&#xff0c;这是开发前端框架的初衷之一。 在网络的早期&#xff0c;网页相当简单。它们主要以静态 HTML 为特色&a…

CSS 结构伪类选择器 伪元素选择器 盒子模型

目录 1. 结构伪类选择器1.1 :nth-child(公式) 2. 伪元素选择器3. 盒子模型3.1 盒子模型的重要组成部分3.2 盒子模型 - 边框线3.3 盒子模型 - 内边距3.4 盒子模型 - 尺寸计算3.5 盒子模型 - 外边距3.6 盒子模型 - 元素溢出3.7 外边距问题 - 合并现象3.8 外边距问题 - 塌陷问题3.…

游戏推广的新篇章:Xinstall助力实现全渠道效果统计与提升

随着游戏市场的日益繁荣&#xff0c;游戏推广已成为各大游戏公司争夺市场份额的关键环节。然而&#xff0c;面对众多推广渠道和复杂的用户行为&#xff0c;如何精准地评估推广效果、优化投放策略&#xff0c;成为了游戏推广人员亟待解决的问题。此时&#xff0c;Xinstall作为一…

如何使用Windows电脑部署Lychee私有图床网站并实现无公网IP远程管理本地图片

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-MSVdVLkQMnY9Y2HW {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

网络工程师实验命令(华为数通HCIA)

VRP系统的基本操作 dis version #查看设备版本信息 sys #进入系统视图 system-name R1 #改设备名字为R1进入接口配置IP地址 int g0/0/0 ip address 192.168.1.1 255.255.255.0 #配置接口地址为192.168.1.1/255.255.255.0 ip address 192.168.1.2 24 sub #此…

flutter生成二维码并截图保存到图库

引入库&#xff1a;flutter_screenutil、image_gallery_saver、qr_flutter弹窗布局 import dart:async; import dart:typed_data; import package/generated/l10n.dart; import package:jade/configs/PathConfig.dart; import package:jade/utils/ImageWaterMarkUtil.dart; im…

车载以太网AVB交换机 gptp透明时钟 8口 千兆/百兆可切换 SW1100TR

SW1100车载以太网交换机 一、产品简要分析 8端口千兆和百兆混合车载以太网交换机&#xff0c;其中包含2个通道的1000BASE-T1采用罗森博格H-MTD接口&#xff0c;5通道100BASE-T1泰科MATEnet接口和1个通道1000BASE-T标准以太网(RJ45接口)&#xff0c;可以实现车载以太网多通道交…

Flink系列之:Flink SQL Gateway

Flink系列之&#xff1a;Flink SQL Gateway 一、Flink SQL Gateway二、部署三、启动SQL Gateway四、运行 SQL 查询五、SQL 网关启动选项六、SQL网关配置七、支持的端点 一、Flink SQL Gateway SQL 网关是一项允许多个客户端从远程并发执行 SQL 的服务。它提供了一种简单的方法…