UPS BP650CH实现nas自动关机

news2024/9/28 13:27:59

家里有个自己拼凑的nas需要防止断电不正常关机,因此购买了施耐德后背式BP650CH,之所以选这款是因为带了串口,串口终究还是很方便的东西。不管linux还是window还是其他系统都能够使用,通过串口直接获得ups的信息,就不需要关心操作系统是什么了。

BP650CH的串口协议参考这篇文档是BP650CHBP1000CH串口通信协议.pdf-原创力文档 (book118.com)

默认波特兰2400,8bit数据,1bit停止位,无检验。SecureCRT设置如下

由于这个施耐德的UPS串口并非终端交互式的,因此我们不适合用SecureCRT,采用其他输入和输出分离的串口助手。

我使用Arduino IDE中的串口助手,设置如下

按照手册,首先需要登录到UPS,方法就是输入M回车,那么串口会返回一个V

接着输入QS回车,这个命令是检索状态。注意施耐德的串口交互命令都是回车结尾。

反正QS命令返回的结果格式为:

(是结果的开始,然后后面的数值用空格分开

216.1=输入电压216.1伏特(有效值rms)

216.1=输入故障电压216.1伏特(有效值rms)

216.1=输出电压216.1伏特(有效值rms)

 000=输出负载,因为我UPS没有接负载,所以就是0,单位是百分比

50.0=输出电压的频率是50Hz

13.5=电池电压13.5V(有效值rms)

 --.-=内部温度,似乎没法显示内部温度

00001001=UPS状态字节b7~b0

b6为高位的话指示电池电压低

b4为高位指示UPS故障

 剩下的看手册

测试1:关闭UPS的市电输入,蜂鸣器10秒叫一次,QS命令检索状态发现UPS的状态字节最高位变成了1,这个时候就可以通知用户进行关机了

测试2:使用破旧没有电池的笔记本电脑装linux系统做断电自动关机的测试。

        将USB转串口线插到电脑,lsusb发现串口PL2303驱动

ls /dev/tty*发现串口设备ttyUSB0

安装minicom软件:yum install minicom

然后minicom -s进入设置,选择Serial port setup。然后设置如下

然后save setup as dfl,下次就不用设置了

然后exit from minicom

接着输入minicom

输入M登录后,输入QS就可以查询数据了

退出minicom方法,ctrl+A后,然后按Z,然后按X,然后yes

 但是minicom是交互式的,因此我们需要自己写一个程序实现ups的状态扫描来实现关机

#include<stdio.h>  
#include<fcntl.h>  
#include<stdlib.h>  
#include<unistd.h>  
#include<termios.h>  
#include<string.h>  
#include<sys/select.h>  
int serialDevFD;//串口设备描述符
char *serialDev = "/dev/ttyUSB0";
void serialDevOpen()
{
    serialDevFD = open(serialDev,O_RDWR|O_NOCTTY|O_NDELAY);//读写方式打开串口设备,后面两个属性不用管
    if(serialDevFD<0)
    {
        printf("Serial port device %s open failed!!!\n",serialDev);
        perror(serialDev);
        exit(1);
    }
    printf("Serial port device %s open success, file descriptor = %d\n",serialDev,serialDevFD);
}
void serialDevClose()
{
    close(serialDevFD);
    printf("Serial port device %s close success\n",serialDev);
}
//延时n秒
void sleepSecond(int n)
{
    sleep(n);
}
//串口通信参数配置
void serialDevCfg()
{
   struct termios newT;//新的配置信息结构体  
   memset(&newT,0,sizeof(newT));//结构体清零  
   cfsetispeed(&newT,B2400);//设置input/output波特率都是2400
   cfsetospeed(&newT,B2400);  
   //  
   newT.c_cflag |= (CLOCAL|CREAD);  
   newT.c_cflag &=~CSIZE;  
   //设置数据位8位  
   newT.c_cflag |= CS8;  
   //设置无校验  
   newT.c_cflag &= ~PARENB;  
   newT.c_iflag &= ~INPCK;  
   //设置停止位1位  
   newT.c_cflag &= ~CSTOPB;  
   //  
   newT.c_cc[VTIME]=0;  
   newT.c_cc[VMIN]=0;  
  
   tcflush(serialDevFD,TCIOFLUSH);  
   if(tcsetattr(serialDevFD,TCSANOW,&newT)!=0){  
    perror("set Baud failed");  
    exit(1);  
   }else {
   	printf("Serial port device %s set params success\n",serialDev);
   }
}

//登录和监控ups
char *UPS_LOGIN = "M\r";
char *UPS_STATUS = "QS\r";
void serialMonitor()
{
    fd_set rds;
	int	ret;
	int len;
	char buf;
	char arr[300];
	write(serialDevFD,UPS_LOGIN,2);//登录
	int loginIndex = 0;
    while(1)
	{
		FD_ZERO(&rds);
		FD_SET(serialDevFD,&rds);
		/*调用select检查是否能够从/dev/input/event0设备读取数据*/
		ret = select(serialDevFD+1, &rds, NULL, NULL, NULL );
		if ( ret < 0 )
		{
			perror( "select" );
			exit(2);
		}
		/*能够读取到数据*/
		else if (FD_ISSET(serialDevFD,&rds))
		{
		    len = read(serialDevFD,&buf,1);
		    if(len==1)
		    {
		        arr[loginIndex++] = buf;
		        if(loginIndex==2)
		        {
		            if(arr[1]=='\r'){
                      arr[1]='<';
                      arr[2] = 'c';
                      arr[3]='r';
                      arr[4] = '>';
                    }
		            arr[5] = '\0';
		            printf("接收到UPS登录响应=%s\n",arr);
		            break;
		        }
		    }
		}
	}
	
	
	//
	int duration = 3;//监测周期,单位秒
	int count = 0;//计数器,检测到断电后再检测2次如果真的没有电就关机
	int statusIndex = 0;
	write(serialDevFD,UPS_STATUS,3);
	while(1)
	{
		FD_ZERO(&rds);
		FD_SET(serialDevFD,&rds);
		/*调用select检查是否能够从/dev/input/event0设备读取数据*/
		ret = select(serialDevFD+1, &rds, NULL, NULL, NULL );
		if ( ret < 0 )
		{
			perror( "select" );
			exit(2);
		}
		/*能够读取到数据*/
		else if (FD_ISSET(serialDevFD,&rds))
		{
		    len = read(serialDevFD,&buf,1);
		    if(len==1)
		    {
                if(buf=='\r'){
                   //printf("<cr>\n");
                   arr[statusIndex] = '\0';
                   printf("接收到ups状态响应=%s<cr>\t",arr);
                   int pass = 1;
                   /*                  ups状态数据合法性检查         */
                   //检查长度是否是46个字符
                   if(statusIndex!=46) pass = 0;
                   //检查第一个字符是不是左括号
                   if(arr[0]!='(') pass = 0;
                  
                   if(pass==1)
                   {
                       printf("ups状态数据合法,");
                       //检测市电是否发生了断电
                       if(arr[38]=='1')
                       {
                           printf("发生了断电\n");
                           count++;
                           if(count==3)
                           {
                             printf("ups发生断电,执行关机命令\n");
                             system("shutdown -h now");  
                           }
                       }else
                       {
                           printf("市电输入正常\n");
                           count = 0;
                       }
                   }else
                   {
                       printf("ups状态数据不合法,跳过\n");
                   }
                   
                   sleepSecond(duration);
                   statusIndex = 0;
                   write(serialDevFD,UPS_STATUS,3);
                }else{
                   //printf("%c",buf);
                   arr[statusIndex++] = buf;
                }
		    }
		}
	    
	   
	}
}
int main(){  
  serialDevOpen();
  serialDevCfg();
  serialMonitor();
  serialDevClose();
  return 0;  
}  

 Makefile如下:

CROSS=  
TARGET=upsMonitor
SRC=main.c  
all: $(TARGET)  
  
$(TARGET):$(SRC)  
	$(CROSS)gcc -std=c99 -o $(TARGET) $(SRC)  
	$(CROSS)strip $(TARGET)  
clean:  
	@rm -vf $(TARGET) *.o *~  

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

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

相关文章

JDBC Maven MyBatis

文章目录JDBC&#xff08;Java Database Connectivity&#xff09;入门API详解DriverManger&#xff08;驱动管理类&#xff09;Connection(数据库连接对象)作用StatementResultSet&#xff08;结果集对象&#xff09;PreparedStatement连接池MavenMaven模型Maven 常用命令依赖…

简单二叉树的介绍

1.树的结构&#xff08;了解&#xff09;1.1概念树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0)个有限节点总成一个具有层次关系的集合。把它叫做树是因为它看起来像一颗倒挂的树&#xff0c;也就是说它的根是朝上&#xff0c;而叶子是朝下的&#xff08;本人…

工作玩手机识别监测系统 YOLOv5

工作玩手机识别监测系统通过YOLOV5网络深度学习算法模型对画面中人员玩手机行为进行实时监测&#xff0c;当识别到有人在玩手机行为时&#xff0c;无需人为干预立即抓拍存档触发告警。YOLO算法- YOLO算法是一种基于回归的算法&#xff0c;它不是选择图像中有趣的部分&#xff0…

WT588D语音芯片介绍

WT588D语音芯片简介WT588D 语音芯片是一款功能强大的可重复擦除烧写的语音单片机芯片。WT588D 让语音芯片不再为控制方式而寻找合适的外围单片机电路&#xff0c;高度集成的单片机技术足于取代复杂的外围控制电路。配套WT588DVoiceChip 上位机操作软件可随意更换WT588D 语音单片…

基于 docker 搭建 mysql5.7 主从复制

安装 docker 的教程可以看我的另一篇文章&#xff0c;拉取 mysql 镜像的步骤也在里面&#xff0c;在这不再重复&#xff1a;https://blog.csdn.net/wanzijy/article/details/128695674 1. 主机搭建 因为本人虚拟机中已经存在了 mysql &#xff0c;所以在使用镜像创建容器的时…

【论文翻译】End-to-End Human Pose and Mesh Reconstruction with Transformers

【cvpr论文】End-to-End Human Pose and Mesh Reconstruction with Transformers (thecvf.com) 【github】microsoft/MeshTransformer: Research code for CVPR 2021 paper "End-to-End Human Pose and Mesh Reconstruction with Transformers" (github.com) 摘要 我…

学习笔记:Java 并发编程③

若文章内容或图片失效&#xff0c;请留言反馈。 部分素材来自网络&#xff0c;若不小心影响到您的利益&#xff0c;请联系博主删除。 视频链接&#xff1a;https://www.bilibili.com/video/av81461839配套资料&#xff1a;https://pan.baidu.com/s/1lSDty6-hzCWTXFYuqThRPw&am…

在甲骨文云容器实例(Container Instances)上部署Ubuntu Desktop

甲骨文云推出了容器实例&#xff0c;这是一项无服务器计算服务&#xff0c;可以即时运行容器&#xff0c;而无需管理任何服务器。 今天我们尝试一下通过容器实例部署Ubuntu Bionic Desktop。 创建容器实例 在甲骨文容器实例页面&#xff0c;单击"创建容器实例"&…

Java 笔试题

Java 笔试题目录概述需求&#xff1a;设计思路实现思路分析1.java 面试题参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challenge Surviv…

分享151个PHP源码,总有一款适合您

PHP源码 分享151个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 151个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/1T_Hs4j0t39b-Y8UWHmAKyw?pwd7ao0 提取码&#…

论文浅尝 | DB4Trans:数据库内置知识图谱嵌入模型训练引擎

笔记整理&#xff1a;柳鹏凯&#xff0c;天津大学硕士发表期刊&#xff1a;计算机学报 第45卷Vol.45, 第9期 No.9链接&#xff1a;http://cjc.ict.ac.cn/online/onlinepaper/lpk-202297212908.pdf动机知识图谱嵌入技术主要将知识图谱中的实体和关系嵌入到连续的向量空间中&…

Centos Java1.8+Nginx+redis+pgsql 手工配置

一、系统升级&#xff0c;安装系统常用工具及配置 1.1 升级软件及Centos 内核 yum update -y yum clean all cat /etc/redhat-release 1.2 安装虚拟机守护进程 yum install qemu-guest-agent -y 1.3 安装系统常用工具包 yum install lrzsz vim wget dnf -y 1.4关…

2023牛客寒假算法基础集训营3 -- E-勉强拼凑的记忆(贪心 + 二分)

题目如下&#xff1a; 题解 or 思路&#xff1a; 我们可以发现&#xff1a;除了 n2n 2n2 无解&#xff0c; 其他情况答案至少为 n12\frac{n 1}{2}2n1​ 答案在 n12\frac{n 1}{2}2n1​ 到 nnn 之间 我们可以假设 答案为 ansansans 最优摆放为&#xff1a; 所以可以二分去求…

软件工程 黄金点游戏

这个故事最初出现在 《移山之道》中&#xff0c;我经常拿来做和创新的时机相关课堂练习和讨论&#xff0c;效果很好。我把这个练习和它的一些延伸话题都搬到这个新博客里。 黄金点游戏 N个同学&#xff08;N通常大于10&#xff09;&#xff0c;每人写一个 0~100之间的有理数 …

1、认识IntelliJ IDEA

文章目录1、认识IntelliJ IDEA1.1 JetBrains公司介绍1.2 IntelliJ IDEA介绍1.3 IDEA的主要优势&#xff08;对比Eclipse&#xff09;1.3.1 功能强大1.3.2 符合人体工程学1.4 IDEA的下载【尚硅谷】idea实战教程-讲师&#xff1a;宋红康 生活是属于每个人自己的感受&#xff0c;不…

Python:Docx文档模板创建使用

✨博文作者 wangzirui32 &#x1f496; 喜欢的可以 点赞 收藏 关注哦~~ &#x1f449;本文首发于CSDN&#xff0c;未经许可禁止转载 &#x1f60e;Hello&#xff0c;大家好&#xff0c;我是wangzirui32&#xff0c;今天我们来学习Docx文档模板创建与使用&#xff0c;开始学习吧…

2023新春祝福html代码,包你学会

前言大家新年好&#xff01;今天是年三十&#xff0c;在这个充满喜悦和欢乐的节日里&#xff0c;祝大家新年快乐。不论你在外面过的风生水起还是不尽人意&#xff0c;回到家一家人团团聚聚才是最好的。进入正题&#xff0c;我们作为IT民工&#xff0c;我们要用自己的方式表达对…

第三天总结 之 商品管理界面的实现 之 页面中 下拉框问题的解决

页面中下拉框问题的解决 在页面中 点击商品类型这个图标 会出现下拉框 展示所有的商品类型 然后通过选择的 类型 来作为 查询时的一个条件 即 当不选或选择展示所有商品时 按照 不对这个条件进行操作 选择其他的商品类型时 会查询出含有该类型的商品 下拉框中 数据的展示与 如…

java设计模式中责任链模式是什么/怎么用责任链模式避免if-else语句

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.5 责任链模式 6.5.1 定义 职责链模式&#xff0c;为避免请求发生者与多个处理者耦合在一起&#xff0c;将所有请求处理者通过前一对象记住其下一对象的引用而连…

重学Attention

注意力机制对比RNN 主要解决了RNN无法并行&#xff0c;并且不能解决长序列依赖问题 所以为什么设计 Q K V这三个矩阵 一边来是让 K V的 首先通过Q 和 K点击计算Attention矩阵&#xff0c;这个矩阵表明的是V上每一个特征与Q的相关程度&#xff0c;相关程度高的&#xff0c;权重…