Kamailio-基于Homer与heplify的SIP信令监控-1

news2024/11/16 13:25:35

接上篇Kamailio监控,对Kamailio的一个基础监控有了一定的概念,但是光看数字如果发现问题,要如何回顾解决呢?生产环境不能随时随地抓包来确定链路的正常与否。

这个时候 Sipcapture 公司推出了Homer这个开源软件,目前Github有1.6K的star

搭建之后体验了一把,先说说总体的印象:

缺点:

  • 部署相对复杂,需要几个服务合作,包括heplify/heplify-server/homer-app,如果你只是小打小闹做点监控,可以先不要尝试。
  • 开源版本功能没有想想中的强大,有”开源版本“该有的丐版模样。

优点:

  • 相对整体的结构布局,可以从Kamalio获取数据,也可以从网口获取 HEP(分包协议)数据,通过heplify-server暂存后,发往homer。有后端服务、前端展示分离的服务,对KM监控无侵入性。
  • Homer对会话数据进行异步存储后,很多自定义的功能可以顺利地在homer上进行二开,基础的查询、会话调用查看,对接有loki\prometheus\ldap\grafana 等新式监控组件与统一认证。
  • 有专业团队维护,持续的更新,活跃的社区,都能保障服务的质量,未来可期。

因为这一整套有专业公司维护,因此这一套还被称为:Sipcapture HEP Stack。

下面将分三个章节来介绍整个Homer的部署安装配置、Kamailio的配置、Homer页面的查询与操作。

跟着我,你将学会:

  • 下载并安装-本篇
    • 踩坑:按照官方步骤来,可是网络条件不允许
      • 获取YUM源
      • 下载RPM包
      • 手动解压安装
      • 避坑
  • 配置并启动
    • heplify
    • heplify-server
    • homer
    • 配置数据库专用用户
    • 初始化homer数据
      • 创建配置数据库
      • 创建数据数据库
      • 创建数据表并修改权限
      • 启动服务
  • 如何使用 Homer 查询会话信息
    • 登录平台
    • 首页看板
    • 会话详情
    • 具体某条信令
    • 自定义查询页面

官方指导手册先放出,如后续此文章版本过期了,请移步官方文档流程。

以下实验版本

  • x86_64 CentOS Linux release 7.9.2009
  • heplify 1.66.7
  • heplify-server 1.59.7
  • homer7
  • PostgreSQL 11.4

为什么不装Homer10?因为生产还是虚机,没上Docker!!

安装的过程中遇到了好多坑的,下面一起来看看。

下载并安装

踩坑:按照官方步骤来,可是网络条件不允许

获取YUM源

首先先要安装一些下载的源,CentOS 采用rpm进行安装。

第一步:

curl -s https://packagecloud.io/install/repositories/qxip/sipcapture/script.rpm.sh | sudo bash

看似一行,实则生产环境翻墙不通,直接就是失败了,那么怎么解决?

看看脚本里到底需要哪些源,需要哪些包,是不是可以手动下了传上去?

那首先就是wget把脚本拿下来。

#!/bin/bash

unknown_os ()
{
  echo "Unfortunately, your operating system distribution and version are not supported by this script."
  echo
  echo "You can override the OS detection by setting os= and dist= prior to running this script."
  echo "You can find a list of supported OSes and distributions on our website: https://packagecloud.io/docs#os_distro_version"
  echo
  echo "For example, to force CentOS 6: os=el dist=6 ./script.sh"
  echo
  echo "Please email support@packagecloud.io and let us know if you run into any issues."
  exit 1
}

curl_check ()
{
  echo "Checking for curl..."
  if command -v curl > /dev/null; then
    echo "Detected curl..."
  else
    echo "Installing curl..."
    yum install -d0 -e0 -y curl
  fi
}


