最近到手一款科星的2路网络继电器,官方有提供上位机方便调试,但是要运用在具体项目中就需要自己编写程序,本文基于ROS平台通过C++编写程序通过socket控制该继电器。

目录

(一)测试报文

(二)创建调试节点

(三)继电器控制节点

3.1 入口

3.2 初始化

3.2 判断调试命令

3.4 连接网络

3.5 执行命令与读取继电器状态

(四)运行结果


(一)测试报文

首先通过官方上位机对继电器继续配置,设定好继电器连接的wifi网络以及自身的ip和端口,再切换到ubuntu系统,下载安装网络调试助手,根据官方提供的指令集详解中的报文进行测试

(二)创建调试节点

在正式开始编写继电器的控制程序前,先创建一个调试节点,用于对继电器控制节点发送命令,控制继电器开关,通过四位数控制继电器的各个功能。

#include <iostream>
#include "ros/ros.h"
#include "std_msgs/Int64.h"int main(int argc, char *argv[]){setlocale(LC_ALL, "");ros::init(argc, argv, "manage");ros::NodeHandle nh;ros::Publisher manage_pub = nh.advertise<std_msgs::Int64>("io_cmd", 10);ros::Rate loop_rate(10);std::cout << "选择输入: 编号+控制字,例如1001" << std::endl;std::cout << "请先输入  x+000  连接网络" << std::endl;std::cout << "001      ——打开DO1"<< std::endl;std::cout << "002       ——关闭DO1"<< std::endl;std::cout << "010       ——打开DO2"<< std::endl;std::cout << "020      ——关闭DO2"<< std::endl;std::cout << "011       ——全开"<< std::endl;std::cout << "022       ——全闭"<< std::endl;std::cout << "066      ——读取继电器状态"<< std::endl;std::cout << "077      ——读取开光量状态"<< std::endl;std::cout << "099      ——断开连接"<< std::endl;while (ros::ok()){std_msgs::Int64 msg;std::cout << "命令输入:";std::cin >>  msg.data;manage_pub.publish(msg);ros::spinOnce();loop_rate.sleep();}return 0;
}

(三)继电器控制节点

3.1 入口

int main(int argc, char *argv[]) {setlocale(LC_ALL, "");ros::init(argc, argv, "relay");ros::NodeHandle nh("~");init(nh);ros::Subscriber relay_sub = nh.subscribe("/io_cmd", 10, flag_message);ros::spin();
}

重点在于初始化和订阅上面的调试节点获得命令。

3.2 初始化

void init(ros::NodeHandle &nh)
{nh.param<std::string>("relay_addr_1", relay_addr_1, "192.168.1.18");nh.param<std::string>("relay_addr_2", relay_addr_2, "192.168.1.19");relay_pub = nh.advertise<std_msgs::Int64>("status_out", 10);ROS_INFO("Relay node initialization completed!");
}

这里的初始化比较简单,主要是通过param传入多个继电器的ip,实现一次性通讯多个WIFI继电器,另外是定义了一个发布话题,将后面获取的继电器状态发布出去,方便在项目中应用。

3.2 判断调试命令

