控制器待完善
This commit is contained in:
commit
98f4de74d2
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/.cache
|
||||
/.vscode
|
||||
/bin
|
||||
/build
|
||||
/unused
|
||||
/log
|
||||
/packages
|
||||
/crs
|
||||
/.xmake
|
||||
/compile_commands.json
|
||||
|
||||
1
AbilitySDK
Submodule
1
AbilitySDK
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e20893b78a520157efeb28aeadb5914c5435d8f8
|
||||
31
ConveyorBeltAbility/include/ConveyorBeltAbility.h.old
Normal file
31
ConveyorBeltAbility/include/ConveyorBeltAbility.h.old
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
#include "ability_sdk/AbilityStub.hpp"
|
||||
#include "conveyorBeltGrpcServer.h"
|
||||
|
||||
|
||||
class ConveyorBeltAbility : public ability_sdk::AbilityStub<ConveyorBeltStatus> {
|
||||
public:
|
||||
using AbilityTemplate::AbilityTemplate;
|
||||
|
||||
void create_ability_server() {
|
||||
ConveyorBeltServer service_ability;
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort("0.0.0.0:0", grpc::InsecureServerCredentials(), &g_abilityPort);
|
||||
cout << "add listening port" << endl;
|
||||
builder.RegisterService(&service_ability);
|
||||
cout << "register service" << endl;
|
||||
ability_cq = builder.AddCompletionQueue();
|
||||
ability_server = builder.BuildAndStart();
|
||||
std::cout << "Server listening on port: " << g_abilityPort << std::endl;
|
||||
sendStateMsg();
|
||||
ability_server->Wait();
|
||||
std::cout << "finish ipc server" << std::endl;
|
||||
}
|
||||
|
||||
void runServer() {
|
||||
g_GLOBAL_STATUS = STATUS_INIT;
|
||||
std::cout << "NOW GLOBAL STATUS IS: " << global2string(g_GLOBAL_STATUS) << std::endl;
|
||||
std::thread heartbeat_thread(&ConveyorBeltAbility::heartbeat_loop, this);
|
||||
heartbeat_thread.detach();
|
||||
}
|
||||
};
|
||||
64
ConveyorBeltAbility/include/conveyorBeltAbility.hpp
Normal file
64
ConveyorBeltAbility/include/conveyorBeltAbility.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "ability_sdk/AbilityStub.hpp"
|
||||
#include "conveyorBeltGrpcServer.h"
|
||||
#include <thread>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
|
||||
class ConveyorBeltAbility : public ability_sdk::AbilityInterface {
|
||||
public:
|
||||
|
||||
int g_abilityPort = 0;
|
||||
std::unique_ptr<Server> ability_server;
|
||||
std::unique_ptr<grpc::ServerCompletionQueue> ability_cq;
|
||||
|
||||
// GRPC 服务端
|
||||
void create_ability_server();
|
||||
|
||||
void onStart() override{
|
||||
|
||||
LOG(WARNING) << "OnStart";
|
||||
|
||||
}
|
||||
|
||||
void onConnect() override {
|
||||
|
||||
LOG(WARNING) << "OnConnect";
|
||||
std::thread t_abilityserver(&ConveyorBeltAbility::create_ability_server, this);
|
||||
t_abilityserver.detach();
|
||||
|
||||
// 主线程轮询等待端口号更新
|
||||
while (g_abilityPort == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
}
|
||||
LOG(WARNING) << "GRPC Server listening on port: "<< g_abilityPort;
|
||||
|
||||
}
|
||||
|
||||
void onDisconnect() override {
|
||||
|
||||
LOG(WARNING) << "OnDisconnect";
|
||||
ability_server->Shutdown();
|
||||
ability_cq->Shutdown();
|
||||
g_abilityPort = 0;
|
||||
|
||||
}
|
||||
|
||||
void onTerminate() override {
|
||||
|
||||
LOG(WARNING) << "OnTerminate";
|
||||
onDisconnect();
|
||||
exit(0);
|
||||
|
||||
}
|
||||
|
||||
// 获取端口
|
||||
int abilityPort() const override {
|
||||
return g_abilityPort;
|
||||
}
|
||||
|
||||
void onSubabilityError(const ability_sdk::SubabilityErrorParam& param) override {
|
||||
LOG(INFO) << "onSubabilityError called in ConveyorBeltAbility";
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
57
ConveyorBeltAbility/include/conveyorBeltGrpcServer.h
Normal file
57
ConveyorBeltAbility/include/conveyorBeltGrpcServer.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef CONVEYOR_BELT_GRPC_SERVER_H_
|
||||
#define CONVEYOR_BELT_GRPC_SERVER_H_
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "conveyorBelt.grpc.pb.h"
|
||||
#include "conveyorBelt.pb.h"
|
||||
#include "conveyorBeltControlUnit.h"
|
||||
#include <glog/logging.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
using grpc::Server;
|
||||
using grpc::ServerBuilder;
|
||||
using grpc::ServerContext;
|
||||
using grpc::Status;
|
||||
|
||||
using ConveyorBelt::ConveyorBeltService;
|
||||
|
||||
typedef int RunningState;
|
||||
|
||||
class ConveyorBeltServer : public ConveyorBeltService::Service {
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
::grpc::Status open(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::SpeedInfo* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) override;
|
||||
::grpc::Status close(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::DeviceID* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) override;
|
||||
::grpc::Status setSpeed(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::SpeedInfo* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) override;
|
||||
::grpc::Status setDirection(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::DirectionInfo* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) override;
|
||||
::grpc::Status getWorkState(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::DeviceID* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) override;
|
||||
ConveyorBeltServer();
|
||||
~ConveyorBeltServer();
|
||||
};
|
||||
|
||||
#endif
|
||||
17
ConveyorBeltAbility/src/conveyorBeltAbility.cpp
Normal file
17
ConveyorBeltAbility/src/conveyorBeltAbility.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "conveyorBeltAbility.hpp"
|
||||
|
||||
|
||||
// GRPC 服务端
|
||||
void ConveyorBeltAbility::create_ability_server() {
|
||||
ConveyorBeltServer service_ability;
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort("0.0.0.0:0", grpc::InsecureServerCredentials(), &g_abilityPort);
|
||||
builder.RegisterService(&service_ability);
|
||||
LOG(WARNING) << "GRPC Server register service";
|
||||
ability_cq = builder.AddCompletionQueue();
|
||||
ability_server = builder.BuildAndStart();
|
||||
//LOG(WARNING) << "GRPC Server add listening port"<< g_abilityPort;
|
||||
ability_server->Wait();
|
||||
LOG(WARNING) << "finish ipc server";
|
||||
}
|
||||
|
||||
97
ConveyorBeltAbility/src/conveyorGrpcServer.cpp
Normal file
97
ConveyorBeltAbility/src/conveyorGrpcServer.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include "conveyorBeltGrpcServer.h"
|
||||
|
||||
ConveyorBeltControlUnit controlUnit;
|
||||
|
||||
::grpc::Status ConveyorBeltServer::open(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::SpeedInfo* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) {
|
||||
std::cout << "grpc call open start" << std::endl;
|
||||
if (controlUnit.getWorkState() == 0) {
|
||||
response->set_code(-1);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
float speed = request->speed();
|
||||
if (speed > 0.16) {
|
||||
response->set_code(-1);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
controlUnit.init();
|
||||
int ret = controlUnit.setSpeed(speed);
|
||||
if (ret < 0) {
|
||||
response->set_code(-1);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
controlUnit.startConveyorBelt();
|
||||
std::thread workThread(&ConveyorBeltControlUnit::conveyorBeltWorkingProcess, &controlUnit);
|
||||
workThread.detach();
|
||||
std::cout << "grpc call open finish" << std::endl;
|
||||
response->set_code(0);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
::grpc::Status ConveyorBeltServer::close(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::DeviceID* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) {
|
||||
std::cout << "grpc call close start" << std::endl;
|
||||
if (controlUnit.getWorkState() < 0) {
|
||||
response->set_code(-1);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
controlUnit.stopConveyorBelt();
|
||||
std::cout << "grpc call close finish" << std::endl;
|
||||
response->set_code(0);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
::grpc::Status ConveyorBeltServer::setSpeed(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::SpeedInfo* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) {
|
||||
std::cout << "grpc call set speed start" << std::endl;
|
||||
int ret = controlUnit.setSpeed(request->speed());
|
||||
if (ret < 0) {
|
||||
response->set_code(-1);
|
||||
::grpc::Status::OK;
|
||||
}
|
||||
std::cout << "grpc call set speed finish" << std::endl;
|
||||
response->set_code(0);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
::grpc::Status ConveyorBeltServer::setDirection(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::DirectionInfo* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) {
|
||||
std::cout << "grpc call set direction start" << std::endl;
|
||||
int ret = controlUnit.setDirection(request->direction());
|
||||
if (ret < 0) {
|
||||
response->set_code(-1);
|
||||
::grpc::Status::OK;
|
||||
}
|
||||
std::cout << "grpc call set direction finish" << std::endl;
|
||||
response->set_code(0);
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
::grpc::Status ConveyorBeltServer::getWorkState(
|
||||
::grpc::ServerContext* context,
|
||||
const ::ConveyorBelt::DeviceID* request,
|
||||
::ConveyorBelt::Response* response
|
||||
) {
|
||||
std::cout << "grpc call get state start" << std::endl;
|
||||
response->set_code(controlUnit.getWorkState());
|
||||
std::cout << "grpc call get state finish" << std::endl;
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
ConveyorBeltServer::ConveyorBeltServer() {}
|
||||
|
||||
ConveyorBeltServer::~ConveyorBeltServer() {}
|
||||
28
ConveyorBeltAbility/src/main.cpp
Normal file
28
ConveyorBeltAbility/src/main.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "conveyorBeltAbility.hpp"
|
||||
#include "ability_sdk/AbilityStub.hpp"
|
||||
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
|
||||
ability_sdk::configure_glog(argv[0]);
|
||||
ConveyorBeltAbility ability1;
|
||||
ability_sdk::IpcServerHandle handle(&ability1);
|
||||
handle.init(argc, argv);
|
||||
handle.run();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Init 阶段
|
||||
通过环境变量,尝试设置目录路径,启动glog
|
||||
启动 redis 客户端
|
||||
向框架读取,获取能力CR,填充ability_info, 并设置 heartbeater
|
||||
设置生命周期ipc服务器
|
||||
启动心跳包
|
||||
|
||||
Start 阶段
|
||||
|
||||
如果有子能力,则初始化SubabilityMgr,并读取子能力cr
|
||||
如果有子能力,尝试启动子能力
|
||||
启动状态同步机制 */
|
||||
29
ConveyorBeltControlUnit/include/color.h
Normal file
29
ConveyorBeltControlUnit/include/color.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef UTILS_COLOR_H_
|
||||
#define UTILS_COLOR_H_
|
||||
|
||||
#define EMPTY "\e[0m"
|
||||
#define BLACK "\e[0;30m"
|
||||
#define L_BLACK "\e[1;30m"
|
||||
#define RED "\e[0;31m"
|
||||
#define L_RED "\e[1;31m"
|
||||
#define GREEN "\e[0;32m"
|
||||
#define L_GREEN "\e[1;32m"
|
||||
#define BROWN "\e[0;33m"
|
||||
#define YELLOW "\e[1;33m"
|
||||
#define BLUE "\e[0;34m"
|
||||
#define L_BLUE "\e[1;34m"
|
||||
#define PURPLE "\e[0;35m"
|
||||
#define L_PURPLE "\e[1;35m"
|
||||
#define CYAN "\e[0;36m"
|
||||
#define L_CYAN "\e[1;36m"
|
||||
#define GRAY "\e[0;37m"
|
||||
#define WHITE "\e[1;37m"
|
||||
#define BOLD "\e[1m"
|
||||
#define UNDERLINE "\e[4m"
|
||||
#define BLINK "\e[5m"
|
||||
#define REVERSE "\e[7m"
|
||||
#define HIDE "\e[8m"
|
||||
#define CLEAR "\e[2J"
|
||||
#define CLRLINE "\r\e[K"
|
||||
|
||||
#endif // UTILS_COLOR_H_
|
||||
74
ConveyorBeltControlUnit/include/conveyorBeltControlUnit.h
Normal file
74
ConveyorBeltControlUnit/include/conveyorBeltControlUnit.h
Normal file
@ -0,0 +1,74 @@
|
||||
#include "color.h"
|
||||
#include <glog/logging.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <shared_mutex>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <time.h>
|
||||
extern "C" {
|
||||
#include <modbus/modbus.h>
|
||||
//#include <wiringPi.h> // 树莓派GPIO库
|
||||
// src中202行记得修改
|
||||
}
|
||||
|
||||
class ConveyorBeltControlUnit {
|
||||
private:
|
||||
// 所有的输入端口配置为内部上拉,低有效
|
||||
// 悬空时为高,视为逻辑0
|
||||
// 外部拉低时,视为逻辑1
|
||||
const int IN_LOGIC_0 = 1;
|
||||
const int IN_LOGIC_1 = 0;
|
||||
|
||||
// 输出端口为Push-Pull模式
|
||||
// 逻辑开时输出高电平
|
||||
// 逻辑低时输出低电平
|
||||
const int OUT_ON = 1;
|
||||
const int OUT_OFF = 0;
|
||||
|
||||
const int BTN_DIRSWITCH = 26; // 运行方向切换按钮
|
||||
const int BTN_START = 23; // 启动按钮
|
||||
const int BTN_STOP = 24; // 停止按钮
|
||||
const int BTN_ESTOP = 11; // 急停
|
||||
|
||||
int INPUT_FSENSOR = 28; // 正转边沿传感器
|
||||
int INPUT_RSENSOR = 29; // 反转边沿传感器
|
||||
int OUT_FRUN = 14; // 正向运行输出
|
||||
int OUT_RRUN = 10; // 反向运行输出
|
||||
|
||||
// 定义事件
|
||||
const int EVENT_ESTOP_PUSH = 0; // 急停按下(电平触发)
|
||||
const int EVENT_STOP_PUSH = 1; // 停止按下(电平触发)
|
||||
const int EVENT_FSENSOR_OBSTRUCT = 2; // 正转传感器触发(电平触发)
|
||||
const int EVENT_RSENSOR_OBSTRUCT = 3; // 反转传感器触发(电平触发)
|
||||
const int EVENT_DIRSWITCH_RISING = 4; // 切换运转方向(逻辑上升沿触发)
|
||||
const int EVENT_START_RISING = 5; // 开始运行(逻辑上升沿触发)
|
||||
|
||||
// 定义unit工作状态
|
||||
const int RUNNING = 1;
|
||||
const int STANDBY = 0;
|
||||
|
||||
int current_start_signal;
|
||||
int current_stop_signal;
|
||||
int currentMode;
|
||||
float speed;
|
||||
int workState;
|
||||
std::map<int, std::map<int, int>> modeSwitchMap;
|
||||
void action(int event);
|
||||
std::string modeToString();
|
||||
int getWaitCount();
|
||||
|
||||
public:
|
||||
void conveyorBeltWorkingProcess();
|
||||
int init();
|
||||
int setSpeed(float speed);
|
||||
int setDirection(int direction);
|
||||
int startConveyorBelt();
|
||||
int stopConveyorBelt();
|
||||
int getWorkState();
|
||||
ConveyorBeltControlUnit(/* args */);
|
||||
~ConveyorBeltControlUnit();
|
||||
};
|
||||
223
ConveyorBeltControlUnit/src/conveyorBeltControlUnit.cpp
Normal file
223
ConveyorBeltControlUnit/src/conveyorBeltControlUnit.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
#include "conveyorBeltControlUnit.h"
|
||||
|
||||
// 202行记得修改
|
||||
// x86 无法运行
|
||||
|
||||
// 定义状态
|
||||
const int MODE_INIT = 0; // 初始状态
|
||||
const int MODE_FRUN = 1; // 正转运行状态
|
||||
const int MODE_RRUN = 2; // 反转运行状态
|
||||
const int MODE_CLOSING_STEP1 = 3; // 进入关闭状态步骤1
|
||||
const int MODE_CLOSING_STEP2 = 4; // 进入关闭状态步骤2
|
||||
const int MODE_STOP = 5;
|
||||
int ConveyorBeltControlUnit::getWaitCount() {
|
||||
return 2 * (0.8 / speed) / 0.1;
|
||||
}
|
||||
|
||||
std::string ConveyorBeltControlUnit::modeToString() {
|
||||
switch (currentMode) {
|
||||
case MODE_INIT: return "MODE_INIT";
|
||||
case MODE_FRUN: return "MODE_FRUN";
|
||||
case MODE_RRUN: return "MODE_RRUN";
|
||||
case MODE_CLOSING_STEP1: return "MODE_CLOSING_STEP1";
|
||||
case MODE_CLOSING_STEP2: return "MODE_CLOSING_STEP2";
|
||||
case MODE_STOP: return "MODE_STOP";
|
||||
default: return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
void ConveyorBeltControlUnit::action(int event) {
|
||||
/* int destMode = modeSwitchMap[currentMode][event];
|
||||
if (destMode == currentMode) { return; }
|
||||
|
||||
switch (destMode) {
|
||||
case MODE_INIT:
|
||||
digitalWrite(OUT_FRUN, OUT_OFF);
|
||||
digitalWrite(OUT_RRUN, OUT_OFF);
|
||||
break;
|
||||
case MODE_FRUN:
|
||||
digitalWrite(OUT_FRUN, OUT_ON);
|
||||
digitalWrite(OUT_RRUN, OUT_OFF);
|
||||
break;
|
||||
case MODE_RRUN:
|
||||
digitalWrite(OUT_FRUN, OUT_OFF);
|
||||
digitalWrite(OUT_RRUN, OUT_ON);
|
||||
break;
|
||||
case MODE_CLOSING_STEP1: break;
|
||||
case MODE_CLOSING_STEP2:
|
||||
digitalWrite(OUT_FRUN, OUT_OFF);
|
||||
digitalWrite(OUT_RRUN, OUT_ON);
|
||||
break;
|
||||
case MODE_STOP:
|
||||
digitalWrite(OUT_FRUN, OUT_OFF);
|
||||
digitalWrite(OUT_RRUN, OUT_OFF);
|
||||
workState = STANDBY;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
currentMode = destMode;
|
||||
LOG(INFO) << GREEN << "now mode is " << modeToString() << EMPTY; */
|
||||
}
|
||||
|
||||
void ConveyorBeltControlUnit::conveyorBeltWorkingProcess() {
|
||||
/* workState = RUNNING;
|
||||
int waitCount = 0;
|
||||
int count = 0;
|
||||
while (workState == RUNNING) {
|
||||
waitCount = getWaitCount();
|
||||
if (currentMode == MODE_CLOSING_STEP1 || currentMode == MODE_CLOSING_STEP2) {
|
||||
count--;
|
||||
if (count < 0) { action(EVENT_RSENSOR_OBSTRUCT); }
|
||||
}
|
||||
else { count = waitCount; }
|
||||
|
||||
if (current_start_signal == 1) {
|
||||
LOG(INFO) << YELLOW << "find a start signal" << EMPTY;
|
||||
current_start_signal = 0;
|
||||
action(EVENT_START_RISING);
|
||||
}
|
||||
|
||||
if (digitalRead(INPUT_FSENSOR) == IN_LOGIC_1) {
|
||||
// LOG(INFO) << YELLOW << "find a Fsensor signal" << EMPTY;
|
||||
action(EVENT_FSENSOR_OBSTRUCT);
|
||||
}
|
||||
|
||||
if (digitalRead(INPUT_RSENSOR) == IN_LOGIC_1) {
|
||||
// LOG(INFO) << YELLOW << "find a Rsensor signal" << EMPTY;
|
||||
action(EVENT_RSENSOR_OBSTRUCT);
|
||||
}
|
||||
|
||||
if (current_stop_signal == 1) {
|
||||
LOG(INFO) << YELLOW << "find a stop signal" << EMPTY;
|
||||
LOG(INFO) << YELLOW << "wait count is " << waitCount << " last wait count left "
|
||||
<< count << EMPTY;
|
||||
current_stop_signal = 0;
|
||||
action(EVENT_STOP_PUSH);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
} */
|
||||
}
|
||||
|
||||
int ConveyorBeltControlUnit::init() {
|
||||
current_start_signal = 0;
|
||||
current_stop_signal = 0;
|
||||
currentMode = MODE_INIT;
|
||||
speed = 0;
|
||||
workState = STANDBY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConveyorBeltControlUnit::setSpeed(float speed) {
|
||||
// if (workState == RUNNING)
|
||||
// {
|
||||
// return -1;
|
||||
// }
|
||||
// 原本已经有的注释
|
||||
|
||||
/* int regValue = speed * 62500;
|
||||
modbus_t* ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 2);
|
||||
modbus_set_slave(ctx, 1);
|
||||
if (modbus_connect(ctx) == -1) {
|
||||
fprintf(stderr, "Connection failed:%s\n", modbus_strerror(errno));
|
||||
modbus_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
LOG(INFO) << YELLOW << "set speed:" << speed << " set register:" << regValue << EMPTY;
|
||||
int result = modbus_write_register(ctx, 4096, regValue);
|
||||
if (result == -1) {
|
||||
fprintf(stderr, "write failed:%s\n", modbus_strerror(errno));
|
||||
modbus_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
LOG(INFO) << YELLOW << "get result from com" << ":" << result << EMPTY;
|
||||
uint16_t* speedBuffer = (uint16_t*)malloc(sizeof(uint16_t));
|
||||
int getBytes = modbus_read_registers(ctx, 4096, 2, speedBuffer);
|
||||
LOG(INFO) << YELLOW << "get result from com : " << getBytes << " register:" << *speedBuffer
|
||||
<< EMPTY;
|
||||
this->speed = speed;
|
||||
modbus_free(ctx); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConveyorBeltControlUnit::setDirection(int direction) {
|
||||
if (workState == RUNNING) { return -1; }
|
||||
|
||||
if (direction == 0) {
|
||||
LOG(INFO) << YELLOW << "set direction to foreward" << EMPTY;
|
||||
INPUT_FSENSOR = 28;
|
||||
INPUT_RSENSOR = 29;
|
||||
OUT_FRUN = 14;
|
||||
OUT_RRUN = 10;
|
||||
}
|
||||
else if (direction == 1) {
|
||||
LOG(INFO) << YELLOW << "set direction to reversal" << EMPTY;
|
||||
INPUT_FSENSOR = 29;
|
||||
INPUT_RSENSOR = 28;
|
||||
OUT_FRUN = 10;
|
||||
OUT_RRUN = 14;
|
||||
}
|
||||
else { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConveyorBeltControlUnit::startConveyorBelt() {
|
||||
current_start_signal = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConveyorBeltControlUnit::stopConveyorBelt() {
|
||||
current_stop_signal = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConveyorBeltControlUnit::getWorkState() {
|
||||
if (workState == RUNNING) { return 0; }
|
||||
else { return -1; }
|
||||
}
|
||||
|
||||
ConveyorBeltControlUnit::ConveyorBeltControlUnit(/* args */) {
|
||||
modeSwitchMap[MODE_INIT]
|
||||
= {{EVENT_START_RISING, MODE_FRUN},
|
||||
{EVENT_FSENSOR_OBSTRUCT, MODE_INIT},
|
||||
{EVENT_RSENSOR_OBSTRUCT, MODE_INIT},
|
||||
{EVENT_STOP_PUSH, MODE_INIT}};
|
||||
modeSwitchMap[MODE_FRUN]
|
||||
= {{EVENT_START_RISING, MODE_FRUN},
|
||||
{EVENT_FSENSOR_OBSTRUCT, MODE_RRUN},
|
||||
{EVENT_RSENSOR_OBSTRUCT, MODE_FRUN},
|
||||
{EVENT_STOP_PUSH, MODE_CLOSING_STEP1}};
|
||||
modeSwitchMap[MODE_RRUN]
|
||||
= {{EVENT_START_RISING, MODE_RRUN},
|
||||
{EVENT_FSENSOR_OBSTRUCT, MODE_RRUN},
|
||||
{EVENT_RSENSOR_OBSTRUCT, MODE_FRUN},
|
||||
{EVENT_STOP_PUSH, MODE_CLOSING_STEP2}};
|
||||
modeSwitchMap[MODE_CLOSING_STEP1]
|
||||
= {{EVENT_START_RISING, MODE_CLOSING_STEP1},
|
||||
{EVENT_FSENSOR_OBSTRUCT, MODE_CLOSING_STEP2},
|
||||
{EVENT_RSENSOR_OBSTRUCT, MODE_STOP},
|
||||
{EVENT_STOP_PUSH, MODE_CLOSING_STEP1}};
|
||||
modeSwitchMap[MODE_CLOSING_STEP2]
|
||||
= {{EVENT_START_RISING, MODE_CLOSING_STEP2},
|
||||
{EVENT_FSENSOR_OBSTRUCT, MODE_CLOSING_STEP2},
|
||||
{EVENT_RSENSOR_OBSTRUCT, MODE_STOP},
|
||||
{EVENT_STOP_PUSH, MODE_CLOSING_STEP2}};
|
||||
// x86 无法运行
|
||||
/* wiringPiSetup();
|
||||
pinMode(BTN_START, INPUT);
|
||||
pinMode(BTN_DIRSWITCH, INPUT);
|
||||
pinMode(BTN_STOP, INPUT);
|
||||
pinMode(INPUT_FSENSOR, INPUT);
|
||||
pinMode(INPUT_RSENSOR, INPUT);
|
||||
pullUpDnControl(BTN_START, PUD_UP);
|
||||
pullUpDnControl(BTN_DIRSWITCH, PUD_UP);
|
||||
pullUpDnControl(BTN_STOP, PUD_UP);
|
||||
pullUpDnControl(INPUT_FSENSOR, PUD_UP);
|
||||
pullUpDnControl(INPUT_RSENSOR, PUD_UP);
|
||||
pinMode(OUT_RRUN, OUTPUT);
|
||||
pinMode(OUT_FRUN, OUTPUT);
|
||||
digitalWrite(OUT_FRUN, OUT_OFF);
|
||||
digitalWrite(OUT_RRUN, OUT_OFF); */
|
||||
|
||||
}
|
||||
|
||||
ConveyorBeltControlUnit::~ConveyorBeltControlUnit() {}
|
||||
84
ConveyorBeltController/include/conveyorBeltController.hpp
Normal file
84
ConveyorBeltController/include/conveyorBeltController.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
#ifndef BELT_CONTROLLER_H_
|
||||
#define BELT_CONTROLLER_H_
|
||||
#include "color.h"
|
||||
#include "conveyorBeltGrpcClient.hpp"
|
||||
#include <cstdlib>
|
||||
#include <glog/logging.h>
|
||||
#include <httplib.h>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <shared_mutex>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "ability_sdk/ControllerHeartbeat.hpp"
|
||||
#include "ability_sdk/Heartbeat.hpp"
|
||||
|
||||
//#include <json/json.h>
|
||||
|
||||
//#include "http_server.h"
|
||||
// 前向声明 HttpServer 类,避免循环依赖
|
||||
//class HttpServer;
|
||||
|
||||
|
||||
typedef int ConveyorBeltStatus;
|
||||
|
||||
|
||||
// 控制器类
|
||||
class ConveyorBeltController {
|
||||
|
||||
public:
|
||||
|
||||
httplib::Server http_server;
|
||||
void configure_http_server();
|
||||
std::map<int, int> directionMap;
|
||||
//std::map<int, std::string> ipMap;
|
||||
int port;
|
||||
|
||||
// 控制器心跳包
|
||||
ability_sdk::ControllerHeartbeat heartbeat_pack;
|
||||
|
||||
// 能力心跳获取
|
||||
std::map<uuids::uuid, ability_sdk::Heartbeat> ability_heartbeats;
|
||||
bool gather_abilities();
|
||||
bool check_ability_status();
|
||||
|
||||
void init();
|
||||
void Run();
|
||||
|
||||
// 控制器心跳线程
|
||||
std::thread th_heartbeat;
|
||||
void routine_heartbeat();
|
||||
|
||||
int handleOpen(float speed, int direction);
|
||||
int handleClose();
|
||||
int handleCheck();
|
||||
void setServerIp(std::string serverIp);
|
||||
ConveyorBeltStatus getCurrentStatus();
|
||||
ConveyorBeltController();
|
||||
~ConveyorBeltController();
|
||||
|
||||
private:
|
||||
std::string ip;
|
||||
ConveyorBeltStatus status;
|
||||
std::shared_mutex mutex_;
|
||||
int IPCPort;
|
||||
int abilityPort;
|
||||
std::map<int, std::string> ipMap;
|
||||
// 状态转换
|
||||
int stateSwitch(ConveyorBeltStatus destState, std::string cmd);
|
||||
// grpc连接
|
||||
int grpcConnect(float speed, int direction);
|
||||
// grpc断开
|
||||
int grpcDisconnect();
|
||||
// grpc检查
|
||||
int grpcCheck();
|
||||
// 同步状态
|
||||
int synchState(std::string json);
|
||||
// 简单状态检查
|
||||
bool simpleStateCheck();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
85
ConveyorBeltController/include/conveyorBeltGrpcClient.hpp
Normal file
85
ConveyorBeltController/include/conveyorBeltGrpcClient.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef CONVEYOR_BELT_GRPC_CLIENT_H_
|
||||
#define CONVEYOR_BELT_GRPC_CLIENT_H_
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "conveyorBelt.grpc.pb.h"
|
||||
#include "conveyorBelt.pb.h"
|
||||
#include "conveyorBeltControlUnit.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpcpp/channel.h>
|
||||
#include <grpcpp/client_context.h>
|
||||
#include <grpcpp/create_channel.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/security/credentials.h>
|
||||
|
||||
using grpc::Channel;
|
||||
using grpc::ClientContext;
|
||||
using grpc::ClientReader;
|
||||
using grpc::ClientWriter;
|
||||
using grpc::Status;
|
||||
|
||||
class ConveyorBeltGrpcClient {
|
||||
private:
|
||||
std::unique_ptr<ConveyorBelt::ConveyorBeltService::Stub> stub_;
|
||||
|
||||
public:
|
||||
// 启动带速度和方向的传送带
|
||||
int startWithSpeedAndDirection(float speed, int direction) {
|
||||
LOG(INFO) << GRAY << "start connect to belt" << EMPTY;
|
||||
ConveyorBelt::SpeedInfo speedInfo;
|
||||
speedInfo.set_speed(speed);
|
||||
ConveyorBelt::DirectionInfo directionInfo;
|
||||
directionInfo.set_direction(direction);
|
||||
ConveyorBelt::Response response;
|
||||
ClientContext context_direction;
|
||||
grpc::Status ret = stub_->setDirection(&context_direction, directionInfo, &response);
|
||||
if (!ret.ok()) {
|
||||
LOG(INFO) << GRAY << "grpc server cannot connect" << EMPTY;
|
||||
return -2;
|
||||
}
|
||||
if (response.code() < 0) { return -1; }
|
||||
ClientContext context_start;
|
||||
stub_->open(&context_start, speedInfo, &response);
|
||||
if (response.code() < 0) { return -1; }
|
||||
LOG(INFO) << GRAY << "finish connect to belt" << EMPTY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 关闭传送带
|
||||
int close() {
|
||||
LOG(INFO) << GRAY << "start connect to belt" << EMPTY;
|
||||
ConveyorBelt::DeviceID id;
|
||||
id.set_conveyorbeltid(0);
|
||||
ClientContext context_close;
|
||||
ConveyorBelt::Response response;
|
||||
stub_->close(&context_close, id, &response);
|
||||
if (response.code() < 0) { return -1; }
|
||||
LOG(INFO) << GRAY << "start connect to belt" << EMPTY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取传送带状态
|
||||
int getWorkState() {
|
||||
LOG(INFO) << GRAY << "start connect to belt" << EMPTY;
|
||||
ConveyorBelt::DeviceID id;
|
||||
id.set_conveyorbeltid(0);
|
||||
ClientContext context_get;
|
||||
ConveyorBelt::Response response;
|
||||
stub_->getWorkState(&context_get, id, &response);
|
||||
LOG(INFO) << GRAY << "start connect to belt" << EMPTY;
|
||||
return response.code();
|
||||
}
|
||||
|
||||
ConveyorBeltGrpcClient(std::shared_ptr<Channel> channel)
|
||||
: stub_(ConveyorBelt::ConveyorBeltService::NewStub(channel)) {}
|
||||
|
||||
~ConveyorBeltGrpcClient() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
36
ConveyorBeltController/include/http_server.h.txt
Normal file
36
ConveyorBeltController/include/http_server.h.txt
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef HTTP_SERVER_H_
|
||||
#define HTTP_SERVER_H_
|
||||
|
||||
#include <httplib.h>
|
||||
#include "color.h"
|
||||
#include "conveyorBeltController.hpp"
|
||||
#include <glog/logging.h>
|
||||
#include <json/json.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
class HttpServer {
|
||||
public:
|
||||
|
||||
// 构造函数,接收 ConveyorBeltController 的引用
|
||||
explicit HttpServer(ConveyorBeltController& controller);
|
||||
|
||||
void Init();
|
||||
void Run();
|
||||
|
||||
private:
|
||||
// http服务器
|
||||
std::shared_ptr<httplib::Server> server;
|
||||
|
||||
// 控制器
|
||||
//std::shared_ptr<ConveyorBeltController> controller;
|
||||
|
||||
std::map<int, int> directionMap;
|
||||
std::map<int, std::string> ipMap;
|
||||
|
||||
// 引用 ConveyorBeltController 实例
|
||||
ConveyorBeltController& controller;
|
||||
};
|
||||
|
||||
#endif // HTTP_SERVER_H_
|
||||
549
ConveyorBeltController/src/conveyorBeltController.cpp
Normal file
549
ConveyorBeltController/src/conveyorBeltController.cpp
Normal file
@ -0,0 +1,549 @@
|
||||
#include "conveyorBeltController.hpp"
|
||||
|
||||
|
||||
const ConveyorBeltStatus OFFLINE = 0;
|
||||
const ConveyorBeltStatus READY = 1;
|
||||
const ConveyorBeltStatus RUNNING = 2;
|
||||
|
||||
ConveyorBeltController::ConveyorBeltController(/* args */) {}
|
||||
ConveyorBeltController::~ConveyorBeltController() {
|
||||
if (th_heartbeat.joinable()) {
|
||||
th_heartbeat.join(); // 等待线程结束
|
||||
}
|
||||
}
|
||||
|
||||
// 配置http服务器
|
||||
void ConveyorBeltController::configure_http_server(){
|
||||
FLAGS_logtostderr = 1;
|
||||
LOG(INFO) << L_GREEN << "init http server" << EMPTY;
|
||||
|
||||
ipMap[108] = "192.168.1.217";
|
||||
ipMap[109] = "192.168.1.218";
|
||||
directionMap[108] = 0;
|
||||
directionMap[109] = 0;
|
||||
|
||||
// GET 请求 /api/processGet 处理函数,通过id参数获取状态
|
||||
http_server.Get(
|
||||
"/api/processGet",
|
||||
[this](const httplib::Request& req, httplib::Response& res) {
|
||||
LOG(INFO) << L_BLUE << "httpserver receive: method: GET URL: /api/processGet"
|
||||
<< EMPTY;
|
||||
std::string conveyorBeltId;
|
||||
int result = 200;
|
||||
//Json::Value response;
|
||||
nlohmann::json response;
|
||||
try {
|
||||
conveyorBeltId = req.get_param_value("id");
|
||||
LOG(INFO) << YELLOW << "GET param id:" << conveyorBeltId << EMPTY;
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
res.status = 400; // Bad Request
|
||||
response["status"] = 400;
|
||||
response["processStatus"] = this->getCurrentStatus();
|
||||
res.set_content(response.dump(4), "application/json");
|
||||
return;
|
||||
}
|
||||
std::map<int, std::string>::iterator it = ipMap.find(std::stoi(conveyorBeltId));
|
||||
if (it != ipMap.end()) { this->setServerIp(it->second); }
|
||||
else {
|
||||
response["status"] = 400;
|
||||
response["processStatus"] = this->getCurrentStatus();
|
||||
res.set_content(response.dump(4), "application/json");
|
||||
return;
|
||||
}
|
||||
if (this->handleCheck() < 0) { result = 400; }
|
||||
|
||||
// status = 200
|
||||
response["status"] = result;
|
||||
response["processStatus"] = this->getCurrentStatus();
|
||||
res.set_content(response.dump(4), "application/json");
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// POST 请求 /api/processPost 处理函数
|
||||
http_server.Post(
|
||||
"/api/processPost",
|
||||
[this](const httplib::Request& req, httplib::Response& res) {
|
||||
LOG(INFO) << L_BLUE << "httpserver receive: method: POST URL: /api/processPost"
|
||||
<< EMPTY;
|
||||
LOG(INFO) << YELLOW << req.get_header_value("Content-Type") << EMPTY;
|
||||
//Json::Value root;
|
||||
nlohmann::json root;
|
||||
int status = 200;
|
||||
if (req.get_header_value("Content-Type").find("application/json")!= std::string::npos) {
|
||||
//Json::Reader reader;
|
||||
/* nlohmann::json reader;
|
||||
bool success = reader.parse(req.body, root);
|
||||
if (!success) {
|
||||
LOG(ERROR) << "json parse error";
|
||||
res.status = 400;
|
||||
status = 400;
|
||||
} */
|
||||
|
||||
try {
|
||||
root = nlohmann::json::parse(req.body); // 使用静态方法解析 JSON
|
||||
} catch (const nlohmann::json::parse_error& e) {
|
||||
// json解析错误
|
||||
LOG(ERROR) << "json parse error: " << e.what();
|
||||
res.status = 400;
|
||||
status = 400;
|
||||
return;
|
||||
}
|
||||
|
||||
// 以下缩进需要调整
|
||||
//else {
|
||||
LOG(INFO) << YELLOW << "id:" << root["id"].get<int>()
|
||||
<< " action:" << root["action"].get<int>()
|
||||
<< " speed:" << root["speed"].get<int>() << EMPTY;
|
||||
//Json::Value result;
|
||||
nlohmann::json result;
|
||||
std::map<int, std::string>::iterator it = ipMap.find(root["id"].get<int>());
|
||||
|
||||
// 根据传送带id,检查该id是否存在于ipMap中
|
||||
// it->first 为传送带id
|
||||
// it->second 为传送带对应的ip地址
|
||||
if (it != ipMap.end()) { this->setServerIp(it->second); }
|
||||
else {
|
||||
result["status"] = 400;
|
||||
result["processStatus"] = this->getCurrentStatus();
|
||||
res.set_content(result.dump(4), "application/json");
|
||||
return;
|
||||
}
|
||||
// 启动
|
||||
if (root["action"].get<int>() == 1) {
|
||||
LOG(INFO) << YELLOW << "http server try to handle open" << EMPTY;
|
||||
std::thread openThread(
|
||||
&ConveyorBeltController::handleOpen,
|
||||
this,
|
||||
root["speed"].get<int>(),
|
||||
directionMap[root["id"].get<int>()]
|
||||
);
|
||||
openThread.detach();
|
||||
}
|
||||
|
||||
// 关闭
|
||||
else if (root["action"].get<int>() == 0) {
|
||||
LOG(INFO) << YELLOW << "http server try to handle close" << EMPTY;
|
||||
std::thread closeThread(
|
||||
&ConveyorBeltController::handleClose, this
|
||||
);
|
||||
closeThread.detach();
|
||||
}
|
||||
else {
|
||||
LOG(INFO) << YELLOW << "invalid action code" << EMPTY;
|
||||
status = 400;
|
||||
}
|
||||
// }
|
||||
}
|
||||
else { status = 400; }
|
||||
//Json::Value result;
|
||||
nlohmann::json result;
|
||||
result["status"] = status;
|
||||
result["processStatus"] = this->getCurrentStatus();
|
||||
res.set_content(result.dump(4), "application/json");
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 设置服务器ip
|
||||
void ConveyorBeltController::setServerIp(std::string conveyorBeltIp) {
|
||||
this->ip = conveyorBeltIp;
|
||||
}
|
||||
|
||||
// 初始化
|
||||
void ConveyorBeltController::init() {
|
||||
|
||||
std::unique_lock<std::shared_mutex> w_lock(mutex_);
|
||||
LOG(INFO) << WHITE << "init controller state" << EMPTY;
|
||||
status = OFFLINE;
|
||||
abilityPort = 0;
|
||||
IPCPort = 0;
|
||||
//configure_http_server();
|
||||
}
|
||||
|
||||
namespace {
|
||||
void send_one_heartbeat(const ability_sdk::ControllerHeartbeat& heartbeat_pack) {
|
||||
try {
|
||||
httplib::Client cli("127.0.0.1", 8080); // 连接到框架
|
||||
// 生成 JSON 格式的心跳包
|
||||
nlohmann::json hb_json;
|
||||
try {
|
||||
hb_json = nlohmann::json(heartbeat_pack);
|
||||
//LOG(INFO) << "heartbeat_pack to json success";
|
||||
} catch (const nlohmann::json::exception& e) {
|
||||
LOG(ERROR) << "JSON serialization error: " << e.what();
|
||||
return;
|
||||
}
|
||||
|
||||
auto post_res = cli.Post("/api/controller-heartbeat", hb_json.dump(2), "application/json");
|
||||
if (!post_res) {
|
||||
LOG(ERROR) << "failed to connect to framework: " << post_res.error();
|
||||
} else if (post_res->status != 200) {
|
||||
LOG(ERROR) << "failed to connect to framework: " << post_res->body;
|
||||
}
|
||||
LOG(INFO) << "send one heartbeat success";
|
||||
} catch (const std::exception& e) {
|
||||
LOG(ERROR) << "Exception in send_one_heartbeat: " << e.what();
|
||||
} catch (...) {
|
||||
LOG(ERROR) << "Unknown exception in send_one_heartbeat";
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
// 心跳包
|
||||
void ConveyorBeltController::routine_heartbeat() {
|
||||
LOG(INFO) << "start heart beat routine";
|
||||
while (true) {
|
||||
try {
|
||||
send_one_heartbeat(heartbeat_pack);
|
||||
//gather_abilities();
|
||||
//check_ability_status();
|
||||
}catch (const std::exception& e) {
|
||||
LOG(ERROR) << "Exception in routine_heartbeat: " << e.what();
|
||||
} catch (...) {
|
||||
LOG(ERROR) << "Unknown exception in routine_heartbeat";
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||
}
|
||||
}
|
||||
|
||||
void ConveyorBeltController::Run() {
|
||||
|
||||
//http_server.Init();
|
||||
//http_server.Run();
|
||||
LOG(INFO) << "ConveyorBeltController::Run()";
|
||||
|
||||
configure_http_server();
|
||||
port = http_server.bind_to_any_port("0.0.0.0");
|
||||
CHECK_GE(port, 0) << "http server bind port failed";
|
||||
LOG(WARNING) << "http server listen on: " << port;
|
||||
// 设置心跳包中的端口
|
||||
this->heartbeat_pack.port = port;
|
||||
|
||||
// 启动心跳包线程
|
||||
this->th_heartbeat = std::thread(&ConveyorBeltController::routine_heartbeat, this);
|
||||
// 启动http服务器
|
||||
http_server.listen_after_bind();
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool ConveyorBeltController::gather_abilities() {
|
||||
httplib::Client cli{"localhost", 8080};
|
||||
auto get_res = cli.Get("/api/ability-heartbeat");
|
||||
if (!get_res) {
|
||||
LOG(ERROR) << "failed to update ability info: failed to connect to framework";
|
||||
return false;
|
||||
}
|
||||
if (get_res.value().status != 200) {
|
||||
LOG(ERROR) << "failed to gather ability information: " << get_res.value().body;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto json_arr_res = nlohmann::json::parse(get_res->body);
|
||||
DLOG(INFO) << "get ablility info:" << json_arr_res;
|
||||
if (json_arr_res.is_null() || (!json_arr_res.is_array())) {
|
||||
DLOG(INFO) << "ability info is null, return";
|
||||
return false;
|
||||
}
|
||||
std::lock_guard _lk(m);
|
||||
DLOG(INFO) << "iterating ablility info: " << json_arr_res.dump();
|
||||
for (int i = 0; i < json_arr_res.size(); ++i) {
|
||||
auto sub_json = json_arr_res.at(i);
|
||||
if (!sub_json.is_object()) { continue; }
|
||||
try {
|
||||
auto entry = sub_json.get<ability_sdk::Heartbeat>();
|
||||
if (entry.abilityName != ABILITY_NAME) { continue; }
|
||||
DLOG(INFO) << "update ablility " << entry.id << " with "
|
||||
<< nlohmann::json(entry).dump();
|
||||
ability_heartbeats[entry.id] = entry;
|
||||
}
|
||||
catch (nlohmann::json::exception& e) {
|
||||
LOG(ERROR) << "invalid heartbeat info: " << e.what() << "\n" << sub_json.dump(2);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ConveyorBeltController::handleCheck() {
|
||||
std::unique_lock<std::shared_mutex> w_lock(mutex_);
|
||||
if (simpleStateCheck()) { return 0; }
|
||||
else { return -1; }
|
||||
}
|
||||
// 获取当前状态,并且根据gRPC检查状态
|
||||
int ConveyorBeltController::getCurrentStatus() {
|
||||
std::shared_lock<std::shared_mutex> r_lock(mutex_);
|
||||
if (status == RUNNING) {
|
||||
if (grpcCheck() < 0) { return READY; }
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int ConveyorBeltController::handleOpen(float speed, int direction) {
|
||||
std::unique_lock<std::shared_mutex> w_lock(mutex_);
|
||||
int result = 0;
|
||||
if (simpleStateCheck() == false) { return -1; }
|
||||
switch (status) {
|
||||
case RUNNING:
|
||||
if (grpcCheck() < 0) {
|
||||
result = grpcConnect(speed, direction);
|
||||
break;
|
||||
}
|
||||
LOG(INFO) << WHITE << "ConveyorBelt is already running, do not open twice" << EMPTY;
|
||||
break;
|
||||
case READY:
|
||||
LOG(INFO) << WHITE << "ConveyorBelt is ready, start handle open request" << EMPTY;
|
||||
result = stateSwitch(RUNNING, "connect");
|
||||
if (result < 0) { break; }
|
||||
result = grpcConnect(speed, direction);
|
||||
break;
|
||||
case OFFLINE:
|
||||
LOG(INFO) << WHITE << "ConveyorBelt is offline, start handle open request" << EMPTY;
|
||||
result = stateSwitch(READY, "start");
|
||||
if (result < 0) { break; }
|
||||
result = stateSwitch(RUNNING, "connect");
|
||||
if (result < 0) { break; }
|
||||
result = grpcConnect(speed, direction);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConveyorBeltController::handleClose() {
|
||||
std::unique_lock<std::shared_mutex> w_lock(mutex_);
|
||||
int result = 0;
|
||||
if (simpleStateCheck() == false) { return -1; }
|
||||
switch (status) {
|
||||
case READY:
|
||||
case OFFLINE:
|
||||
LOG(INFO) << WHITE << "ConveyorBelt has not been opened, do not close twice" << EMPTY;
|
||||
break;
|
||||
case RUNNING:
|
||||
LOG(INFO) << WHITE << "ConveyorBelt is now running, start handle ConveyorBelt close"
|
||||
<< EMPTY;
|
||||
result = grpcDisconnect();
|
||||
if (result < 0) { break; }
|
||||
result = stateSwitch(READY, "disconnect");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ConveyorBeltController::simpleStateCheck() {
|
||||
LOG(INFO) << WHITE << "start simple check" << EMPTY;
|
||||
httplib::Client client(ip, 8080);
|
||||
int mStatus;
|
||||
auto res = client.Get("/api/AbilityRunning");
|
||||
if (res) {
|
||||
LOG(INFO) << WHITE << "GET response:" << res->status << EMPTY;
|
||||
mStatus = synchState(res->body);
|
||||
if (mStatus == status) {
|
||||
LOG(INFO) << WHITE
|
||||
<< "simple check pass current status is correct with abilityFrameWork"
|
||||
<< EMPTY;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LOG(INFO) << WHITE << "simple check failed incorrect state" << EMPTY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "FIRST STEP: can not connect with abilityFrameWork" << EMPTY;
|
||||
LOG(INFO) << WHITE << "now ConveyorBelt is OFFLINE" << EMPTY;
|
||||
status = OFFLINE;
|
||||
abilityPort = 0;
|
||||
IPCPort = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ConveyorBeltController::synchState(std::string json) {
|
||||
nlohmann::json states;
|
||||
try {
|
||||
states = nlohmann::json::parse(json); // 使用 nlohmann::json 解析 JSON 字符串
|
||||
for (const auto& state : states) { // 遍历 JSON 数组
|
||||
LOG(INFO) << WHITE << "IPCPort:" << state["IPCPort"].get<std::string>()
|
||||
<< " abilityName:" << state["abilityName"].get<std::string>()
|
||||
<< " status:" << state["status"].get<std::string>() << EMPTY;
|
||||
|
||||
if (state["IPCPort"].get<int>() == IPCPort ||
|
||||
(IPCPort == 0 && state["abilityName"].get<std::string>() == "conveyorBelt")) {
|
||||
if (state["status"].get<std::string>() == "RUNNING") {
|
||||
LOG(INFO) << WHITE << "now ConveyorBelt is RUNNING" << EMPTY;
|
||||
status = RUNNING;
|
||||
IPCPort = state["IPCPort"].get<int>();
|
||||
abilityPort = state["abilityPort"].get<int>();
|
||||
if (abilityPort == 0) {
|
||||
return READY;
|
||||
} else {
|
||||
return RUNNING;
|
||||
}
|
||||
} else if (state["status"].get<std::string>() == "STANDBY" ||
|
||||
state["status"].get<std::string>() == "SUSPEND") {
|
||||
LOG(INFO) << WHITE << "now ConveyorBelt is READY" << EMPTY;
|
||||
status = READY;
|
||||
IPCPort = state["IPCPort"].get<int>();
|
||||
abilityPort = 0;
|
||||
return READY;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const nlohmann::json::parse_error& e) {
|
||||
LOG(ERROR) << "JSON parse error: " << e.what();
|
||||
// 如果解析失败,返回 OFFLINE 状态
|
||||
status = OFFLINE;
|
||||
abilityPort = 0;
|
||||
IPCPort = 0;
|
||||
return OFFLINE;
|
||||
}
|
||||
|
||||
// 如果没有匹配的状态,设置为 OFFLINE
|
||||
LOG(INFO) << WHITE << "now ConveyorBelt is OFFLINE" << EMPTY;
|
||||
status = OFFLINE;
|
||||
abilityPort = 0;
|
||||
IPCPort = 0;
|
||||
return OFFLINE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* int ConveyorBeltController::synchState(std::string json) {
|
||||
Json::Reader reader;
|
||||
Json::Value states;
|
||||
if (reader.parse(json, states)) {
|
||||
for (int i = 0; i < states.size(); i++) {
|
||||
LOG(INFO) << WHITE << "IPCPort:" << states[i]["IPCPort"].asString()
|
||||
<< " abilityName:" << states[i]["abilityName"].asString() << "status"
|
||||
<< states[i]["status"].asString() << EMPTY;
|
||||
if (states[i]["IPCPort"].asInt() == IPCPort
|
||||
|| (IPCPort == 0 && states[i]["abilityName"].asString().compare("conveyorBelt") == 0
|
||||
)) {
|
||||
if (states[i]["status"].asString() == "RUNNING") {
|
||||
// std::unique_lock<std::shared_mutex> w_lock(mutex_);
|
||||
LOG(INFO) << WHITE << "now ConveyorBelt is RUNNING" << EMPTY;
|
||||
status = RUNNING;
|
||||
IPCPort = states[i]["IPCPort"].asInt();
|
||||
abilityPort = states[i]["abilityPort"].asInt();
|
||||
if (abilityPort == 0) { return READY; }
|
||||
else { return RUNNING; }
|
||||
}
|
||||
else if (states[i]["status"].asString() == "STANDBY"
|
||||
|| states[i]["status"].asString() == "SUSPEND") {
|
||||
// std::unique_lock<std::shared_mutex> w_lock(mutex_);
|
||||
LOG(INFO) << WHITE << "now ConveyorBelt is READY" << EMPTY;
|
||||
status = READY;
|
||||
IPCPort = states[i]["IPCPort"].asInt();
|
||||
abilityPort = 0;
|
||||
// w_lock.unlock();
|
||||
return READY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// std::unique_lock<std::shared_mutex> w_lock(mutex_);
|
||||
LOG(INFO) << WHITE << "now ConveyorBelt is OFFLINE" << EMPTY;
|
||||
status = OFFLINE;
|
||||
abilityPort = 0;
|
||||
IPCPort = 0;
|
||||
// w_lock.unlock();
|
||||
return OFFLINE;
|
||||
} */
|
||||
|
||||
|
||||
int ConveyorBeltController::stateSwitch(ConveyorBeltStatus destState, std::string cmd) {
|
||||
httplib::Client client(ip, 8080);
|
||||
httplib::Params params;
|
||||
ConveyorBeltStatus mStatus;
|
||||
// 发出请求
|
||||
params.emplace("abilityName", "conveyorBelt");
|
||||
params.emplace("IPCPort", std::to_string(IPCPort));
|
||||
params.emplace("cmd", cmd);
|
||||
params.emplace("connectIP", "0.0.0.0");
|
||||
params.emplace("connectPort", "0");
|
||||
auto res = client.Post("/api/AbilityRequest", params);
|
||||
if (res) { LOG(INFO) << WHITE << "POST response:" << res->status << EMPTY; }
|
||||
else {
|
||||
LOG(ERROR) << "SECOND STEP: can not connect with abilityFrameWork" << EMPTY;
|
||||
return -1;
|
||||
}
|
||||
params.clear();
|
||||
// 查询当前状态
|
||||
for (int i = 0; i < 10; i++) {
|
||||
res = client.Get("/api/AbilityRunning");
|
||||
if (res) {
|
||||
LOG(INFO) << WHITE << "GET response:" << res->status << EMPTY;
|
||||
mStatus = synchState(res->body);
|
||||
if (mStatus == destState) {
|
||||
LOG(INFO) << WHITE << "switch state success" << EMPTY;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "THIRD STEP: can not connect with abilityFrameWork" << EMPTY;
|
||||
return -1;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
LOG(ERROR) << "ability state change failed" << EMPTY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ConveyorBeltController::grpcConnect(float speed, int direction) {
|
||||
if (abilityPort == 0) { return -1; }
|
||||
|
||||
std::string url;
|
||||
url.append(ip);
|
||||
url.append(":");
|
||||
url.append(std::to_string(abilityPort));
|
||||
LOG(INFO) << WHITE << url << EMPTY;
|
||||
int result;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ConveyorBeltGrpcClient client(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
|
||||
result = client.startWithSpeedAndDirection(speed, direction);
|
||||
if (result != -2) { break; }
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConveyorBeltController::grpcDisconnect() {
|
||||
if (abilityPort == 0) { return -1; }
|
||||
std::string url;
|
||||
url.append(ip);
|
||||
url.append(":");
|
||||
url.append(std::to_string(abilityPort));
|
||||
LOG(INFO) << WHITE << url << EMPTY;
|
||||
ConveyorBeltGrpcClient client(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
|
||||
if (client.close() == -1) {
|
||||
LOG(ERROR) << "grpc call failed" << EMPTY;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConveyorBeltController::grpcCheck() {
|
||||
if (abilityPort == 0) { return -1; }
|
||||
std::string url;
|
||||
url.append(ip);
|
||||
url.append(":");
|
||||
url.append(std::to_string(abilityPort));
|
||||
LOG(INFO) << WHITE << url << EMPTY;
|
||||
ConveyorBeltGrpcClient client(grpc::CreateChannel(url, grpc::InsecureChannelCredentials()));
|
||||
if (client.getWorkState() == -1) {
|
||||
LOG(ERROR) << "grpc work state is false" << EMPTY;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
123
ConveyorBeltController/src/http_server.cpp.txt
Normal file
123
ConveyorBeltController/src/http_server.cpp.txt
Normal file
@ -0,0 +1,123 @@
|
||||
#include "http_server.h"
|
||||
|
||||
HttpServer::HttpServer(ConveyorBeltController& controller)
|
||||
: controller(controller) {} // 初始化引用
|
||||
|
||||
|
||||
|
||||
void HttpServer::Init() {
|
||||
FLAGS_logtostderr = 1;
|
||||
LOG(INFO) << L_GREEN << "init http server" << EMPTY;
|
||||
// 初始化 http 服务器
|
||||
this->server = std::make_shared<httplib::Server>();
|
||||
|
||||
// 初始化控制器
|
||||
//this->controller = std::make_shared<ConveyorBeltController>();
|
||||
// 初始化控制器
|
||||
//this->controller->init();
|
||||
|
||||
ipMap[108] = "192.168.1.217";
|
||||
ipMap[109] = "192.168.1.218";
|
||||
directionMap[108] = 0;
|
||||
directionMap[109] = 0;
|
||||
|
||||
this->server->Get(
|
||||
"/api/processGet",
|
||||
[this](const httplib::Request& req, httplib::Response& res) {
|
||||
LOG(INFO) << L_BLUE << "httpserver receive: method: GET URL: /api/processGet"
|
||||
<< EMPTY;
|
||||
std::string conveyorBeltId;
|
||||
int result = 200;
|
||||
Json::Value response;
|
||||
try {
|
||||
conveyorBeltId = req.get_param_value("id");
|
||||
LOG(INFO) << YELLOW << "GET param id:" << conveyorBeltId << EMPTY;
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
res.status = 400; // Bad Request
|
||||
response["status"] = 400;
|
||||
response["processStatus"] = this->controller.getCurrentStatus();
|
||||
res.set_content(response.toStyledString(), "application/json");
|
||||
return;
|
||||
}
|
||||
std::map<int, std::string>::iterator it = ipMap.find(std::stoi(conveyorBeltId));
|
||||
if (it != ipMap.end()) { this->controller.setServerIp(it->second); }
|
||||
else {
|
||||
response["status"] = 400;
|
||||
response["processStatus"] = this->controller.getCurrentStatus();
|
||||
res.set_content(response.toStyledString(), "application/json");
|
||||
return;
|
||||
}
|
||||
if (this->controller.handleCheck() < 0) { result = 400; }
|
||||
response["status"] = result;
|
||||
response["processStatus"] = this->controller.getCurrentStatus();
|
||||
res.set_content(response.toStyledString(), "application/json");
|
||||
}
|
||||
);
|
||||
|
||||
this->server->Post(
|
||||
"/api/processPost",
|
||||
[this](const httplib::Request& req, httplib::Response& res) {
|
||||
LOG(INFO) << L_BLUE << "httpserver receive: method: POST URL: /api/processPost"
|
||||
<< EMPTY;
|
||||
LOG(INFO) << YELLOW << req.get_header_value("Content-Type") << EMPTY;
|
||||
Json::Value root;
|
||||
int status = 200;
|
||||
if (req.get_header_value("Content-Type").find("application/json")
|
||||
!= std::string::npos) {
|
||||
Json::Reader reader;
|
||||
bool success = reader.parse(req.body, root);
|
||||
if (!success) {
|
||||
LOG(ERROR) << "json parse error";
|
||||
res.status = 400;
|
||||
status = 400;
|
||||
}
|
||||
else {
|
||||
LOG(INFO) << YELLOW << "id:" << root["id"].asInt()
|
||||
<< " action:" << root["action"].asInt()
|
||||
<< " speed:" << root["speed"].asFloat() << EMPTY;
|
||||
Json::Value result;
|
||||
std::map<int, std::string>::iterator it = ipMap.find(root["id"].asInt());
|
||||
if (it != ipMap.end()) { this->controller.setServerIp(it->second); }
|
||||
else {
|
||||
result["status"] = 400;
|
||||
result["processStatus"] = this->controller.getCurrentStatus();
|
||||
res.set_content(result.toStyledString(), "application/json");
|
||||
return;
|
||||
}
|
||||
if (root["action"].asInt() == 1) {
|
||||
LOG(INFO) << YELLOW << "http server try to handle open" << EMPTY;
|
||||
std::thread openThread(
|
||||
&ConveyorBeltController::handleOpen,
|
||||
this->controller,
|
||||
root["speed"].asFloat(),
|
||||
directionMap[root["id"].asInt()]
|
||||
);
|
||||
openThread.detach();
|
||||
}
|
||||
else if (root["action"].asInt() == 0) {
|
||||
LOG(INFO) << YELLOW << "http server try to handle close" << EMPTY;
|
||||
std::thread closeThread(
|
||||
&ConveyorBeltController::handleClose, this->controller
|
||||
);
|
||||
closeThread.detach();
|
||||
}
|
||||
else {
|
||||
LOG(INFO) << YELLOW << "invalid action code" << EMPTY;
|
||||
status = 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { status = 400; }
|
||||
Json::Value result;
|
||||
result["status"] = status;
|
||||
result["processStatus"] = this->controller.getCurrentStatus();
|
||||
res.set_content(result.toStyledString(), "application/json");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void HttpServer::Run() {
|
||||
LOG(INFO) << L_GREEN << "http server start" << EMPTY;
|
||||
this->server->listen("0.0.0.0", 8001);
|
||||
}
|
||||
48
ConveyorBeltController/src/main.cpp
Normal file
48
ConveyorBeltController/src/main.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "conveyorBeltController.hpp"
|
||||
#include "ability_sdk/AbilityStub.hpp"
|
||||
#include "ability_sdk/util/parse_cmd.hpp"
|
||||
|
||||
|
||||
int main(int argc, char const* argv[]) {
|
||||
// 初始化glog
|
||||
ability_sdk::configure_glog(argv[0]);
|
||||
|
||||
ability_sdk::CmdInfo cmd(argc, argv);
|
||||
ConveyorBeltController controller;
|
||||
|
||||
// 配置心跳包
|
||||
controller.heartbeat_pack.controllerInstanceId = uuids::to_string(cmd.instance_id);
|
||||
controller.heartbeat_pack.abilityName = "ConveyorBelt";
|
||||
controller.heartbeat_pack.package = "ConveyorBelt.test.org";
|
||||
controller.heartbeat_pack.protocol = "http";
|
||||
controller.heartbeat_pack.version = "0.1.0";
|
||||
|
||||
controller.Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* struct ControllerHeartbeat {
|
||||
int port; // 控制器基础服务器对应的端口
|
||||
std::string controllerInstanceId; // 控制器的实例id 能力的类id
|
||||
std::string package; // 控制器所对应能力的包名称
|
||||
std::string version; // 控制器所对应能力的版本名
|
||||
std::string abilityName; // 控制器所对应能力的类型名
|
||||
std::string protocol; // 控制器所使用的协议
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(
|
||||
ControllerHeartbeat, port, controllerInstanceId, package, version, abilityName, protocol
|
||||
);
|
||||
}; */
|
||||
|
||||
|
||||
/* #include "http_server.h"
|
||||
|
||||
// 控制器在http服务器中启动
|
||||
int main(int argc, char* argv[]) {
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
HttpServer server;
|
||||
server.Init();
|
||||
server.Run();
|
||||
} */
|
||||
|
||||
|
||||
32
package-index.lua
Normal file
32
package-index.lua
Normal file
@ -0,0 +1,32 @@
|
||||
package("wiringPi")
|
||||
add_urls("https://github.com/WiringPi/WiringPi/archive/refs/tags/$(version).tar.gz")
|
||||
add_versions("3.14","71d8b4c3bc967cf77ac15fad38791e9976cded31798715cdd3abbf8cca5cd401")
|
||||
if is_plat("linux") then
|
||||
add_extsources("apt::wiringpi")
|
||||
end
|
||||
on_install(function(package)
|
||||
io.writefile(
|
||||
"xmake.lua",
|
||||
[[add_rules("mode.debug", "mode.release")
|
||||
target("wiringPi")
|
||||
set_kind("static")
|
||||
add_files("wiringPi/*.c")
|
||||
add_headerfiles("wiringPi/wiringPi.h")
|
||||
add_includedirs("wiringPi")
|
||||
]])
|
||||
import("package.tools.xmake").install(package)
|
||||
end)
|
||||
package_end()
|
||||
|
||||
package("my-libmodbus")
|
||||
set_base("libmodbus")
|
||||
on_install(function(package)
|
||||
local configs = {"--disable-tests"};
|
||||
if not package:config("shared") then
|
||||
table.insert(configs,"--enable-static=yes")
|
||||
table.insert(configs,"--enable-shared=no")
|
||||
end
|
||||
import("package.tools.autoconf").install(package,configs)
|
||||
end)
|
||||
package_end()
|
||||
|
||||
35
protos/abilityProto.proto
Normal file
35
protos/abilityProto.proto
Normal file
@ -0,0 +1,35 @@
|
||||
syntax = "proto3";
|
||||
package abilityUnit;
|
||||
option java_package = "ability.proto";
|
||||
option java_outer_classname = "AbilityProto";
|
||||
option java_multiple_files = true;
|
||||
|
||||
service Ability{
|
||||
rpc Start(StartInfo) returns (Response){}
|
||||
rpc Connect (ConnectInfo) returns (Response) {}
|
||||
rpc Disconnect(DisconnectInfo) returns (Response){}
|
||||
rpc Terminate(TerminateInfo) returns (Response){}
|
||||
}
|
||||
|
||||
message Response{
|
||||
int32 code = 1;
|
||||
string msg = 2;
|
||||
}
|
||||
|
||||
message StartInfo{
|
||||
int32 timestamp = 1;
|
||||
}
|
||||
|
||||
message ConnectInfo{
|
||||
string ip = 1;
|
||||
int32 port = 2;
|
||||
int32 timestamp = 3;
|
||||
}
|
||||
|
||||
message DisconnectInfo{
|
||||
int32 timestamp = 1;
|
||||
}
|
||||
|
||||
message TerminateInfo{
|
||||
int32 timestamp = 1;
|
||||
}
|
||||
29
protos/conveyorBelt.proto
Normal file
29
protos/conveyorBelt.proto
Normal file
@ -0,0 +1,29 @@
|
||||
syntax = "proto3";
|
||||
package ConveyorBelt;
|
||||
option java_multiple_files = true;
|
||||
option java_package = "ConveyorBelt.proto";
|
||||
|
||||
service ConveyorBeltService {
|
||||
rpc open(SpeedInfo) returns (Response) {}
|
||||
rpc close(DeviceID) returns (Response) {}
|
||||
rpc setSpeed(SpeedInfo) returns (Response) {}
|
||||
rpc setDirection(DirectionInfo) returns (Response) {}
|
||||
rpc getWorkState(DeviceID) returns (Response) {}
|
||||
}
|
||||
|
||||
message Response{
|
||||
int32 code = 1;
|
||||
string msg = 2;
|
||||
}
|
||||
|
||||
message SpeedInfo{
|
||||
float speed = 1;
|
||||
}
|
||||
|
||||
message DeviceID{
|
||||
int32 conveyorBeltId = 1;
|
||||
}
|
||||
|
||||
message DirectionInfo{
|
||||
int32 direction = 1;
|
||||
}
|
||||
13
protos/makefile
Normal file
13
protos/makefile
Normal file
@ -0,0 +1,13 @@
|
||||
all: abilityProto.grpc.pb.cc abilityProto.grpc.pb.h conveyorBelt.grpc.pb.cc conveyorBelt.grpc.pb.h abilityProto.pb.cc abilityProto.pb.h conveyorBelt.pb.cc conveyorBelt.pb.h
|
||||
abilityProto.grpc.pb.cc abilityProto.grpc.pb.h:
|
||||
protoc -I . --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` abilityProto.proto
|
||||
conveyorBelt.grpc.pb.cc conveyorBelt.grpc.pb.h:
|
||||
protoc -I . --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` conveyorBelt.proto
|
||||
|
||||
abilityProto.pb.cc abilityProto.pb.h:
|
||||
protoc -I . --cpp_out=. abilityProto.proto
|
||||
conveyorBelt.pb.cc conveyorBelt.pb.h:
|
||||
protoc -I . --cpp_out=. conveyorBelt.proto
|
||||
|
||||
clean:
|
||||
rm abilityProto.grpc.pb.cc abilityProto.grpc.pb.h conveyorBelt.grpc.pb.cc conveyorBelt.grpc.pb.h abilityProto.pb.cc abilityProto.pb.h conveyorBelt.pb.cc conveyorBelt.pb.h
|
||||
51
test/test-controller-api.py
Normal file
51
test/test-controller-api.py
Normal file
@ -0,0 +1,51 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
# 设置服务器地址和端口
|
||||
BASE_URL = "http://127.0.0.1:1"
|
||||
|
||||
def test_process_get(conveyor_belt_id):
|
||||
"""
|
||||
测试 /api/processGet 接口
|
||||
"""
|
||||
url = f"{BASE_URL}/api/processGet"
|
||||
params = {"id": conveyor_belt_id}
|
||||
print(f"Testing GET {url} with params: {params}")
|
||||
|
||||
try:
|
||||
response = requests.get(url, params=params)
|
||||
print(f"Response Status Code: {response.status_code}")
|
||||
print(f"Response Body: {response.json()}")
|
||||
except Exception as e:
|
||||
print(f"Error during GET request: {e}")
|
||||
|
||||
def test_process_post(conveyor_belt_id, action, speed):
|
||||
"""
|
||||
测试 /api/processPost 接口
|
||||
"""
|
||||
url = f"{BASE_URL}/api/processPost"
|
||||
headers = {"Content-Type": "application/json"}
|
||||
payload = {
|
||||
"id": conveyor_belt_id,
|
||||
"action": action,
|
||||
"speed": speed
|
||||
}
|
||||
print(f"Testing POST {url} with payload: {json.dumps(payload, indent=4)}")
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
print(f"Response Status Code: {response.status_code}")
|
||||
print(f"Response Body: {response.json()}")
|
||||
except Exception as e:
|
||||
print(f"Error during POST request: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 测试 /api/processGet
|
||||
print("=== Testing /api/processGet ===")
|
||||
test_process_get(conveyor_belt_id=108) # 替换为实际的传送带 ID
|
||||
|
||||
# 测试 /api/processPost
|
||||
print("\n=== Testing /api/processPost ===")
|
||||
test_process_post(conveyor_belt_id=108, action=1, speed=100) # 启动传送带
|
||||
test_process_post(conveyor_belt_id=108, action=0, speed=0) # 停止传送带
|
||||
test_process_post(conveyor_belt_id=108, action=2, speed=50) # 无效操作测试
|
||||
61
xmake.lua
Normal file
61
xmake.lua
Normal file
@ -0,0 +1,61 @@
|
||||
-- 设置项目基本配置
|
||||
add_rules("mode.debug", "mode.release")
|
||||
add_languages("c++20")
|
||||
set_policy("package.install_locally", true)
|
||||
|
||||
-- 包含 SDK 的构建配置
|
||||
includes("AbilitySDK/xmake.lua")
|
||||
|
||||
|
||||
add_requires("wiringPi")
|
||||
add_requires("my-libmodbus",{alias="libmodbus"})
|
||||
|
||||
add_requires("jsoncpp")
|
||||
|
||||
add_requires("protobuf-cpp")
|
||||
add_requires("grpc")
|
||||
|
||||
add_requires("abseil", {alias = "abseil"})
|
||||
|
||||
includes("package-index.lua")
|
||||
|
||||
-- 添加包含路径
|
||||
add_includedirs("AbilitySDK/include")
|
||||
|
||||
|
||||
target("protos")
|
||||
set_kind("object")
|
||||
add_packages("protobuf-cpp","grpc",{public=true})
|
||||
add_rules("protobuf.cpp")
|
||||
add_files("protos/conveyorBelt.proto", {proto_public=true,proto_rootdir = "protos", proto_grpc_cpp_plugin = true})
|
||||
-- 这是旧版api使用的protos,移植到新版后可以去除
|
||||
add_files("protos/abilityProto.proto", {proto_public=true,proto_rootdir = "protos", proto_grpc_cpp_plugin = true})
|
||||
|
||||
|
||||
-- ConveyorBeltControlUnit 库
|
||||
target("conveyor-control-unit")
|
||||
set_kind("static")
|
||||
add_includedirs("ConveyorBeltControlUnit/include", {public = true})
|
||||
add_files("ConveyorBeltControlUnit/src/*.cpp")
|
||||
--add_packages("cpp-httplib","jsoncpp","glog","libmodbus","wiringPi","abseil",{public=true})
|
||||
add_packages("cpp-httplib","jsoncpp","glog","libmodbus","abseil",{public=true})
|
||||
|
||||
|
||||
-- ConveyorBeltAbility 库
|
||||
target("conveyor-ability")
|
||||
set_kind("binary")
|
||||
add_includedirs("ConveyorBeltAbility/include", {public = true})
|
||||
add_files("ConveyorBeltAbility/src/*.cpp")
|
||||
add_deps("AbilitySDK", "conveyor-control-unit", "protos")
|
||||
add_packages("cpp-httplib","jsoncpp","glog","abseil",{public=true})
|
||||
|
||||
|
||||
-- ConveyorBeltController 库
|
||||
target("conveyor-controller")
|
||||
set_kind("binary")
|
||||
add_includedirs("ConveyorBeltControlUnit/include", {public = true})
|
||||
add_includedirs("ConveyorBeltController/include", {public = true})
|
||||
add_files("ConveyorBeltController/src/*.cpp")
|
||||
add_deps("AbilitySDK", "protos")
|
||||
add_packages("cpp-httplib","jsoncpp","libmodbus","glog","abseil",{public=true})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user