detect_os ()
{
  if [[ ( -z "${os}" ) && ( -z "${dist}" ) ]]; then
    if [ -e /etc/os-release ]; then
      . /etc/os-release
      os=${ID}
      if [ "${os}" = "poky" ]; then
        dist=`echo ${VERSION_ID}`
      elif [ "${os}" = "sles" ]; then
        dist=`echo ${VERSION_ID}`
      elif [ "${os}" = "opensuse" ]; then
        dist=`echo ${VERSION_ID}`
      elif [ "${os}" = "opensuse-leap" ]; then
        os=opensuse
        dist=`echo ${VERSION_ID}`
      elif [ "${os}" = "amzn" ]; then
        dist=`echo ${VERSION_ID}`
      else
        dist=`echo ${VERSION_ID} | awk -F '.' '{ print $1 }'`
      fi

    elif [ `which lsb_release 2>/dev/null` ]; then
      # get major version (e.g. '5' or '6')
      dist=`lsb_release -r | cut -f2 | awk -F '.' '{ print $1 }'`

      # get os (e.g. 'centos', 'redhatenterpriseserver', etc)
      os=`lsb_release -i | cut -f2 | awk '{ print tolower($1) }'`

    elif [ -e /etc/oracle-release ]; then
      dist=`cut -f5 --delimiter=' ' /etc/oracle-release | awk -F '.' '{ print $1 }'`
      os='ol'

    elif [ -e /etc/fedora-release ]; then
      dist=`cut -f3 --delimiter=' ' /etc/fedora-release`
      os='fedora'

    elif [ -e /etc/redhat-release ]; then
      os_hint=`cat /etc/redhat-release  | awk '{ print tolower($1) }'`
      if [ "${os_hint}" = "centos" ]; then
        dist=`cat /etc/redhat-release | awk '{ print $3 }' | awk -F '.' '{ print $1 }'`
        os='centos'
      elif [ "${os_hint}" = "scientific" ]; then
        dist=`cat /etc/redhat-release | awk '{ print $4 }' | awk -F '.' '{ print $1 }'`
        os='scientific'
      else
        dist=`cat /etc/redhat-release  | awk '{ print tolower($7) }' | cut -f1 --delimiter='.'`
        os='redhatenterpriseserver'
      fi

    else
      aws=`grep -q Amazon /etc/issue`
      if [ "$?" = "0" ]; then
        dist='6'
        os='aws'
      else
        unknown_os
      fi
    fi
  fi

  if [[ ( -z "${os}" ) || ( -z "${dist}" ) ]]; then
    unknown_os
  fi

  # Enumerate all old versions that need pygpgme for each os/dist.
  # This is not hard because all old versions are known.
  # Even if we miss some versions, users will report them and eventually we'll have a complete list.
  # This ensures that if pygpgme is required, we will install it.
  # The harder part is detecting when pygpgme is NOT required since we don't know what
  # new version names/numbering are, however, it's alright to miss those because
  # as long as they are not the enumerated old versions, we can assume that they are new.
  # If we wrongly assume that they are new, then repo/package install will fail and users
  # will report back, and this goes away eventually once we have a complete list of old versions
  amzn_dist_requires_pygpgme_array=("1${IFS}2${IFS}2016${IFS}2017${IFS}2018")

  echo "Detected operating system as ${os}/${dist}."

  if [[ "$os" = "ol" || "$os" = "el" || "$os" = "rocky" || "$os" = "almalinux" || "$os" = "centos" || "$os" = "rhel" ]] && [ $(($dist)) \> 7 ]; then
    _skip_pygpgme=1
  elif [ "$os" = "fedora" ] && [ $(($dist)) \> 19 ]; then
    _skip_pygpgme=1
  elif [ "$os" = "amzn" ]; then
    amzn_dist="${dist%%[.-]*}"
    if  [[ ! " ${amzn_dist_requires_pygpgme_array[*]} " =~ [[:space:]]${amzn_dist}[[:space:]] ]]; then
      # whatever you want to do when array doesn't contain value
      _skip_pygpgme=1
    else
      _skip_pygpgme=0
    fi
  else
    _skip_pygpgme=0
  fi
}