void flag_message(const std_msgs::Int64::ConstPtr& manage)
{int control_msg = manage->data;int relay_num = (int)control_msg/1000;// std::cout << relay_num <<std::endl;int control_instruction = control_msg%1000;// std::cout << control_instruction <<std::endl;if(control_instruction == 0 && !network_connections){      //连接网络recovery(relay_num);send_topic_msg(relay_num*1000);// x000 继电器联网成功反馈current_sockfd_num = relay_num;return;}else if(control_instruction != 0 && !network_connections){ROS_INFO("请先连接网络");return;}if(current_sockfd_num == relay_num && network_connections){switch(control_instruction){case 1:                                                                     //打开DO1send_relay_msg({ 0xCC, 0xDD, 0xA1, 0x01, 0x00, 0x01, 0x00,0x01,0xA4,0x48 });read_feedback_status(relay_num);break;case 2:                                                                     //关闭DO1send_relay_msg( { 0xCC, 0xDD, 0xA1, 0x01, 0x00, 0x00, 0x00,0x01,0xA3,0x46 });read_feedback_status(relay_num);break;case 3:                                                                     //反转send_relay_msg({ 0xCC, 0xDD, 0xA1, 0x01, 0x00, 0x01, 0x00,0x03,0xA6,0x4C });read_feedback_status(relay_num);break;case 4:                                                                     //反转send_relay_msg({ 0xCC, 0xDD, 0xA1, 0x01, 0x00, 0x02, 0x00,0x03,0xA7,0x4E });read_feedback_status(relay_num);break;case 10:                                                                   //打开DO2send_relay_msg( { 0xCC, 0xDD, 0xA1, 0x01, 0x00, 0x02, 0x00,0x02,0xA6,0x4C });read_feedback_status(relay_num);break;case 20:                                                                   //关闭DO2send_relay_msg( { 0xCC, 0xDD, 0xA1, 0x01, 0x00, 0x00, 0x00,0x02,0xA4,0x48 });read_feedback_status(relay_num);break;case 11:                                                                   //全开send_relay_msg({ 0xCC, 0xDD, 0xA1, 0x01, 0xFF, 0xFF, 0xFF,0xFF,0x9E,0x3C });//CC DD A1 01 FF FF FF FF 9E 3Cread_feedback_status(relay_num);break;case 22:                                                                   //全闭send_relay_msg({ 0xCC, 0xDD, 0xA1, 0x01, 0x00, 0x00, 0xFF,0xFF,0xA0,0x40 });//CC DD A1 01 00 00 FF FF BE 7Cread_feedback_status(relay_num);break;case 66:                                                                   //读取继电器状态send_relay_msg({ 0xCC, 0xDD, 0xB0, 0x01, 0x00, 0x00, 0x00,0x0D,0xBE,0x7C });read_out_status(relay_num);break;case 77:                                                                   //读取开关状态send_relay_msg( {0xCC, 0xDD, 0xC0, 0x01, 0x00, 0x00, 0x00,0x0D,0xCE,0x9C });read_in_status(relay_num);break;case 99:                                                                   //断开连接close(sockfd);network_connections = false ;send_topic_msg(relay_num*1000 + 99);// x099 继电器断开连接成功反馈ROS_INFO("断开连接");break;default:ROS_WARN("[WIFI relay]Abnormal control status of WIFI repeater!");}}else{ROS_WARN("[WIFI relay]Abnormal control status of WIFI repeater!");}
}

将main中订阅的话题消息传入这个回调函数,根据调试节点中规定的命令条件编写判断,分别进行不同功能。

3.4 连接网络

void recovery(const int &relay_num){if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);exit(0);}memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;if(relay_num == 1){servaddr.sin_addr.s_addr = inet_addr( relay_addr_1.c_str());servaddr.sin_port = htons(50000);}else if(relay_num == 2){servaddr.sin_addr.s_addr = inet_addr( relay_addr_2.c_str());servaddr.sin_port = htons(50000);  }else{ROS_WARN("WIFI relay No. %u failed to connect to the network",relay_num);return;}if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){printf("connect error: %s(errno: %d)\n",strerror(errno),errno);exit(0);}network_connections = true;ROS_INFO("%u号继电器连接网络",relay_num);
}

继电器与主机的通讯依靠socket通信,在接受到连接网络的命令后创建一个套接字(目前只预留了两个位置,同时只能连接一个),后面对这个套接字进行操作,关闭网络连接时注销这个套接字。

3.5 执行命令与读取继电器状态