finalize_yum_repo ()
{
  if [ "$_skip_pygpgme" = 0 ]; then
    echo "Attempting to install pygpgme for your os/dist: ${os}/${dist}. Only required on older OSes to verify GPG signatures."
    yum install -y pygpgme --disablerepo="${repo_config_name}" 2>/dev/null
    pypgpme_check=`rpm -qa | grep -qw pygpgme`
    if [ "$?" != "0" ]; then
      echo
      echo "Note: "
      echo "The pygpgme package may no longer be required for your OS (${os}/${dist}), and has not been installed."
      echo "If your repo and package installation does not work please reach out to support."
      echo
    fi
  fi

  echo "Installing yum-utils..."
  yum install -y yum-utils --disablerepo="${repo_config_name}"
  yum_utils_check=`rpm -qa | grep -qw yum-utils`
  if [ "$?" != "0" ]; then
    echo
    echo "WARNING: "
    echo "The yum-utils package could not be installed. This means you may not be able to install source RPMs or use other yum features."
    echo
  fi

  echo "Generating yum cache for ${repo_config_name}..."
  yum -q makecache -y --disablerepo='*' --enablerepo="${repo_config_name}"

  echo "Generating yum cache for ${repo_config_name}-source..."
  yum -q makecache -y --disablerepo='*' --enablerepo="${repo_config_name}-source"
}

finalize_zypper_repo ()
{
  zypper --gpg-auto-import-keys refresh $repo_config_name
  zypper --gpg-auto-import-keys refresh $repo_config_name-source
}


main ()
{
  repo_config_name=qxip_sipcapture
  detect_os
  curl_check


  yum_repo_config_url="https://packagecloud.io/install/repositories/qxip/sipcapture/config_file.repo?os=${os}&dist=${dist}&source=script"

  if [ "${os}" = "sles" ] || [ "${os}" = "opensuse" ]; then
    yum_repo_path=/etc/zypp/repos.d/$repo_config_name.repo
  else
    yum_repo_path=/etc/yum.repos.d/$repo_config_name.repo
  fi

  echo "Downloading repository file: ${yum_repo_config_url}"

  curl -sSf "${yum_repo_config_url}" > $yum_repo_path
  curl_exit_code=$?

  if [ "$curl_exit_code" = "22" ]; then
    echo
    echo
    echo -n "Unable to download repo config from: "
    echo "${yum_repo_config_url}"
    echo
    echo "This usually happens if your operating system is not supported by "
    echo "packagecloud.io, or this script's OS detection failed."
    echo
    echo "You can override the OS detection by setting os= and dist= prior to running this script."
    echo "You can find a list of supported OSes and distributions on our website: https://packagecloud.io/docs#os_distro_version"
    echo
    echo "For example, to force CentOS 6: os=el dist=6 ./script.sh"
    echo
    echo "If you are running a supported OS, please email support@packagecloud.io and report this."
    [ -e $yum_repo_path ] && rm $yum_repo_path
    exit 1
  elif [ "$curl_exit_code" = "35" -o "$curl_exit_code" = "60" ]; then
    echo
    echo "curl is unable to connect to packagecloud.io over TLS when running: "
    echo "    curl ${yum_repo_config_url}"
    echo
    echo "This is usually due to one of two things:"
    echo
    echo " 1.) Missing CA root certificates (make sure the ca-certificates package is installed)"
    echo " 2.) An old version of libssl. Try upgrading libssl on your system to a more recent version"
    echo
    echo "Contact support@packagecloud.io with information about your system for help."
    [ -e $yum_repo_path ] && rm $yum_repo_path
    exit 1
  elif [ "$curl_exit_code" -gt "0" ]; then
    echo
    echo "Unable to run: "
    echo "    curl ${yum_repo_config_url}"
    echo
    echo "Double check your curl installation and try again."
    [ -e $yum_repo_path ] && rm $yum_repo_path
    exit 1
  else
    echo "done."
  fi


  if [ "${os}" = "sles" ] || [ "${os}" = "opensuse" ]; then
    finalize_zypper_repo
  else
    finalize_yum_repo
  fi

  echo
  echo "The repository is setup! You can now install packages."
}

main

简单一看脚本里做的事情,就是判断我的操作系统,然后生产一个yum仓库config的文件地址,然后配置为资源地址。