void send_relay_msg(const buff_send &relay_msg){send(sockfd, relay_msg.msgs, sizeof(relay_msg),0);
}void read_out_status(const int &relay_num){unsigned char buff_recv[4096];int t = recv(sockfd, buff_recv, MAXLINE, 0);if(t > 0){int status_bit = (unsigned int)buff_recv [5];switch(status_bit){case 0:send_topic_msg(relay_num*1000 + 1);ROS_INFO("DO1 OFF,DO2 OFF");break;case 1:send_topic_msg(relay_num*1000 + 2);ROS_INFO("DO1 ON,DO2 OFF");break;case 2:send_topic_msg(relay_num*1000 + 3);ROS_INFO("DO1 OFF,DO2 ON");break;case 3:send_topic_msg(relay_num*1000 + 4);ROS_INFO("DO1 ON,DO2 ON");break;default:ROS_WARN("[WIFI relay]Abnormal WIFI relay status!");return;}}else{ROS_WARN("[WIFI relay]Abnormal reading of WIFI relay data status!");}
}void read_in_status(const int &relay_num){unsigned char buff_recv[4096];int t = recv(sockfd, buff_recv, MAXLINE, 0);if(t > 0){int status_bit = (unsigned int)buff_recv [5];switch(status_bit){case 0:send_topic_msg(relay_num*1000 + 10);ROS_INFO("DI1 OFF,DI2 OFF");break;case 1:send_topic_msg(relay_num*1000 + 20);ROS_INFO("DI1 ON,DI2 OFF");break;case 2:send_topic_msg(relay_num*1000 + 30);ROS_INFO("DI1 OFF,DI2 ON");break;case 3:send_topic_msg(relay_num*1000 + 40);ROS_INFO("DI1 ON,DI2 ON");break;default:ROS_WARN("[WIFI relay]Abnormal WIFI relay status!");return;}}else{ROS_WARN("[WIFI relay]Abnormal reading of WIFI relay data status!");}
}void read_feedback_status(const int &relay_num){char buff_recv[4096];int t = recv(sockfd, buff_recv, MAXLINE, 0);if(t > 0){send_topic_msg(relay_num*1000 + 88);// x088 继电器执行成功反馈// std::cout << buff_recv << std::endl;ROS_INFO("Sending msg :%c%c!",buff_recv[0],buff_recv[1]);}
}

在完成3.2的判断之后,将下发的命令对应的报文通过socket的send发送到网络继电器,同时通过read读取网络继电器回馈的报文,可以判断命令是否成功执行。并可以通过查询继电器状态的报文主动获取网络继电器当前的状态。

(四)运行结果

由于没有连接上网络继电器,第一次发送命令时会直接崩溃,第二次直接发送指令报文,能正确识别并提醒。

[C++/ROS]通过socket控制科星WIFI继电器相关推荐

  1. php和javascript的get和post方式 有人串口转wifi模块httpdclient网页交互通信成功源码2 wifi继电器小黄人软件ypnr

    全部源码下载:链接: http://pan.baidu.com/s/1qXxr0i4 密码: 有人串口转wifi模块 httpd client通信示例-用户使用网页通过服务器收发串口数据get 功能: ...

  2. 使用Blinker控制esp01s Relay继电器模块

    目录 一.ESP-01s和ESP-01区别 外观区别 电路区别 二.ESP-01s引脚 管脚示意图 管脚功能定义 电路原理图 三.控制esp01s Relay 安装blinker arduino库 申 ...

  3. 基于51单片机51wifi控制4路继电器开关定时功能

    项目简介: 一款基于STC89C52单片机的手机WIFI控制4路继电器的插座控制器设计.通过安装手机APP实现手机和设备的互联,只要手机发送相应的指令,继电器将会按照相关指令进行操作该设计极大的方便了 ...

  4. python串口控制8通道继电器方法笔记

    python串口控制8通道继电器方法笔记 保存当前文件为RelayControl.py,在其他py文件引用时,使用from RelayControl import relay 格式导入 调用时,使用 ...

  5. 航模遥控继电器单通道控制2路继电器开关实现原理解析

    航模遥控继电器单通道控制2路继电器开关实现原理解析 航模遥控继电器 硬件解析 两路型号为: SRD-05VDC-SL-C 继电器 2个PC817光耦 3个S4,1N5819WS肖特基二极管 2个S80 ...

  6. 安卓情景模式开发-控制GPS/WIFI/蓝牙/飞行模式/控制静音/音量/振动

    http://www.cnblogs.com/wii/archive/2012/03/18/2404947.html 对于android上GPS的控制,官方提供了相关的API Settings.Sec ...

  7. android manager provider模式,安卓情景模式开发(一)-控制GPS/WIFI/蓝牙/飞行模式...

    对于android上GPS的控制,官方提供了相关的API Settings.Secure.setLocationProviderEnabled(getContentResolver(), Locati ...

  8. ESPHome入门02 - 开关控制 (小白入门 - (继电器控制) 开关卧室灯)

    ESPHome入门02 - 开关控制 (小白入门 - (继电器控制) 开关卧室灯) 现在开始正式进入ESPHome的编程 (确切来说只是配置一些参数, 不要担心学不会, 根据教程 一步步来 很容易实现 ...

  9. 大一电赛:51单片机(状态机编程)——控制外部开关(继电器)达到自定义输出波

    题目来源于某双流一大学第八届"电协杯"电子设计(校赛) 大一C组:自定义信号发生器 队伍名称:摆烂三人组 下文有对相应软件和硬件的实现进行介绍 复盘电赛(软件部分) 读题方面 定时 ...

最新文章

  1. 链家员工因不满工作调动,怒删公司9TB大数据,获判7年
  2. 增删改查 HTML表格页面,表格增删改查.html
  3. 计算机游戏的作文,玩电脑游戏作文
  4. 在CentOS6.2下安装DNS服务软件Bind并快速配置简单实例
  5. 华科计算机复试ccf成绩,新鲜速递!刚拟录取华科学妹总结的复试攻略,快看
  6. 蒙哥马利java算法_算法详解 - 蒙哥马利算法的概念与原理
  7. Linux各个目录的用途
  8. angularjs路由_AngularJS路由示例– ngRoute,$ routeProvider
  9. python torchvision_pip install torchvision error:安装版本为0.4.1的torch后继续安装torchvision报错...
  10. Linux多线程通信
  11. SQL Server 2016 CTP3.2 开荒 Reporting Service 篇
  12. Atitit.mysql oracle with as模式临时表模式 CTE 语句的使用,减少子查询的结构性 mssql sql server..
  13. 《麦肯锡方法》读书笔记21
  14. 字符间距和文字效果(转)
  15. ndows 资源管理器,windows资源管理器不见了.怎么办?
  16. 帝国CMS仿玩游戏网源码大型游戏资讯网站源码
  17. 计算机函数的输入,向计算机输入复杂的数学函数公式怎样处理?
  18. 毕业去哪儿?看这里!神策数据 2023 校园招聘启动啦
  19. 一级b计算机excel有几题,一级B练习的Excel题库.doc
  20. 瑞幸咖啡完成债务重组:陆正耀出局 股东大钲资本成实控方

热门文章

  1. 《图解数据结构》(第二版)读书笔记
  2. C51单片机-1只LED灯闪烁
  3. 从零开始学人脸检测之Retinaface篇(内含魔改版GhostNet+mbv2)
  4. 猫猫学iOS之安装cocoapods
  5. paintkeep未能连接到服务器,Paintkeep
  6. 计算机桌面一直刷新,win7自动刷新桌面怎么办_win7一直自动刷新桌面的解决方法...
  7. 命令注入-命令的连接符【‘’‘’‘||’‘|’】的含义及其用法
  8. 打造自己本地的渗透测试武器库-工欲善其事必先利其器
  9. mysql带有子查询的like查询
  10. android如何定时息屏_Android亮屏和熄屏控制实例详解