这里只是生产一个yum源地址是没什么问题的,那关键的是这个地址是外网,国内不用手段就访问不了。

所以你梳理执行完源配置后,下一步拉取,包括其他所有yum安装的步骤就都开始报错,说这个仓库地址连接不上。

所以遗憾的,需要手动来做后续的步骤,手动下载配置,看后续的包到底是去哪里下载的,手动下载后,放到服务器上。

我根据上面的脚本拼接出我的yum源配置的内容:
https://packagecloud.io/install/repositories/qxip/sipcapture/config_file.repo?os=centos&dist=7&source=script

放到浏览器,获取到仓库信息:

[qxip_sipcapture]
name=qxip_sipcapture
baseurl=https://packagecloud.io/qxip/sipcapture/el/7/$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/qxip/sipcapture/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300

[qxip_sipcapture-source]
name=qxip_sipcapture-source
baseurl=https://packagecloud.io/qxip/sipcapture/el/7/SRPMS
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/qxip/sipcapture/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300

看到了我想要的真实下载安装包的网址 https://packagecloud.io/qxip/sipcapture/,通过合法手段登录平台后你将看到。

在这里插入图片描述

能看到我们非常熟悉的RPM包,这个就好办了。

下载RPM包

手动下载,传送到服务器,然后采用rpm手动安装,这一条流程就比较顺利了。

确认准备好的材料。

$ ls -l
total 48296
-rw-r--r-- 1 root root  5343776 Aug 20 16:22 heplify-1.66.6-1.x86_64.rpm
-rw-r--r-- 1 root root  7629945 Aug 20 16:31 heplify-server-1.59.7-1.x86_64.rpm
-rw-r--r-- 1 root root 22776724 Aug 20 16:31 homer-app-1.5.3-1.x86_64.rpm
手动解压安装

手动魔鬼安装,顺序还是遵循官方的指导。

我这边heplify-server是借用现有的一个PG数据库,那么如果你没有的话,这个步骤请自行百度安装好,客户端也安装上(yum install postgresql -y)。

中间环节会提示要装相关的依赖包,比如:luajit-2.0.5、luajit-devel、postgresql-libs、postgresql-9.2.24。

rpm安装的过程中,可能需要一些依赖的版本是没有,它会提示让你更新仓库中的列表,你按照指示去更新即可。

报错示例:

error: Failed dependencies:
        luajit is needed by heplify-server-0:1.59.7-1.x86_64
# 表示缺 luajit, 那你就可以通过 yum install luajit-devel 之类的方式去安装      

环境一切顺利的话,rpm安装会非常快速

$ rpm -ivh heplify-1.66.6-1.x86_64.rpm
.....
$ rpm -ivh heplify-server-1.59.7-1.x86_64.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:heplify-server-0:1.59.7-1        ################################# [100%]
$ rpm -ivh homer-app-1.5.3-1.x86_64.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:homer-app-0:1.5.3-1              ################################# [100%]   
....

避坑

那你如果提前就知道你的网络环境会有很多下包的限制,或者是纯内网的情况的话,可以提前将Rpm包素材离线准备完毕,直接按照上面的步骤依次执行安装即可,也不需要强行去走他的源去自动化安装了。少走很多坑吧。。。。。

通过以上艰难险阻,服务算是都安装上了,确认一下:

$ systemctl status heplify
● heplify.service - Captures packets from wire and sends them to Homer
   Loaded: loaded (/etc/systemd/system/heplify.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since 三 2024-08-21 13:11:49 CST; 3 weeks 1 days ago
  Process: 22817 ExecStop=/bin/kill ${MAINPID} (code=exited, status=0/SUCCESS)
  Process: 29535 ExecStart=/opt/heplify/heplify -i lo -hs 192.168.5.167:9060 -m SIP -dim REGISTER -pr 5060-5090 (code=exited, status=0/SUCCESS)
 Main PID: 29535 (code=exited, status=0/SUCCESS)

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.


$ systemctl status heplify-server
● heplify-server.service - HEP Server & Switch in Go
   Loaded: loaded (/usr/lib/systemd/system/heplify-server.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since 四 2024-08-29 11:59:57 CST; 2 weeks 0 days ago
  Process: 901 ExecStart=/usr/local/bin/heplify-server $HEPLIFY_CONFIG (code=exited, status=0/SUCCESS)
 Main PID: 901 (code=exited, status=0/SUCCESS)

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.


$ systemctl status homer-app
● homer-app.service - Homer API Server and UI Webapplication
   Loaded: loaded (/usr/lib/systemd/system/homer-app.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
[root@192 ~]# systemctl status homer-web

下面我们就对其开始配置、数据初始化,将其启动起来。


如果这篇文章对你有帮助的话,麻烦 Github 点一个免费关注 哦~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件测试】常用的开发、测试模型

哈喽,哈喽,大家好~ 我是你们的老朋友:保护小周ღ 今天给大家带来的是 【软件测试】常用的开发、测试模型,首先了解, 什么是软件的生命周期, 测试的生命周期, 常见的开发模型: 瀑布, 螺旋, 增量, 迭代, 敏捷. 常用的测试模型, …

银河麒麟桌面系统卸载应用报错快速解决

银河麒麟桌面系统卸载应用报错快速解决 1、问题简述2、解决方案步骤 1: 删除dpkg信息步骤 2: 强制卸载步骤 3: 验证与清理 💖The Begin💖点点关注,收藏不迷路💖 1、问题简述 在银河麒麟桌面系统中卸载应用时,可能会遇…

AE 让合成重复循环播放

在合成上点右键 > Time > Enable Time Remapping 按住 Alt 键,点秒表图标 输入 loop_out("cycle", 0) 将子合成拖到此合成结束的位置 结束

Linux 上自动下载 Docker 依赖并离线安装的完整指南

Linux 上自动下载 Docker 依赖并离线安装的完整指南 文章目录 Linux 上自动下载 Docker 依赖并离线安装的完整指南一 添加软件源二 更新 yum 缓存三 下载依赖四 打包 rpm 文件五 离线安装 这篇指南详细讲解了如何在CentOS 7.9系统上,通过 yum命令自动下载Docker的所…

vue3使用leaflet+trackplayer实现非地图动画轨迹(市场平面图动态轨迹)

vue3使用leaflettrackplayer实现非地图动画轨迹(市场平面图动态轨迹) 先下载 leaflet 和 leaflet-trackplayer两个主要库 leaflet官方文档 npm install leaflet npm install leaflet-trackplayer然后在页面中引用 html <template><button click"playMap&quo…

LLM - 理解 多模态大语言模型 (MLLM) 的指令微调与相关技术 (四)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142063880 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 完备(F…

第 12 篇 Helm 部署 Redis

文章目录 Redis Chart部署 Redis 单机版部署 Redis 哨兵版第 1 步&#xff1a;准备 values.yaml 配置文件第 2 步&#xff1a;安装 bitnami/redis第 3 步&#xff1a;解决 Pod Pending 问题查看 Pod 状态添加 PV 持久化卷创建 pv1创建 pv2创建 pv3 查看 Pod 状态 第 4 步&#…

java实际开发——数据库存储金额时用什么数据类型?(MySQL、PostgreSQL)

目录 java开发时金额用的数据类型——BigDecimal MySQL存储金额数据时用的数据类型是——decimal PostgreSQL存储金额数据时用的数据类型是——decimal 或 money java开发时金额用的数据类型——BigDecimal https://blog.csdn.net/Jilit_jilit/article/details/142180903?…

传统Malmquist-Luenberger指数与全局Malmquist-Luenberger指数的区别

1.全局技术前沿的构建 1.1传统ML指数 技术前沿的时间依赖性 传统的Malmquist-Luenberger&#xff08;ML&#xff09;指数在每个时期&#xff08;例如年份&#xff09;单独构建各自的技术前沿。这意味着每个时期的生产可能性集合和技术效率都是基于该时期的数据。 不可比性问…

【包教包会】CocosCreator3.xSprite和Label渐变色(支持3.x、支持原生、可合批)

完美适配Web、原生平台&#xff08;其余平台没测过&#xff09;。 下载地址&#xff1a;水煮肉片饭/Palette3.x 如何导入自己项目&#xff1a; 1、将Demo中Palette.ts复制到自己项目assets目录下 2、新建一个Sprite或Label节点&#xff0c;将Palette组件挂上去 3、设置顶点…

openstack之glance介绍

概念 glance为nova提供镜像服务&#xff0c;用于启动实例&#xff0c;预建镜像已安装cloud-init&#xff0c;可以访问openstack基金会获取操作系统镜像&#xff1a;官方镜像 格式 raw&#xff1a;无格式的镜像&#xff1b; vhd&#xff1a;hyper-v使用的格式&#xff1b; vm…

arcgisPro地理配准

1、添加图像 2、在【影像】选项卡中&#xff0c;点击【地理配准】 3、 点击添加控制点 4、选择影像左上角格点&#xff0c;然后右击填入目标点的投影坐标 5、依次输入四个格角点的坐标 6、点击【变换】按钮&#xff0c;选择【一阶多项式&#xff08;仿射&#xff09;】变换 7…

数据结构(7.3_1)——二叉排序树

二叉排序树&#xff0c;又称二叉查找树(BST,Binary Search Tree) 一棵二叉树或者是空二叉树&#xff0c;或者是具有如下性质的二叉树&#xff1a; 左子树上所有结点的关键字均小于根结点的关键字&#xff1b;右子树上所有结点的关键字均大于根结点的关键字&#xff1b;左子树…

系统优化工具 | PC Cleaner v9.7.0.3 绿色版

PC Cleaner是一款功能强大的电脑清理和优化工具&#xff0c;旨在通过清理系统垃圾文件、解除恶意软件和优化系统性能来提高计算机的运行效率。该软件提供了多种功能&#xff0c;可以帮助用户维护和提升计算机的整体表现。 PC Cleaner 支持 Windows 7 及以上操作系统&#xff0…

餐饮+KTV点歌一体化思路-—SAAS本地化及未来之窗行业应用跨平台架构

一、餐饮KTV点歌一体化 1. 多元化体验&#xff1a;为顾客提供了餐饮和娱乐的双重享受&#xff0c;满足了不同需求&#xff0c;增加了顾客的停留时间和消费可能性。 2. 增加消费机会&#xff1a;顾客在享受美食的同时可以唱歌娱乐&#xff0c;可能会增加酒水、小吃等额外消费。…

【我的 PWN 学习手札】Unlink Attack

目录 前言 一、Unlink介绍 二、保护和限制 &#xff08;1&#xff09;FD->bk P AND BK->fd P &#xff08;2&#xff09;chunksize(P) prev_size(next_chunk(P)) &#xff08;3&#xff09;largebin chunk 三、适用场景 四、利用与绕过 &#xff08;1&#…

Day 11-12:查找

目录 概念 方法 折半查找 前提 算法思路 分块查找 算法思路 哈希表 概念 构造哈希函数的方法 保留除数法 处理冲突的方法 开放地址法&#xff08;二次探查法&#xff09; 链地址法&#xff08;重要&#xff09; 哈希表的实现 结构体的创建 哈希表的创建 哈希…

Agent实战——使用 Dify 和 Moonshot API 构建 AI 工作流

引言 在当今的大模型应用浪潮中&#xff0c;AI Agent的开发和集成已经成为技术革新的重要方向。随着大模型的不断进步&#xff0c;如何利用这些强大的模型来简化复杂的任务&#xff0c;并将其集成到企业的生产环境中&#xff0c;成为开发者和企业共同关注的焦点。在2024年稀土…

linux-L3_linux 查看进程(node-red)

linux 查看进程 以查看进程node-red为例 ps aux | grep node-red

自制游戏手柄--Android画面的input输入控制

在使用传感器获取到运动数据后&#xff0c;怎样转换为input事件传给手机呢&#xff0c;这里以Android为例&#xff0c; 我们可以考虑以下方式&#xff1a; 1. 物理方式&#xff0c;使用舵机连接触碰笔去实现&#xff0c; 2. 构造MotionEvent事件&#xff0c;注入input&#…