diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..6fe2959
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,9 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(source /opt/rk3506-toolchain/environment-setup)",
+ "Bash(java -jar fastddsgen.jar lib/System.idl -d lib/ -replace)",
+ "Bash(make)"
+ ]
+ }
+}
diff --git a/.qtcreator/CMakeLists.txt.user b/.qtcreator/CMakeLists.txt.user
new file mode 100644
index 0000000..6abe076
--- /dev/null
+++ b/.qtcreator/CMakeLists.txt.user
@@ -0,0 +1,318 @@
+
+
+
+
+
+ EnvironmentId
+ {834c89b2-b6a0-49f4-8777-82ca3f17a41d}
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ true
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ UTF-8
+ false
+ 4
+ false
+ 0
+ 80
+ true
+ true
+ 1
+ 0
+ false
+ true
+ false
+ 2
+ true
+ true
+ 0
+ 8
+ true
+ false
+ 1
+ false
+ true
+ true
+ *.md, *.MD, Makefile
+ false
+ true
+ true
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+ true
+ false
+ true
+ true
+ true
+ true
+
+ false
+
+
+ 0
+ true
+
+ true
+ true
+ Builtin.DefaultTidyAndClazy
+ 10
+ true
+
+
+
+ true
+
+ 0
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ true
+ Desktop Qt 6.11.1 MinGW 64-bit
+ Desktop Qt 6.11.1 MinGW 64-bit
+ qt.qt6.6111.win64_mingw_kit
+ 0
+ 0
+ 0
+
+ Release
+ 2
+ false
+
+ -DCMAKE_BUILD_TYPE:STRING=Release
+-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
+-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
+-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
+-DCMAKE_GENERATOR:STRING=MinGW Makefiles
+-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
+-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtcreator/cmake-helper/qtcreator-project.cmake
+-DQT_CREATOR_ENABLE_MAINTENANCE_TOOL_PROVIDER:BOOL=ON
+-DQT_CREATOR_ENABLE_PACKAGE_MANAGER_SETUP:BOOL=ON
+-DQT_ENABLE_QML_DEBUG:BOOL=%{Qt:QT_ENABLE_QML_DEBUG}
+-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
+ .\build\%{Asciify:%{Kit:FileSystemName}-%{BuildConfig:Name}}
+
+
+
+
+ all
+
+ false
+
+ true
+ 构建
+ CMakeProjectManager.MakeStep
+
+ 1
+ 构建
+ 构建
+ ProjectExplorer.BuildSteps.Build
+
+
+
+
+
+ clean
+
+ false
+
+ true
+ 构建
+ CMakeProjectManager.MakeStep
+
+ 1
+ 清除
+ 清除
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ false
+
+ Release
+ CMakeProjectManager.CMakeBuildConfiguration
+ 0
+ 0
+
+
+ 0
+ 部署
+ 部署
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ProjectExplorer.DefaultDeployConfiguration
+
+
+
+
+
+
+
+
+ false
+
+ true
+ 构建
+ ApplicationManagerPlugin.Deploy.CMakePackageStep
+
+
+ install-package --acknowledge
+ true
+ Install Application Manager package
+ ApplicationManagerPlugin.Deploy.InstallPackageStep
+
+
+
+
+
+
+
+ 2
+ 部署
+ 部署
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ApplicationManagerPlugin.Deploy.Configuration
+
+ 2
+
+ false
+
+ false
+
+
+ true
+ true
+ 0
+ true
+
+
+ 2
+
+ false
+ -e cpu-cycles --call-graph "dwarf,4096" -F 250
+
+ ProjectExplorer.CustomExecutableRunConfiguration
+
+ false
+
+ true
+ true
+ %{RunConfig:Executable:Path}
+
+ 1
+
+ 1
+
+
+ 0
+ 部署
+ 部署
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ProjectExplorer.DefaultDeployConfiguration
+
+
+
+
+
+
+
+
+ false
+
+ true
+ 构建
+ ApplicationManagerPlugin.Deploy.CMakePackageStep
+
+
+ install-package --acknowledge
+ true
+ Install Application Manager package
+ ApplicationManagerPlugin.Deploy.InstallPackageStep
+
+
+
+
+
+
+
+ 2
+ 部署
+ 部署
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ApplicationManagerPlugin.Deploy.Configuration
+
+ 2
+
+ true
+ true
+ 0
+ true
+
+
+ 2
+
+ false
+ -e cpu-cycles --call-graph "dwarf,4096" -F 250
+
+ ProjectExplorer.CustomExecutableRunConfiguration
+
+ false
+
+ true
+ true
+ %{RunConfig:Executable:Path}
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ Version
+ 22
+
+
diff --git a/BX-5(M)_6K字库控制器通讯协议用户版.pdf b/BX-5(M)_6K字库控制器通讯协议用户版.pdf
new file mode 100644
index 0000000..5143ff1
Binary files /dev/null and b/BX-5(M)_6K字库控制器通讯协议用户版.pdf differ
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd03ab7..9b034c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,7 +30,7 @@ include_directories(common)
include_directories(lib)
message(STATUS "Configuring System...")
-add_library(System_lib lib/SystemTypeObjectSupport.cxx lib/SystemPubSubTypes.cxx)
+add_library(System_lib lib/WeighingDDSTypeTypeObjectSupport.cxx lib/WeighingDDSTypePubSubTypes.cxx)
target_link_libraries(System_lib fastcdr fastdds)
# Demo Application.
@@ -52,6 +52,8 @@ add_executable(Core
core/main.cxx
core/Publisher.cxx
core/Subscriber.cxx
+ core/msg.hpp
+ lib/WeighingDDSType.hpp
)
target_compile_definitions(Core PRIVATE PROGRAM_MODULE="${PROGRAM_MODULE}" PROGRAM_VERSION="${PROGRAM_VERSION}")
target_include_directories(Core PRIVATE core)
@@ -104,16 +106,18 @@ target_link_libraries(HttpServer fastcdr fastdds
)
# Led Application.
-link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)
+# 注:不再依赖 vendor SDK(libfun.so / YQNetCom.h),改为裸 TCP 走 BX-6K1-YY 协议。
set(PROGRAM_MODULE "Led")
add_executable(Led
led/main.cxx
led/Subscriber.cxx
+ led/BX6K1YYProtocol.cxx
+ led/Bx6k1YyLedClient.cxx
)
target_compile_definitions(Led PRIVATE PROGRAM_MODULE="${PROGRAM_MODULE}" PROGRAM_VERSION="${PROGRAM_VERSION}")
target_include_directories(Led PRIVATE led)
target_link_libraries(Led fastcdr fastdds
- System_lib fun
+ System_lib
)
# Print Application.
@@ -125,6 +129,7 @@ add_executable(Print
print/MsgHandler.cxx
common/SerialMsgHandler.cxx
lib/strcode.cpp
+ print/MsgHandler.hpp
)
target_compile_definitions(Print PRIVATE PROGRAM_MODULE="${PROGRAM_MODULE}" PROGRAM_VERSION="${PROGRAM_VERSION}")
target_include_directories(Print PRIVATE print)
@@ -132,6 +137,24 @@ target_link_libraries(Print fastcdr fastdds
System_lib
)
+# ReadCard Application.
+set(PROGRAM_MODULE "ReadCard")
+add_executable(ReadCard
+ readcard/main.cxx
+ readcard/Publisher.cxx
+ readcard/Subscriber.cxx
+ readcard/MsgHandler.cxx
+ readcard/Publisher.hpp
+ readcard/msg.hpp
+ common/SerialMsgHandler.cxx
+ readcard/MsgHandler.hpp
+ )
+target_compile_definitions(ReadCard PRIVATE PROGRAM_MODULE="${PROGRAM_MODULE}" PROGRAM_VERSION="${PROGRAM_VERSION}")
+target_include_directories(ReadCard PRIVATE readcard)
+target_link_libraries(ReadCard fastcdr fastdds
+ System_lib
+ )
+
# Weigh Application.
set(PROGRAM_MODULE "Weigh")
add_executable(Weigh
@@ -141,6 +164,7 @@ add_executable(Weigh
weigh/MsgHandler.cxx
weigh/WeightStabilityDetector.cxx
common/SerialMsgHandler.cxx
+ common/SerialMsgHandler.hpp
)
target_compile_definitions(Weigh PRIVATE PROGRAM_MODULE="${PROGRAM_MODULE}" PROGRAM_VERSION="${PROGRAM_VERSION}")
target_include_directories(Weigh PRIVATE weigh)
diff --git a/RC522.c b/RC522.c
new file mode 100644
index 0000000..912174b
--- /dev/null
+++ b/RC522.c
@@ -0,0 +1,666 @@
+//#include "intrins.h"
+#include "main.h"
+#include "RC522.h"
+#include "stdio.h"
+//#include "tim.h"
+
+extern TIM_HandleTypeDef htim6;
+
+#define MAXRLEN 18
+
+
+/////////////////////////////////////////////////////////////////////
+#define RC522_RST_HIGH HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); //任意未接IO
+#define RC522_RST_LOW HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); //任意未接IO
+
+#define RC522_ENABLE HAL_GPIO_WritePin(ADDR_ALE_GPIO_Port,ADDR_ALE_Pin,GPIO_PIN_RESET);
+#define RC522_DISABLE HAL_GPIO_WritePin(ADDR_ALE_GPIO_Port,ADDR_ALE_Pin,GPIO_PIN_SET);
+
+extern SPI_HandleTypeDef hspi1;
+
+#define fac_us 25 //72 //时钟频率,单位MHZ
+
+/*微秒级延时函数*/
+//void delay_us(uint32_t nus)
+//{
+// uint32_t ticks;
+// uint32_t told,tnow,tcnt=0;
+// uint32_t reload=SysTick->LOAD; //LOAD的值
+// ticks=nus*fac_us; //需要的节拍数
+//// delay_osschedlock(); //阻止os调度,防止打断us延时
+//// vTaskSuspendAll();
+// told=SysTick->VAL; //刚进入时的计数器值
+// while(1)
+// {
+//
+// tnow=SysTick->VAL;
+// if(tnow!=told)
+// {
+// if(tnow=ticks) //时间超过/等于要延迟的时间,则退出.
+// {
+// break;
+// }
+// }
+// }
+//// delay_osschedunlock(); //恢复os调度
+//// xTaskResumeAll(); //恢复OS调度
+//}
+
+void delay_us(uint16_t nus)
+{
+ __HAL_TIM_SetCounter(&htim6,0);
+ __HAL_TIM_ENABLE(&htim6);
+ while(__HAL_TIM_GetCounter(&htim6)SR&SPI_FLAG_TXE)==0)//等待发送区空
+ {
+ retry++;
+ if(retry>20000)return -1;
+ }
+ SPIx->DR=*p_TxData++;//发送一个byte
+ retry=0;
+ while((SPIx->SR&SPI_FLAG_RXNE)==0)//等待接收完一个byte
+ {
+ SPIx->SR = SPIx->SR;
+ retry++;
+ if(retry>20000)return -1;
+ }
+ SPIx->DR;
+ }
+ return 0;
+}
+//------------------------------------------------------------------------------------
+int32_t SPI_ReadNBytes(SPI_TypeDef* SPIx, uint8_t *p_RxData,uint32_t readDataNum)
+{
+ uint16_t retry=0;
+ while(readDataNum--)
+ {
+ SPIx->DR = 0xFF;
+ while(!(SPIx->SR&SPI_FLAG_TXE))
+ {
+ retry++;
+ if(retry>20000)return -1;
+ }
+ retry = 0;
+ while(!(SPIx->SR&SPI_FLAG_RXNE))
+ {
+ retry++;
+ if(retry>20000)return -1;
+ }
+ *p_RxData++ = SPIx->DR;
+ }
+ return 0;
+}
+//------------------------------------------------------------------------------------
+void RC522_Init(void)
+{
+ RC522_ENABLE;
+ HAL_SPI_Transmit(&hspi1, (uint8_t *)0xaa, sizeof((uint8_t *)0xaa), 0xFF);//启动传输
+ RC522_DISABLE;
+
+ HAL_Delay(50);
+ PcdReset();//复位RC522读卡器
+ HAL_Delay(10);
+ PcdReset();//复位RC522读卡器
+ HAL_Delay(10);
+
+ PcdAntennaOff();//关闭天线发射
+ HAL_Delay(10);
+ PcdAntennaOn();//开启天线发射
+
+ printf("RFID-MFRC522 初始化完成\r\n"); //测试引脚初始化完成
+// printf("RFID-MFRC522 Initialization Finished!\r\n"); //测试引脚初始化完成
+ printf("FindCard Starting ...\r\n"); //测试引脚初始化完成
+}
+//-------------------------------------------------------------------------------
+//功 能:寻卡
+//参数说明: req_code[IN]:寻卡方式
+// 0x52 = 寻感应区内所有符合14443A标准的卡
+// 0x26 = 寻未进入休眠状态的卡
+// pTagType[OUT]:卡片类型代码
+// 0x4400 = Mifare_UltraLight
+// 0x0400 = Mifare_One(S50)
+// 0x0200 = Mifare_One(S70)
+// 0x0800 = Mifare_Pro(X)
+// 0x4403 = Mifare_DESFire
+//返 回: 成功返回MI_OK
+char PcdRequest(unsigned char req_code, unsigned char *pTagType)
+{
+ char status;
+ unsigned int unLen;
+ unsigned char ucComMF522Buf[MAXRLEN];
+
+ ClearBitMask(Status2Reg, 0x08); //清RC522寄存位
+ WriteRawRC(BitFramingReg, 0x07); //写RC623寄存器
+ SetBitMask(TxControlReg, 0x03); //置RC522寄存位
+
+ ucComMF522Buf[0] = req_code;
+
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &unLen);
+ if ((status == MI_OK) && (unLen == 0x10))
+ {
+ *pTagType = ucComMF522Buf[0];
+ *(pTagType + 1) = ucComMF522Buf[1];
+ }
+ else
+ {
+ status = MI_ERR;
+ }
+ return status;
+}
+//-------------------------------------------------------------------------------
+//功 能:防冲撞
+//参数说明: pSnr[OUT]:卡片序列号,4字节
+//返 回: 成功返回MI_OK
+char PcdAnticoll(unsigned char *pSnr)
+{
+ char status;
+ unsigned char i, snr_check = 0;
+ unsigned int unLen;
+ unsigned char ucComMF522Buf[MAXRLEN];
+ ClearBitMask(Status2Reg, 0x08);
+ WriteRawRC(BitFramingReg, 0x00);
+ ClearBitMask(CollReg, 0x80);
+ ucComMF522Buf[0] = PICC_ANTICOLL1;
+ ucComMF522Buf[1] = 0x20;
+
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, &unLen);
+ if (status == MI_OK)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ *(pSnr + i) = ucComMF522Buf[i];
+ snr_check ^= ucComMF522Buf[i];
+ }
+ if (snr_check != ucComMF522Buf[i])
+ {
+ status = MI_ERR;
+ }
+ }
+ SetBitMask(CollReg, 0x80);
+ return status;
+}
+//---------------------------------------------------------------------------
+//功 能:选定卡片
+//参数说明: pSnr[IN]:卡片序列号,4字节
+//返 回: 成功返回MI_OK
+char PcdSelect(unsigned char *pSnr)
+{
+ char status;
+ unsigned char i;
+ unsigned int unLen;
+ unsigned char ucComMF522Buf[MAXRLEN];
+ ucComMF522Buf[0] = PICC_ANTICOLL1;
+ ucComMF522Buf[1] = 0x70;
+ ucComMF522Buf[6] = 0;
+ for (i = 0; i < 4; i++)
+ {
+ ucComMF522Buf[i + 2] = *(pSnr + i);
+ ucComMF522Buf[6] ^= *(pSnr + i);
+ }
+ CalulateCRC(ucComMF522Buf, 7, &ucComMF522Buf[7]);
+ ClearBitMask(Status2Reg, 0x08);
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, &unLen);
+ if ((status == MI_OK) && (unLen == 0x18))
+ {
+ status = MI_OK;
+ }
+ else
+ {
+ status = MI_ERR;
+ }
+ return status;
+}
+//----------------------------------------------------------------------------------
+//功 能:验证卡片密码
+//参数说明: auth_mode[IN]: 密码验证模式
+// 0x60 = 验证A密钥
+// 0x61 = 验证B密钥
+// addr[IN]:块地址
+// pKey[IN]:密码
+// pSnr[IN]:卡片序列号,4字节
+//返 回: 成功返回MI_OK
+char PcdAuthState(unsigned char auth_mode, unsigned char addr, unsigned char *pKey, unsigned char *pSnr)
+{
+ char status;
+ unsigned int unLen;
+ unsigned char i, ucComMF522Buf[MAXRLEN];
+ ucComMF522Buf[0] = auth_mode;
+ ucComMF522Buf[1] = addr;
+ for (i = 0; i < 6; i++)
+ {
+ ucComMF522Buf[i + 2] = *(pKey + i);
+ }
+ for (i = 0; i < 6; i++)
+ {
+ ucComMF522Buf[i + 8] = *(pSnr + i);
+ }
+ status = PcdComMF522(PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, &unLen);
+ if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
+ {
+ status = MI_ERR;
+ }
+ return status;
+}
+//--------------------------------------------------------------------------------------
+//功 能:读取M1卡一块数据
+//参数说明: addr[IN]:块地址
+// p [OUT]:读出的数据,16字节
+//返 回: 成功返回MI_OK
+char PcdRead(unsigned char addr, unsigned char *pData)
+{
+ char status;
+ unsigned int unLen;
+ unsigned char i, ucComMF522Buf[MAXRLEN];
+ ucComMF522Buf[0] = PICC_READ;
+ ucComMF522Buf[1] = addr;
+ CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
+
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
+ if ((status == MI_OK) && (unLen == 0x90))
+ {
+ for (i = 0; i < 16; i++)
+ {
+ *(pData + i) = ucComMF522Buf[i];
+ }
+ }
+ else
+ {
+ status = MI_ERR;
+ }
+ return status;
+}
+//-----------------------------------------------------------------------------------
+//功 能:写数据到M1卡一块
+//参数说明: addr[IN]:块地址
+// p [IN]:写入的数据,16字节
+//返 回: 成功返回MI_OK
+char PcdWrite(unsigned char addr, unsigned char *pData)
+{
+ char status;
+ unsigned int unLen;
+ unsigned char i, ucComMF522Buf[MAXRLEN];
+ ucComMF522Buf[0] = PICC_WRITE;
+ ucComMF522Buf[1] = addr;
+ CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
+ if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
+ {
+ status = MI_ERR;
+ }
+ if (status == MI_OK)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ ucComMF522Buf[i] = *(pData + i);
+ }
+ CalulateCRC(ucComMF522Buf, 16, &ucComMF522Buf[16]);
+
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, &unLen);
+ if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
+ {
+ status = MI_ERR;
+ }
+ }
+ return status;
+}
+//----------------------------------------------------------------------------------
+//功 能:扣款和充值
+//参数说明: dd_mode[IN]:命令字
+// 0xC0 = 扣款
+// 0xC1 = 充值
+// addr[IN]:钱包地址
+// pValue[IN]:4字节增(减)值,低位在前
+//返 回: 成功返回MI_OK
+char PcdValue(unsigned char dd_mode, unsigned char addr, unsigned char *pValue)
+{
+ char status;
+ unsigned int unLen;
+ unsigned char i, ucComMF522Buf[MAXRLEN];
+ ucComMF522Buf[0] = dd_mode;
+ ucComMF522Buf[1] = addr;
+ CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
+
+ if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
+ {
+ status = MI_ERR;
+ }
+ if (status == MI_OK)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ ucComMF522Buf[i] = *(pValue + i);
+ }
+ CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]);
+ unLen = 0;
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen);
+ if (status != MI_ERR)
+ {
+ status = MI_OK;
+ }
+ }
+ if (status == MI_OK)
+ {
+ ucComMF522Buf[0] = PICC_TRANSFER;
+ ucComMF522Buf[1] = addr;
+ CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
+
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
+
+ if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
+ {
+ status = MI_ERR;
+ }
+ }
+ return status;
+}
+//------------------------------------------------------------------------------------
+//功 能:备份钱包
+//参数说明: sourceaddr[IN]:源地址
+// goaladdr[IN]:目标地址
+//返 回: 成功返回MI_OK
+char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr)
+{
+ char status;
+ unsigned int unLen;
+ unsigned char ucComMF522Buf[MAXRLEN];
+ ucComMF522Buf[0] = PICC_RESTORE;
+ ucComMF522Buf[1] = sourceaddr;
+ CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
+ if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
+ {
+ status = MI_ERR;
+ }
+ if (status == MI_OK)
+ {
+ ucComMF522Buf[0] = 0;
+ ucComMF522Buf[1] = 0;
+ ucComMF522Buf[2] = 0;
+ ucComMF522Buf[3] = 0;
+ CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]);
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen);
+ if (status != MI_ERR)
+ {
+ status = MI_OK;
+ }
+ }
+ if (status != MI_OK)
+ {
+ return MI_ERR;
+ }
+ ucComMF522Buf[0] = PICC_TRANSFER;
+ ucComMF522Buf[1] = goaladdr;
+ CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
+ status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
+ if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
+ {
+ status = MI_ERR;
+ }
+ return status;
+}
+//------------------------------------------------------------------------------------
+//功 能:命令卡片进入休眠状态
+//返 回: 成功返回MI_OK
+char PcdHalt(void)
+{
+ // char status;
+ unsigned int unLen;
+ unsigned char ucComMF522Buf[MAXRLEN];
+
+ ucComMF522Buf[0] = PICC_HALT;
+ ucComMF522Buf[1] = 0;
+ CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
+
+ PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
+
+ return MI_OK;
+}
+//--------------------------------------------------------------------------------------
+//用MF522计算CRC16函数
+void CalulateCRC(unsigned char *pIndata, unsigned char len, unsigned char *pOutData)
+{
+ unsigned char i, n;
+ ClearBitMask(DivIrqReg, 0x04);
+ WriteRawRC(CommandReg, PCD_IDLE);
+ SetBitMask(FIFOLevelReg, 0x80);
+ for (i = 0; i < len; i++)
+ {
+ WriteRawRC(FIFODataReg, *(pIndata + i));
+ }
+ WriteRawRC(CommandReg, PCD_CALCCRC);
+ i = 0xFF;
+ do
+ {
+ n = ReadRawRC(DivIrqReg);
+ i--;
+ } while ((i != 0) && !(n & 0x04));
+ pOutData[0] = ReadRawRC(CRCResultRegL);
+ pOutData[1] = ReadRawRC(CRCResultRegM);
+}
+//-----------------------------------------------------------------------------------------
+//功 能:复位RC522
+//返 回: 成功返回MI_OK
+char PcdReset(void)
+{
+// RC522_RST_HIGH;
+// delay_us(10);
+// RC522_RST_LOW;
+// HAL_Delay(60);
+// RC522_RST_HIGH;
+// HAL_GPIO_WritePin(LED_RUN_GPIO_Port,LED_RUN_Pin,GPIO_PIN_RESET);
+ delay_us(4000);
+
+
+ WriteRawRC(CommandReg, PCD_RESETPHASE);
+ HAL_Delay(20);
+
+ WriteRawRC(ModeReg, 0x3D);
+ WriteRawRC(TReloadRegL, 30);
+ WriteRawRC(TReloadRegH, 0);
+ WriteRawRC(TModeReg, 0x8D);
+ WriteRawRC(TPrescalerReg, 0x3E);
+ WriteRawRC(TxAutoReg, 0x40);
+
+ ClearBitMask(TestPinEnReg, 0x80);
+ WriteRawRC(TxAutoReg, 0x40);
+
+ return MI_OK;
+}
+//-------------------------------------------------------------------------------------
+//功 能:读RC632寄存器
+//参数说明:Address[IN]:寄存器地址
+//返 回:读出的值
+unsigned char ReadRawRC(unsigned char Address)
+{
+ unsigned char ucAddr;
+ unsigned char ucResult = 0;
+ ucAddr = ((Address << 1) & 0x7E) | 0x80;
+ HAL_Delay(10);
+ RC522_ENABLE;
+ SPI_WriteNBytes(SPI1, &ucAddr, 1); //向总线写多个数据
+ SPI_ReadNBytes(SPI1, &ucResult, 1); //向总线读多个数据
+// HAL_SPI_Transmit(&hspi1,&ucAddr,1,0xff);
+// HAL_SPI_Receive(&hspi1,&ucResult,1,0xff);
+// while(HAL_SPI_Transmit(&hspi1,&ucAddr,1,0xff) == HAL_OK);
+// while(HAL_SPI_Receive(&hspi1,&ucResult,1,0xff) == HAL_OK);
+ RC522_DISABLE;
+ return ucResult;
+}
+//---------------------------------------------------------------------------------------------
+//功 能:写RC632寄存器
+//参数说明:Address[IN]:寄存器地址
+// value[IN]:写入的值
+void WriteRawRC(unsigned char Address, unsigned char value)
+{
+ unsigned char ucAddr;
+ uint8_t write_buffer[2] = {0};
+ ucAddr = ((Address << 1) & 0x7E);
+ write_buffer[0] = ucAddr;
+ write_buffer[1] = value;
+ HAL_Delay(10);
+ RC522_ENABLE;
+ SPI_WriteNBytes(SPI1, write_buffer, 2);
+// HAL_SPI_Transmit(&hspi1,write_buffer,2,0xff);
+// while(HAL_SPI_Transmit(&hspi1,write_buffer,2,0xff) == HAL_OK);
+ RC522_DISABLE;
+}
+//---------------------------------------------------------------------------------------------
+//功 能:置RC522寄存器位
+//参数说明:reg[IN]:寄存器地址
+// mask[IN]:置位值
+void SetBitMask(unsigned char reg, unsigned char mask)
+{
+ char tmp = 0x0;
+ tmp = ReadRawRC(reg); //读RC632寄存器
+ WriteRawRC(reg, tmp | mask); // set bit mask
+}
+//-----------------------------------------------------------------------------------------------
+//功 能:清RC522寄存器位
+//参数说明:reg[IN]:寄存器地址
+// mask[IN]:清位值
+void ClearBitMask(unsigned char reg, unsigned char mask)
+{
+ char tmp = 0x0;
+ tmp = ReadRawRC(reg);
+ WriteRawRC(reg, tmp & ~mask); // clear bit mask
+}
+//------------------------------------------------------------------------------------------
+//功 能:通过RC522和ISO14443卡通讯
+//参数说明:Command[IN]:RC522命令字
+// pIn [IN]:通过RC522发送到卡片的数据
+// InLenByte[IN]:发送数据的字节长度
+// pOut [OUT]:接收到的卡片返回数据
+// *pOutLenBit[OUT]:返回数据的位长度
+char PcdComMF522(unsigned char Command,
+ unsigned char *pInData,
+ unsigned char InLenByte,
+ unsigned char *pOutData,
+ unsigned int *pOutLenBit)
+{
+ char status = MI_ERR;
+ unsigned char irqEn = 0x00;
+ unsigned char waitFor = 0x00;
+ unsigned char lastBits;
+ unsigned char n;
+ unsigned int i;
+ switch (Command)
+ {
+ case PCD_AUTHENT:
+ irqEn = 0x12;
+ waitFor = 0x10;
+ break;
+ case PCD_TRANSCEIVE:
+ irqEn = 0x77;
+ waitFor = 0x30;
+ break;
+ default:
+ break;
+ }
+ WriteRawRC(ComIEnReg, irqEn | 0x80);
+ ClearBitMask(ComIrqReg, 0x80);
+ WriteRawRC(CommandReg, PCD_IDLE);
+ SetBitMask(FIFOLevelReg, 0x80);
+ for (i = 0; i < InLenByte; i++)
+ {
+ WriteRawRC(FIFODataReg, pInData[i]);
+ }
+ WriteRawRC(CommandReg, Command);
+ if (Command == PCD_TRANSCEIVE)
+ {
+ SetBitMask(BitFramingReg, 0x80);
+ }
+ i = 800; //根据时钟频率调整,操作M1卡最大等待时间25ms
+ do
+ {
+ n = ReadRawRC(ComIrqReg);
+ i--;
+ } while ((i != 0) && !(n & 0x01) && !(n & waitFor));
+ ClearBitMask(BitFramingReg, 0x80);
+ if (i != 0)
+ {
+ if (!(ReadRawRC(ErrorReg) & 0x1B))
+ {
+ status = MI_OK;
+ if (n & irqEn & 0x01)
+ {
+ status = MI_NOTAGERR;
+ }
+ if (Command == PCD_TRANSCEIVE)
+ {
+ n = ReadRawRC(FIFOLevelReg);
+ lastBits = ReadRawRC(ControlReg) & 0x07;
+ if (lastBits)
+ {
+ *pOutLenBit = (n - 1) * 8 + lastBits;
+ }
+ else
+ {
+ *pOutLenBit = n * 8;
+ }
+ if (n == 0)
+ {
+ n = 1;
+ }
+ if (n > MAXRLEN)
+ {
+ n = MAXRLEN;
+ }
+ for (i = 0; i < n; i++)
+ {
+ pOutData[i] = ReadRawRC(FIFODataReg);
+ }
+ }
+ }
+ else
+ {
+ status = MI_ERR;
+ }
+ }
+ SetBitMask(ControlReg, 0x80); // stop timer now
+ WriteRawRC(CommandReg, PCD_IDLE);
+ return status;
+}
+//--------------------------------------------------------------------------------------
+//开启天线
+//每次启动或关闭天险发射之间应至少有1ms的间隔
+void PcdAntennaOn(void)
+{
+ unsigned char i;
+ i = ReadRawRC(TxControlReg);
+ if (!(i & 0x03))
+ {
+ SetBitMask(TxControlReg, 0x03);
+ }
+}
+//----------------------------------------------------------------------------------------
+//关闭天线
+void PcdAntennaOff(void)
+{
+ ClearBitMask(TxControlReg, 0x03);
+}
+//------------------------------------------------
+void RC522_Config(unsigned char Card_Type)
+{
+ ClearBitMask(Status2Reg, 0x08);
+ WriteRawRC(ModeReg, 0x3D);
+ WriteRawRC(RxSelReg, 0x86);
+ WriteRawRC(RFCfgReg, 0x7F);
+ WriteRawRC(TReloadRegL, 30);
+ WriteRawRC(TReloadRegH, 0);
+ WriteRawRC(TModeReg, 0x8D);
+ WriteRawRC(TPrescalerReg, 0x3E);
+ HAL_Delay(5);
+ PcdAntennaOn();
+}
diff --git a/RFID_S50.c b/RFID_S50.c
new file mode 100644
index 0000000..988f5da
--- /dev/null
+++ b/RFID_S50.c
@@ -0,0 +1,532 @@
+/*******************************************************************************
+ * ļ User\src\RFID_S50.c
+ * ־
+ * ̼汾 V3.5.0
+ * 汾 V1.0
+ * 2016218
+ * Ȩ а˾
+ ******************************************************************************
+ * ã
+ * DZ
+ *
+ *
+ *
+ *
+ *
+ ******************************************************************************/
+#ifdef RFIDS50_DEV
+
+#include "stm32f10x.h"
+#include "RFID_S50.h"
+#include
+#include
+#include "FiveSuart.h"
+#include "CANManager.h"
+
+
+#define RFID_S50_CMD_Parameter 20 //0x14 ڲ
+#define RFID_S50_CMD_Control 21 //0x15 豸 ر
+#define RFID_S50_CMD_Beep 22 //0x16
+#define RFID_S50_CMD_Password 23 //0x17
+#define RFID_S50_CMD_FindCard 24 //0x18 ԶѰ
+#define RFID_S50_CMD_ReadCard 25 //0x19
+#define RFID_S50_CMD_WriteCard 26 //0x1A д
+#define RFID_S50_CMD_Stop 27 //0x1B ֹ
+#define RFID_S50_CMD_Reset 29 //0x1D λ
+
+RFID_S50_Parameter RFID_S50_Para;
+
+//֤д modified by Hy 2019-10-20
+uint8_t RFID_S50_CheckedData[16]={0};
+
+//֤д modified by Hy 2019-10-20
+uint8_t RFID_S50_CheckedBlockID=0;
+
+//Ƿдɹ modified by Hy 2019-10-20
+bool isWrite=false;
+
+// modified by Hy 2019-10-20
+void ReadCard(uint8_t blockID)
+{
+ uint16_t crcResult=0;
+ uint8_t crcL=0;
+ uint8_t crcH=0;
+ uint8_t m_buf[6]={0};
+
+ m_buf[0] = 0x05; //
+ m_buf[1] = 0x01; //ַ
+ m_buf[2] = 0x04; //
+ m_buf[3] = blockID; //
+ crcResult = CRC16(m_buf, 4);
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+ m_buf[4] = crcH;
+ m_buf[5] = crcL;
+ Usart_SendData(RFID_S50_Para.CommPara.USARTID,m_buf,6);
+}
+
+/*******************************************************************************
+* Function Name : RFID_S50_OnCommand
+* Description :
+* Input : data
+* Output : None
+* Return : None
+* Attention :
+*******************************************************************************/
+void RFID_S50_OnCommand(uint8_t * pData ,uint16_t m_len )
+{
+ //յȫ
+ if (pData[1] == 1)
+ {
+ //ַ1
+ uint16_t crcResult = 0; //У
+ uint8_t crcL = 0; //Уλ
+ uint8_t crcH = 0; //Уλ
+ crcResult = CRC16(pData,m_len - 2);
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+
+ //if ((crcL == pData[m_len - 1]) || (crcH == pData[m_len]))
+ if ((crcH == pData[m_len - 2]) && (crcL == pData[m_len-1]))
+ {
+
+ //ͨУ
+ uint8_t m_Command = pData[2]; //
+ if (pData[3]==0)
+ {
+ //
+ CanTxMsg TxMsg;
+ TxMsg.RTR = CAN_RTR_DATA; // Ϊ֡
+ TxMsg.IDE = CAN_ID_EXT; // ʹչ֡
+ switch (m_Command)
+ {
+ case 1: //
+ {
+ uint32_t m_id=GetCANID(DeviceID,RFID_S50_CMD_Beep,0x01);
+ //سɹϢ
+ CAN_SendResult(m_id,0x00);
+ }
+ break;
+ case 2: //Ѱ
+ {
+ TxMsg.ExtId=GetCANID(DeviceID,RFID_S50_CMD_FindCard,0x01);
+ TxMsg.DLC=5;
+ TxMsg.Data[0]=0x00;
+ TxMsg.Data[1]=pData[4];
+ TxMsg.Data[2]=pData[5];
+ TxMsg.Data[3]=pData[6];
+ TxMsg.Data[4]=pData[7];
+ CAN_SendData(&TxMsg);
+ }
+ break;
+ case 3: //
+ {
+ uint32_t m_id=GetCANID(DeviceID,RFID_S50_CMD_Password,0x01);
+ //سɹϢ
+ CAN_SendResult(m_id,0x00);
+ }
+ break;
+ case 4: //ݿ鷵
+ {
+ int flag = 0;
+ int i = 0;
+ //֤ modified by Hy 2019-10-20
+ if(isWrite)
+ {
+ isWrite=false;
+ if(RFID_S50_CheckedBlockID==pData[4])
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if (RFID_S50_CheckedData[i] != pData[i+5])
+ {
+ flag = 1;
+ break;
+ }
+ }
+ if (flag == 1)
+ {
+ uint32_t m_id=GetCANID(DeviceID,RFID_S50_CMD_WriteCard,0x01);
+ //ʧϢ
+ CAN_SendResult(m_id,0x01);
+ }
+ else
+ {
+ uint32_t m_id=GetCANID(DeviceID,RFID_S50_CMD_WriteCard,0x01);
+ //سɹϢ
+ CAN_SendResult(m_id,0x00);
+ }
+ }
+ }
+ else
+ {
+ //ȷ1ֽڵĿź16ֽ
+ TxMsg.ExtId=GetCANID(DeviceID,RFID_S50_CMD_ReadCard,0x01);
+ TxMsg.DLC=2;
+ TxMsg.Data[0]=0x00;
+ TxMsg.Data[1]=pData[4];
+ CAN_SendData(&TxMsg);
+
+ TxMsg.ExtId=GetCANID(DeviceID,RFID_S50_CMD_ReadCard,0x02);
+ TxMsg.DLC=8;
+ TxMsg.Data[0]=pData[5];
+ TxMsg.Data[1]=pData[6];
+ TxMsg.Data[2]=pData[7];
+ TxMsg.Data[3]=pData[8];
+ TxMsg.Data[4]=pData[9];
+ TxMsg.Data[5]=pData[10];
+ TxMsg.Data[6]=pData[11];
+ TxMsg.Data[7]=pData[12];
+ CAN_SendData(&TxMsg);
+
+ TxMsg.ExtId=GetCANID(DeviceID,RFID_S50_CMD_ReadCard,0x03);
+ TxMsg.DLC=8;
+ TxMsg.Data[0]=pData[13];
+ TxMsg.Data[1]=pData[14];
+ TxMsg.Data[2]=pData[15];
+ TxMsg.Data[3]=pData[16];
+ TxMsg.Data[4]=pData[17];
+ TxMsg.Data[5]=pData[18];
+ TxMsg.Data[6]=pData[19];
+ TxMsg.Data[7]=pData[20];
+ CAN_SendData(&TxMsg);
+ }
+ }
+
+ break;
+ case 5: //д
+ {
+ //дɹ modified by Hy 2019-10-20
+ isWrite=true;
+ ReadCard(RFID_S50_CheckedBlockID);
+ }
+ break;
+
+ case 8: //ֹIC
+ {
+ uint32_t m_id=GetCANID(DeviceID,RFID_S50_CMD_Stop,0x01);
+ //سɹϢ
+ CAN_SendResult(m_id,0x00);
+ }
+ break;
+ }
+ }
+ else
+ {
+ //ʧ
+ CanTxMsg TxMsg;
+ TxMsg.RTR = CAN_RTR_DATA; // Ϊ֡
+ TxMsg.IDE = CAN_ID_EXT; // ʹչ֡
+ switch (m_Command)
+ {
+ case 4: //ݿ鷵
+ {
+ //ȡCANID
+ TxMsg.ExtId=GetCANID(DeviceID,RFID_S50_CMD_ReadCard,0x01);
+ TxMsg.DLC=3;
+ TxMsg.Data[0]=0x01;
+ TxMsg.Data[1]=pData[3];
+ TxMsg.Data[2]=pData[4];
+ CAN_SendData(&TxMsg);
+ }
+
+ }
+
+ }
+ }//У
+ }
+ else
+ {
+ //ַȷ践
+ RFID_S50_Reset();
+ }
+
+}
+
+//յ
+void RFID_S50_OnData(uint8_t * m_buf,int m_len)
+{
+ int m_idx=0;
+ uint8_t temp;
+ for (m_idx=0;m_idxCommandID)
+ {
+ case RFID_S50_CMD_Parameter: //0x14 ôڲ
+ {
+ RFID_S50_Reset();
+ RFID_S50_Para.Times=1; //óʱʱ
+ RFID_S50_Para.CommPara.USARTID =RxMsg->Value[0]; //ں
+ RFID_S50_Para.CommPara.BaudRate =RxMsg->Value[1]; //
+ RFID_S50_Para.CommPara.WordLength =RxMsg->Value[2]; //λ
+ RFID_S50_Para.CommPara.StopBits =RxMsg->Value[3]; //ֹͣλ
+ RFID_S50_Para.CommPara.Parity =RxMsg->Value[4]; //Уλ
+ RFID_S50_Para.Type =RxMsg->Value[5]; //
+ iTemp=GetCANID(DeviceID,0x14,0x01);
+ CAN_SendResult(iTemp,00);
+ bResult=true;
+ }
+ break;
+
+ case RFID_S50_CMD_Control: //0x15 豸
+ {
+ if (RxMsg->Value[0]==1)
+ {
+ //豸
+ //1
+ //2ǰ豸պҽӵ
+ uint32_t tmp_BaudRate=GetBaudRate(RFID_S50_Para.CommPara.BaudRate);
+ uint16_t tmp_Parity =GetParity(RFID_S50_Para.CommPara.Parity);
+
+ Usart_Open(RFID_S50_Para.CommPara.USARTID,tmp_BaudRate,RFID_S50_Para.CommPara.WordLength,RFID_S50_Para.CommPara.StopBits,tmp_Parity);
+ SetDeviceOnData(RFID_S50_Para.CommPara.USARTID,RFID_S50_OnData);
+ SetDeviceProcess(RFID_S50_Para.CommPara.USARTID,RFID_S50_Process);
+
+ //TIM2_Configuration(Weight_Times*2000); //ʱ2
+
+ //TIM_Cmd(TIM2, ENABLE); //ʱʱ
+
+ iTemp=GetCANID(DeviceID,RFID_S50_CMD_Control,0x01);
+ CAN_SendResult(iTemp,00);
+
+
+ RFID_S50_Para.Open=true;
+
+ }
+ else if (RxMsg->Value[0]==0)
+ {
+ //ر豸
+ }
+ bResult=true;
+ }
+ break;
+
+ case RFID_S50_CMD_Beep: //
+ {
+ uint16_t crcResult=0;
+ uint8_t crcL=0;
+ uint8_t crcH=0;
+ uint8_t m_buf[6]={0};
+
+ if (!RFID_S50_Para.Open)
+ return false;
+
+
+ m_buf[0] = 0x05; //
+ m_buf[1] = 0x01; //ַ
+ m_buf[2] = 0x01; //
+ m_buf[3] = 0x0F; //ʱ
+ crcResult = CRC16(m_buf, 4);
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+ m_buf[4] = crcH; //0xBC
+ m_buf[5] = crcL; //0x10
+ Usart_SendData(RFID_S50_Para.CommPara.USARTID,m_buf,6);
+ bResult=true;
+ }
+ break;
+
+ case RFID_S50_CMD_Password : // 22 0x16
+ {
+ uint16_t crcResult=0;
+ uint8_t crcL=0;
+ uint8_t crcH=0;
+ uint8_t m_buf[13]={0};
+ m_buf[0] = 0x0C; //
+ m_buf[1] = 0x01; //ַ
+ m_buf[2] = 0x03; //
+ memcpy(m_buf+3,RxMsg->Value,8); //CAN8ֽ
+
+ crcResult = CRC16(m_buf,11);
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+ m_buf[11] = crcH;
+ m_buf[12] = crcL;
+ Usart_SendData(RFID_S50_Para.CommPara.USARTID,m_buf,13);
+ bResult=true;
+ }
+ break;
+ case RFID_S50_CMD_FindCard : // 23 ԶѰ 0x18
+ {
+ uint16_t crcResult=0;
+ uint8_t crcL=0;
+ uint8_t crcH=0;
+ uint8_t m_buf[5]={0};
+
+ if (!RFID_S50_Para.Open)
+ return false;
+
+ m_buf[0] = 0x04; //
+ m_buf[1] = 0x01; //ַ
+ m_buf[2] = 0x02; // Ѱ
+ crcResult = CRC16(m_buf, 3);
+
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+ m_buf[3] = crcH;
+ m_buf[4] = crcL;
+ Usart_SendData(RFID_S50_Para.CommPara.USARTID,m_buf,5);
+ bResult=true;
+ }
+ break;
+ case RFID_S50_CMD_ReadCard : // 24 0x19
+ {
+ uint16_t crcResult=0;
+ uint8_t crcL=0;
+ uint8_t crcH=0;
+ uint8_t m_buf[6]={0};
+
+ if (!RFID_S50_Para.Open)
+ return false;
+
+ m_buf[0] = 0x05; //
+ m_buf[1] = 0x01; //ַ
+ m_buf[2] = 0x04; //
+ m_buf[3] = RxMsg->Value[0]; //
+ crcResult = CRC16(m_buf, 4);
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+ m_buf[4] = crcH;
+ m_buf[5] = crcL;
+ Usart_SendData(RFID_S50_Para.CommPara.USARTID,m_buf,6);
+ bResult=true;
+ }
+ break;
+ case RFID_S50_CMD_WriteCard : // 25 д 0x19
+ {
+ if (RxMsg->BlockID==1)
+ {
+ //һ
+ RFID_S50_ProcessData[0]=RxMsg->Value[0];
+ RFID_S50_CheckedBlockID=RxMsg->Value[0];
+ }
+ else if (RxMsg->BlockID==2)
+ {
+ //ڶ
+ memcpy(RFID_S50_ProcessData+1,RxMsg->Value,8);
+
+ }
+ else if (RxMsg->BlockID==3)
+ {
+ //
+ uint16_t crcResult=0;
+ uint8_t crcL=0;
+ uint8_t crcH=0;
+ uint8_t m_buf[22]={0};
+
+ if (!RFID_S50_Para.Open)
+ return false;
+
+ memcpy(RFID_S50_ProcessData+9,RxMsg->Value,8);
+
+ m_buf[0] = 0x15; //
+ m_buf[1] = 0x01; //ַ
+ m_buf[2] = 0x05; //
+
+ memcpy(m_buf+3,RFID_S50_ProcessData,17); //CAN17ֽ
+ crcResult = CRC16(m_buf,20);
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+ m_buf[20] = crcH;
+ m_buf[21] = crcL;
+ Usart_SendData(RFID_S50_Para.CommPara.USARTID,m_buf,22);
+ //дʱ modified by Hy 2019-10-20
+ memcpy(RFID_S50_CheckedData,RFID_S50_ProcessData+1,16);
+ }
+ bResult=true;
+ }
+ break;
+
+ case RFID_S50_CMD_Stop: //ֹ
+ {
+ uint16_t crcResult=0;
+ uint8_t crcL=0;
+ uint8_t crcH=0;
+ uint8_t m_buf[5]={0};
+
+ if (!RFID_S50_Para.Open)
+ return false;
+
+ m_buf[0] = 0x04; //
+ m_buf[1] = 0x01; //ַ
+ m_buf[2] = 0x08; //
+ crcResult = CRC16(m_buf, 3);
+
+ crcL = (uint8_t)(crcResult & 0xFF);
+ crcH = (uint8_t)(crcResult >> 8);
+ m_buf[3] = crcH;
+ m_buf[4] = crcL;
+ Usart_SendData(RFID_S50_Para.CommPara.USARTID,m_buf,5);
+ bResult=true;
+ }
+ break;
+ case RFID_S50_CMD_Reset:
+ {
+ uint32_t m_id=GetCANID(DeviceID,RFID_S50_CMD_Reset,0x01);
+ //سɹϢ
+ CAN_SendResult(m_id,0x00);
+ RFID_S50_Reset();
+ bResult=true;
+ }
+ break;
+ }
+ return bResult;
+}
+
+// void TIM3_IRQHandler(void)
+// {
+// if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
+// {
+// TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
+
+// }
+// }
+
+//λ
+void RFID_S50_Reset()
+{
+ RFID_S50_Para.IndexFlag=0;
+}
+
+
+#endif
+
diff --git a/S99appinit b/S99appinit
new file mode 100644
index 0000000..3c9cc20
--- /dev/null
+++ b/S99appinit
@@ -0,0 +1,78 @@
+#! /bin/sh
+
+# Load default env variables from profiles(e.g. /etc/profile.d/*.sh)
+. /etc/profile
+
+start_app()
+{
+ # Wait for weston ready, 5 seconds timeout
+ counter=0
+ while [ ! -e "${XDG_RUNTIME_DIR}/wayland-0" ] && [ $counter -lt 50 ]; do
+ sleep 0.1
+ counter=$((counter + 1))
+ done
+
+ if wait_for_network; then
+
+ killall weston 2>/dev/null || true
+ sleep 0.5
+ /userdata/auseft/WeighUI --domain 13 > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/device-daemon > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/Core --domain 13 > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/IoCtrl --device gpio --device_id 1 --domain 13 > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/HttpServer --domain 13 --port 8081 > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/Print --domain 13 --port ttyS2 > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/MqttDds --domain 13 --addr ws://10.180.4.1:8083 --user auseft --password 1q2w3E** > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/Led --domain 13 --type 1 --addr 192.168.6.147 > /dev/null 2>&1 &
+ sleep 0.5
+ /userdata/auseft/ReadCard --domain 13 > /dev/null 2>&1 &
+ else
+ echo "network failed."
+ fi
+}
+
+wait_for_network()
+{
+ local interface="eth0"
+ local retries=50
+ local count=0
+
+ echo "wait network $interface start..."
+
+ while [ $count -lt $retries ]; do
+ if ip link show $interface | grep -q "state UP"; then
+ echo "$interface started."
+ return 0
+ fi
+ sleep 1
+ count=$((count + 1))
+ done
+
+ echo "network $interface start failed, retry $retries times."
+ return 1
+}
+
+case $1 in
+ start)
+ #sh /oem/RkLunch.sh
+ ip link set can0 type can bitrate 500000 dbitrate 1000000 fd on
+ ip link set up can0
+ echo 34 > /sys/class/gpio/export
+ echo out > /sys/class/gpio/gpio34/direction
+ echo 1 > /sys/class/gpio/gpio34/value
+# start_app
+ ;;
+ stop)
+ #sh /oem/RkLunch-stop.sh
+ ;;
+ *)
+ echo "Usage: $0 {start|stop}"
+ ;;
+esac
diff --git a/common/CanMsgHandler.cxx b/common/CanMsgHandler.cxx
index 0b434b9..d995b6b 100644
--- a/common/CanMsgHandler.cxx
+++ b/common/CanMsgHandler.cxx
@@ -83,6 +83,8 @@ bool CanMsgHandler::OpenPort(const std::string& port, const std::string& baudrat
// return false;
// }
+
+
return true;
}
diff --git a/common/SerialMsgHandler.cxx b/common/SerialMsgHandler.cxx
index 0c698cd..1178584 100644
--- a/common/SerialMsgHandler.cxx
+++ b/common/SerialMsgHandler.cxx
@@ -23,6 +23,8 @@ bool SerialMsgHandler::OpenPort(const std::string &port, const std::string &baud
ClosePort();
+
+
fd = open(tty.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
@@ -51,16 +53,31 @@ bool SerialMsgHandler::OpenPort(const std::string &port, const std::string &baud
if (baudrate == "115200")
{
baund = B115200;
+
}
else if (baudrate == "9600")
{
baund = B9600;
+
+ }
+ else if (baudrate == "19200")
+ {
+ baund = B19200;
+ }
+ else if (baudrate == "57600")
+ {
+ baund = B57600;
}
else
{
baund = B9600;
+
}
+ // ========== 新增:保存波特率 ==========
+ baudrate_ = baund;
+
+
return setPortAttributes(baund);
}
@@ -69,6 +86,10 @@ bool SerialMsgHandler::setPortAttributes(int baudrate)
{
struct termios options;
+ // ========== 新增:调试打印配置前的状态 ==========
+ std::cout << "[DEBUG] setPortAttributes: configuring port with baudrate=" << baudrate << std::endl;
+
+
// 获取当前串口设置
if (tcgetattr(fd, &options) != 0)
{
@@ -116,3 +137,17 @@ bool SerialMsgHandler::setPortAttributes(int baudrate)
return true;
}
+
+// ========== 新增:刷新串口配置 ==========
+bool SerialMsgHandler::refreshPort()
+{
+ if (fd == -1) {
+ std::cout << "[DEBUG] refreshPort: fd is -1, skip" << std::endl;
+ return false;
+ }
+
+ // ========== 调试打印 ==========
+ std::cout << "[DEBUG] refreshPort: reconfiguring port, baudrate=" << baudrate_ << std::endl;
+
+ return setPortAttributes(baudrate_);
+}
\ No newline at end of file
diff --git a/common/SerialMsgHandler.hpp b/common/SerialMsgHandler.hpp
index 9e485c4..34dfe08 100644
--- a/common/SerialMsgHandler.hpp
+++ b/common/SerialMsgHandler.hpp
@@ -3,6 +3,8 @@
#include
#include
+#include
+#include
#include "MsgHandler.hpp"
@@ -18,7 +20,11 @@ public:
// 设置串口参数
bool setPortAttributes(int baudrate);
+ bool refreshPort();
+
private:
+
+ speed_t baudrate_; // 新增:保存波特率(speed_t 类型)
};
#endif // _SERIALMSGHANDLER_HPP_
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..7f297e0
--- /dev/null
+++ b/config.json
@@ -0,0 +1,89 @@
+{
+ "dds":
+ {
+ "domain": 0
+ },
+ "mqtt":
+ {
+ "server_url": "mqtt://192.168.1.2:1883",
+ "client_id": "ddsmqtt_sub_pub_0",
+ "username": "admin",
+ "password": "admin",
+ "sub_topic": ["command"],
+ "sub_qos": [0],
+ "pub_topic": ["response"],
+ "pub_qos": [0]
+ },
+ "httpserver":
+ {
+ "port": 8080
+ },
+ "ioctrl":
+ {
+ "bus": "gpio",
+ "device": "gpio",
+ "iomap": {
+ "out": {
+ "frontbarrup": [48, 0],
+ "frontbardown": [49, 0]
+ },
+ "in": {
+ "frontdetect": [5, 1]
+ }
+ }
+ },
+ "led":
+ {
+ "ip": "192.168.0.199",
+ "port": 80,
+ "path": "/home/bo/project/app/dds/led/build/"
+ },
+ "print":
+ {
+ "bus": "serial",
+ "port": "ttyS2",
+ "baudrate": "9600",
+ "device": "NP80A"
+ },
+ "readcard":
+ {
+ "bus": "serial",
+ "port": "ttyS1",
+ "baudrate": "9600",
+ "device": "RC522",
+ "password":
+ [
+ {
+ "sector": 1,
+ "data": [1, 2, 3, 4, 5, 6]
+ },
+ {
+ "sector": 2,
+ "data": [7, 8, 9, 10, 11, 12]
+ },
+ {
+ "sector": 3,
+ "data": [13, 14, 15, 16, 17, 18]
+ },
+ {
+ "sector": 4,
+ "data": [19, 20, 21, 22, 23, 24]
+ },
+ {
+ "sector": 5,
+ "data": [25, 26, 27, 28, 29, 30]
+ },
+ {
+ "sector": 10,
+ "data": [177, 10, 35, 209, 143, 32]
+ }
+ ]
+ },
+ "weigh":
+ {
+ "bus": "serial",
+ "port": "ttyS5",
+ "baudrate": "9600",
+ "device": "Keli"
+ }
+}
\ No newline at end of file
diff --git a/core/Publisher.cxx b/core/Publisher.cxx
index 8254960..d3cea79 100644
--- a/core/Publisher.cxx
+++ b/core/Publisher.cxx
@@ -24,7 +24,10 @@
#include
#include
#include
+#include
+#include
#include
+#include // 新增:用于 std::fabs
#include
#include
@@ -33,10 +36,11 @@
#include
#include
-#include "SystemPubSubTypes.hpp"
+#include "WeighingDDSTypePubSubTypes.hpp"
#include "msg.hpp"
#include "DEBUG.hpp"
+
using namespace eprosima::fastdds::dds;
PublisherApp::PublisherApp(
@@ -55,13 +59,11 @@ PublisherApp::PublisherApp(
, summary_type_(new WeighingSystem::SummaryUpdatePubSubType())
, print_topic_(nullptr)
, print_writer_(nullptr)
- , print_type_(new InternalSystem::PrintReqPubSubType())
+ , print_type_(new WeighingSystem::PrintReqPubSubType())
, matched_(0)
, samples_sent_(0)
, stop_(false)
{
- //
-
// Create the participant
DomainParticipantQos pqos = PARTICIPANT_QOS_DEFAULT;
pqos.name("Core_pub_participant");
@@ -319,7 +321,7 @@ bool PublisherApp::light_ctrl(const std::map& ctrl)
bool PublisherApp::print_receipt(const std::map& msg)
{
- InternalSystem::PrintReq req;
+ WeighingSystem::PrintReq req;
req.msg() = msg;
@@ -333,163 +335,60 @@ bool PublisherApp::print_receipt(const std::map& msg)
return true;
}
-#define WEIGH_IDLE 0
-#define WEIGH_LIC 1
-#define WEIGH_STABLE1 2
-#define WEIGH_STABLE2 3
-#define WEIGH_SEND 4
-#define WEIGH_PRINT 5
-#define WEIGH_ERROR 6
-#define WEIGH_LEAVE 7
+#define WEIGH_IDLE 0
+#define WEIGH_QUEUE_RAISED 1 // 已抬杆,计时等 60s 落杆
void PublisherApp::run()
{
- std::string license_no;
- float stable_weight = 0;
- float stable_weight1 = 0;
- float stable_weight2 = 0;
int weigh_state = WEIGH_IDLE;
while (!is_stopped())
{
+ // 1) 消费 DDS 队列
std::unique_lock dds_lock(DdsMsgData::queue_cv_mtx_, std::try_to_lock);
if (dds_lock.owns_lock())
{
- if (!DdsMsgData::LicenseSnapUpdate_queue_.empty())
+ if (!DdsMsgData::QueueSuccess_queue_.empty())
{
- WeighingSystem::LicenseSnapUpdate info = std::move(DdsMsgData::LicenseSnapUpdate_queue_.front());
- DdsMsgData::LicenseSnapUpdate_queue_.pop();
+ Queue::QueueSuccess info = std::move(DdsMsgData::QueueSuccess_queue_.front());
+ DdsMsgData::QueueSuccess_queue_.pop();
dds_lock.unlock();
- DEBUG("车牌: " << info.License());
- DEBUG("类型: " << info.NewTag());
-
- if (license_no.empty() == true)
- {
- license_no = info.License();
- weigh_state = WEIGH_LIC;
- }
- }
- else if (!DdsMsgData::ScaleInfo_queue_.empty())
- {
- WeighingSystem::ScaleInfo info = std::move(DdsMsgData::ScaleInfo_queue_.front());
- DdsMsgData::ScaleInfo_queue_.pop();
- dds_lock.unlock();
+ DEBUG("==== QueueSuccess received, raising front bar ====");
+ DEBUG(" message_id = " << info.message_id());
+ DEBUG(" card_number = " << info.card_number());
+ DEBUG(" device_id = " << info.device_id());
- DEBUG("有车: " << info.HasVehicle());
- DEBUG("稳定: " << info.WeightOK());
- DEBUG("设备状态: " << info.State());
- DEBUG("实时重量: " << info.Value());
- DEBUG("稳定重量: " << info.StableValue());
-
- if (info.WeightOK() == true)
- {
- stable_weight = info.StableValue();
- }
- else
- {
- stable_weight = 0;
- }
-
- if (info.HasVehicle() == 0)
- {
- license_no.clear();
- if (weigh_state == WEIGH_LEAVE)
- {
- std::this_thread::sleep_for(std::chrono::seconds(5));
- std::map ctrl;
- ctrl["FrontBar"] = "down";
- bar_ctrl(ctrl);
- weigh_state = WEIGH_IDLE;
- }
- }
- }
- else if (!DdsMsgData::BarUpdate_queue_.empty())
- {
- WeighingSystem::BarUpdate info = std::move(DdsMsgData::BarUpdate_queue_.front());
- DdsMsgData::BarUpdate_queue_.pop();
- dds_lock.unlock();
-
- DEBUG("前拦车器状态: " << info.FrontBarState());
- DEBUG("后拦车器状态: " << info.BackBarState());
- }
- else if (!DdsMsgData::LightsUpdate_queue_.empty())
- {
- WeighingSystem::LightsUpdate info = std::move(DdsMsgData::LightsUpdate_queue_.front());
- DdsMsgData::LightsUpdate_queue_.pop();
- dds_lock.unlock();
-
- DEBUG("前红绿灯状态: " << info.FrontLEDState());
- DEBUG("后红绿灯状态: " << info.BackLEDState());
- }
- else if (!DdsMsgData::InfraredUpdate_queue_.empty())
- {
- WeighingSystem::InfraredUpdate info = std::move(DdsMsgData::InfraredUpdate_queue_.front());
- DdsMsgData::InfraredUpdate_queue_.pop();
- dds_lock.unlock();
+ // 抬前拦车器
+ std::map ctrl;
+ ctrl["FrontBar"] = "up";
+ bar_ctrl(ctrl);
- DEBUG("前红外对射状态: " << info.FrontResistanceSignal());
- DEBUG("后红外对射状态: " << info.BackResistanceSignal());
- }
- else if (!DdsMsgData::WeightInfoOk_queue_.empty())
- {
- WeighingSystem::WeightInfoOk info = std::move(DdsMsgData::WeightInfoOk_queue_.front());
- DdsMsgData::WeightInfoOk_queue_.pop();
- dds_lock.unlock();
+ // 抬后拦车器
+ // std::map ctrl;
+ // ctrl["BackBar"] = "up";
+ // bar_ctrl(ctrl);
- auto formatFloat = [](float value) -> std::string
- {
- std::ostringstream oss;
- oss << std::fixed << std::setprecision(0) << value;
- return oss.str();
- };
- if (info.IsPrintTicker() == true)
+ // 收到 QueueSuccess 后下发"排队票"打印任务(仅打一次)
+ // 字段映射:QueueSuccess → Print1_3 期望的 map key
{
std::map print_msg;
-
- print_msg["Title"] = "五彩湾";
- print_msg["GrossDeviceID"] = std::to_string(info.GrossDeviceID());
- print_msg["GrossDeviceName"] = info.GrossDeviceName();
- print_msg["TareDeviceID"] = std::to_string(info.TareDeviceID());
- print_msg["TareDeviceName"] = info.TareDeviceName();
- print_msg["TitleCorp"] = info.EnterpriseName();
- print_msg["CoalNumber"] = info.BillNumber();
- print_msg["CarNumber"] = info.CarNumber();
- print_msg["Supplier"] = info.Supplier();
- print_msg["GoodsType"] = info.GoodsType();
- print_msg["GrossWeight"] = formatFloat(info.GrossWeight());
- print_msg["GrossTime"] = info.GrossTime();
- print_msg["GrossOperater"] = info.GrossOperater();
- print_msg["TareWeight"] = formatFloat(info.Tare());
- print_msg["TareTime"] = info.TareTime();
- print_msg["TareOperater"] = info.TareOperater();
- print_msg["SuttleWeight"] = formatFloat(info.Suttle());
- print_msg["duduction1"] = formatFloat(info.duduction1());
- print_msg["duduction2"] = formatFloat(info.duduction2());
- print_msg["duduction3"] = formatFloat(info.duduction3());
- print_msg["INCoalYard"] = info.INCoalYard();
- print_msg["OUTCoalYard"] = info.OutCoalYard();
- print_msg["BatchNumber"] = info.BatchNumber();
- print_msg["Warning"] = info.Warning();
- print_msg["Tips"] = info.Tips();
- print_msg["TicketType"] = info.TicketType();
-
+ print_msg["Title"] = "排队票"; // 触发 print/MsgHandler2.cxx::Print1_3
+ print_msg["CarNumber"] = info.vehicle_number(); // 车牌号
+ print_msg["DateTime"] = info.queue_time(); // 时间
+ print_msg["QueueID"] = std::to_string(info.queue_number()); // 排队号 (long→string)
+ print_msg["Supplier"] = std::to_string(info.sample_code()); // 采样编码
+ print_msg["GoodsType"] = info.goods_name(); // 品种
+ print_msg["sample_machine"] = info.sample_machine(); // 采样机名称
+ print_msg["CoalYard"] = ""; // 煤场:缺省为空(冒号后无内容)
print_receipt(print_msg);
- std::this_thread::sleep_for(std::chrono::seconds(1));
}
- weigh_state = WEIGH_LEAVE;
- std::map ctrl;
- ctrl["FrontBar"] = "up";
- bar_ctrl(ctrl);
- }
- else if (!DdsMsgData::WeightInfoError_queue_.empty())
- {
- WeighingSystem::WeightInfoError info = std::move(DdsMsgData::WeightInfoError_queue_.front());
- DdsMsgData::WeightInfoError_queue_.pop();
- dds_lock.unlock();
- weigh_state = WEIGH_ERROR;
+ // 记录抬杆时刻,开始 60s 倒计时
+ queue_success_time_ = std::chrono::steady_clock::now();
+ queue_success_pending_ = true;
+ weigh_state = WEIGH_QUEUE_RAISED;
}
else
{
@@ -497,69 +396,41 @@ void PublisherApp::run()
}
}
- // logic
+ // 2) 状态机
switch (weigh_state)
{
- case WEIGH_IDLE:
- break;
- case WEIGH_LIC:
- if ((stable_weight != 0) && (license_no.empty() != true))
- {
- DEBUG("stable_weight1 " << stable_weight);
- DEBUG("license_no " << license_no);
- stable_weight1 = stable_weight;
- weigh_state = WEIGH_STABLE1;
- }
- break;
- case WEIGH_STABLE1:
- if (stable_weight == 0)
- {
- DEBUG("weigh1 clear");
- weigh_state = WEIGH_STABLE2;
- }
- break;
- case WEIGH_STABLE2:
- if ((stable_weight != 0) && (license_no.empty() != true))
- {
- DEBUG("license_no " << license_no);
- DEBUG("stable_weight2 " << stable_weight);
- stable_weight2 = stable_weight;
- if ((stable_weight1 - stable_weight2) > 45)
- {
- weigh_state = WEIGH_SEND;
- }
- else
- {
- DEBUG("stable_weight2 error");
- stable_weight1 = stable_weight;
- weigh_state = WEIGH_STABLE1;
- }
- }
- break;
- case WEIGH_SEND:
- DEBUG("send summary");
+ case WEIGH_IDLE:
+ break;
+
+ case WEIGH_QUEUE_RAISED:
+ if (queue_success_pending_)
+ {
+ auto elapsed = std::chrono::duration_cast(
+ std::chrono::steady_clock::now() - queue_success_time_).count();
+ if (elapsed >= 60)
{
- WeighingSystem::SummaryUpdate info;
- info.License() = license_no;
- info.StableValue() = stable_weight2;
- summary_writer_->write(&info);
+ DEBUG("60s elapsed after QueueSuccess, lowering front bar...");
+ std::map ctrl;
+ ctrl["FrontBar"] = "down";
+ bar_ctrl(ctrl);
+
+ // std::map ctrl;
+ // ctrl["BackBar"] = "down";
+ // bar_ctrl(ctrl);
+
+
+ queue_success_pending_ = false;
+ weigh_state = WEIGH_IDLE;
}
- weigh_state = WEIGH_PRINT;
- break;
- case WEIGH_PRINT:
- break;
- case WEIGH_ERROR:
- std::this_thread::sleep_for(std::chrono::seconds(3));
- weigh_state = WEIGH_STABLE2;
- break;
- case WEIGH_LEAVE:
- break;
- default:
- weigh_state = WEIGH_IDLE;
- break;
+ }
+ break;
+
+ default:
+ weigh_state = WEIGH_IDLE;
+ break;
}
-
- // Wait for period or stop event
+
+ // 3) 周期等待
std::unique_lock period_lock(mutex_);
cv_.wait_for(period_lock, std::chrono::milliseconds(period_ms_), [this]()
{
@@ -568,7 +439,6 @@ void PublisherApp::run()
}
}
-
bool PublisherApp::publish()
{
bool ret = false;
@@ -598,4 +468,4 @@ void PublisherApp::stop()
{
stop_.store(true);
cv_.notify_one();
-}
\ No newline at end of file
+}
diff --git a/core/Publisher.hpp b/core/Publisher.hpp
index 3e8fb28..cc8bfc3 100644
--- a/core/Publisher.hpp
+++ b/core/Publisher.hpp
@@ -23,6 +23,7 @@
#define FAST_DDS_GENERATED__PUBLISHERAPP_HPP
#include
+#include
#include
#include
@@ -82,6 +83,10 @@ private:
const uint32_t period_ms_ = 100; // in ms
uint16_t samples_sent_;
std::atomic stop_;
+
+ // ── QueueSuccess 抬杆/落杆计时 ──
+ std::chrono::steady_clock::time_point queue_success_time_;
+ bool queue_success_pending_ = false;
};
#endif // FAST_DDS_GENERATED__PUBLISHERAPP_HPP
\ No newline at end of file
diff --git a/core/Subscriber.cxx b/core/Subscriber.cxx
index 9cf04eb..f6c6313 100644
--- a/core/Subscriber.cxx
+++ b/core/Subscriber.cxx
@@ -28,17 +28,32 @@
#include
#include
#include
+
+#include
+#include
+#include "msg.hpp"
+
+// Static member definitions for DdsMsgData
+// (other queue/mutex members are already defined in core/main.cxx;
+// only QueueSuccess_queue_ is missing there)
+std::queue DdsMsgData::QueueSuccess_queue_;
#include
#include
#include
-#include "SystemPubSubTypes.hpp"
+#include "WeighingDDSTypePubSubTypes.hpp"
#include "msg.hpp"
#include "DEBUG.hpp"
using namespace eprosima::fastdds::dds;
+// 【新增】静态成员变量定义
+// std::mutex DdsMsgData::infrared_mtx_;
+// WeighingSystem::InfraredUpdate DdsMsgData::latest_infrared_;
+// std::atomic DdsMsgData::stop_flag_{false};
+
+
SubscriberApp::SubscriberApp(
const int& domain_id)
: factory_(nullptr)
@@ -68,6 +83,9 @@ SubscriberApp::SubscriberApp(
, weightinfoerror_topic_(nullptr)
, weightinfoerror_reader_(nullptr)
, weightinfoerror_type_(new WeighingSystem::WeightInfoErrorPubSubType())
+ , queuesuccess_topic_(nullptr)
+ , queuesuccess_reader_(nullptr)
+ , queuesuccess_type_(new Queue::QueueSuccessPubSubType())
, samples_received_(0)
, stop_(false)
{
@@ -92,6 +110,7 @@ SubscriberApp::SubscriberApp(
scaleinfo_type_.register_type(participant_);
weightinfook_type_.register_type(participant_);
weightinfoerror_type_.register_type(participant_);
+ queuesuccess_type_.register_type(participant_);
// Create the subscriber
SubscriberQos sub_qos = SUBSCRIBER_QOS_DEFAULT;
@@ -317,6 +336,33 @@ SubscriberApp::SubscriberApp(
{
throw std::runtime_error("WeighingSystem::WeightInfoError DataReader initialization failed");
}
+
+ // Create the topic
+ topic_qos = TOPIC_QOS_DEFAULT;
+ participant_->get_default_topic_qos(topic_qos);
+ queuesuccess_topic_ = participant_->create_topic("QueueSuccess", queuesuccess_type_.get_type_name(), topic_qos);
+ if (queuesuccess_topic_ == nullptr)
+ {
+ throw std::runtime_error("Queue::QueueSuccess Topic initialization failed");
+ }
+
+ // Create the reader
+ reader_qos = DATAREADER_QOS_DEFAULT;
+ subscriber_->get_default_datareader_qos(reader_qos);
+ reader_qos.reliability().kind = ReliabilityQosPolicyKind::RELIABLE_RELIABILITY_QOS;
+ reader_qos.reliability().max_blocking_time = Duration_t(1, 0);
+ reader_qos.durability().kind = DurabilityQosPolicyKind::VOLATILE_DURABILITY_QOS;
+ reader_qos.history().kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
+ reader_qos.history().depth = 1;
+ reader_qos.resource_limits().max_samples = 200;
+ reader_qos.resource_limits().max_instances = 1;
+ reader_qos.resource_limits().max_samples_per_instance = 100;
+ reader_qos.data_sharing().off();
+ queuesuccess_reader_ = subscriber_->create_datareader(queuesuccess_topic_, reader_qos, this, StatusMask::all());
+ if (queuesuccess_reader_ == nullptr)
+ {
+ throw std::runtime_error("Queue::QueueSuccess DataReader initialization failed");
+ }
}
SubscriberApp::~SubscriberApp()
@@ -383,6 +429,7 @@ void SubscriberApp::on_data_available(
DdsMsgData::LightsUpdate_queue_.push(std::move(sample_));
lock.unlock();
}
+
}
}
}
@@ -398,6 +445,11 @@ void SubscriberApp::on_data_available(
DdsMsgData::InfraredUpdate_queue_.push(std::move(sample_));
lock.unlock();
}
+ // // 【新增】保存最新红外对射状态
+ // {
+ // std::lock_guard lock(DdsMsgData::infrared_mtx_);
+ // DdsMsgData::latest_infrared_ = sample_;
+ // }
}
}
}
@@ -476,6 +528,21 @@ void SubscriberApp::on_data_available(
}
}
}
+ else if (topic_name == "QueueSuccess")
+ {
+ Queue::QueueSuccess sample_;
+ while ((!is_stopped()) && (RETCODE_OK == reader->take_next_sample(&sample_, &info)))
+ {
+ if ((info.instance_state == ALIVE_INSTANCE_STATE) && info.valid_data)
+ {
+ {
+ std::unique_lock lock(DdsMsgData::queue_cv_mtx_);
+ DdsMsgData::QueueSuccess_queue_.push(std::move(sample_));
+ lock.unlock();
+ }
+ }
+ }
+ }
}
void SubscriberApp::run()
@@ -498,4 +565,4 @@ void SubscriberApp::stop()
{
stop_.store(true);
terminate_cv_.notify_all();
-}
\ No newline at end of file
+}
diff --git a/core/Subscriber.hpp b/core/Subscriber.hpp
index 669b2cf..d860d12 100644
--- a/core/Subscriber.hpp
+++ b/core/Subscriber.hpp
@@ -29,7 +29,7 @@
#include
#include
-#include "System.hpp"
+#include "WeighingDDSType.hpp"
class SubscriberApp : public eprosima::fastdds::dds::DataReaderListener
{
@@ -87,6 +87,10 @@ private:
eprosima::fastdds::dds::Topic* weightinfoerror_topic_;
eprosima::fastdds::dds::DataReader* weightinfoerror_reader_;
eprosima::fastdds::dds::TypeSupport weightinfoerror_type_;
+ // 【新增】QueueSuccess 订阅相关
+ eprosima::fastdds::dds::Topic* queuesuccess_topic_;
+ eprosima::fastdds::dds::DataReader* queuesuccess_reader_;
+ eprosima::fastdds::dds::TypeSupport queuesuccess_type_;
uint16_t samples_received_;
std::atomic stop_;
uint32_t period_ms_ = 100; // in ms
@@ -94,4 +98,4 @@ private:
std::condition_variable terminate_cv_;
};
-#endif // FAST_DDS_GENERATED__SUBSCRIBERAPP_HPP
\ No newline at end of file
+#endif // FAST_DDS_GENERATED__SUBSCRIBERAPP_HPP
diff --git a/core/msg.hpp b/core/msg.hpp
index f93a94f..5c9bbf1 100644
--- a/core/msg.hpp
+++ b/core/msg.hpp
@@ -3,10 +3,17 @@
#include
#include
-#include "System.hpp"
+#include "WeighingDDSType.hpp"
+#include
class DdsMsgData {
public:
+
+ // 【修改】红外对射最新状态存储(放在最前面,保持正确缩进)
+ // static std::mutex infrared_mtx_;
+ // static WeighingSystem::InfraredUpdate latest_infrared_;
+ // static std::atomic stop_flag_;
+
static std::queue BarUpdate_queue_;
static std::queue LightsUpdate_queue_;
static std::queue InfraredUpdate_queue_;
@@ -15,7 +22,10 @@ public:
static std::queue ScaleInfo_queue_;
static std::queue WeightInfoOk_queue_;
static std::queue WeightInfoError_queue_;
+ static std::queue QueueSuccess_queue_;
static std::mutex queue_cv_mtx_;
+
+
};
-#endif
\ No newline at end of file
+#endif
diff --git a/demo/Publisher.cxx b/demo/Publisher.cxx
index 7045623..72f9b46 100644
--- a/demo/Publisher.cxx
+++ b/demo/Publisher.cxx
@@ -33,7 +33,7 @@
#include
#include
-#include "SystemPubSubTypes.hpp"
+#include "WeighingDDSTypePubSubTypes.hpp"
using namespace eprosima::fastdds::dds;
@@ -44,7 +44,7 @@ PublisherApp::PublisherApp(
, publisher_(nullptr)
, topic_(nullptr)
, writer_(nullptr)
- , type_(new WeighRspPubSubType())
+ , type_(new WeighingSystem::ScaleInfoPubSubType())
, matched_(0)
, samples_sent_(0)
, stop_(false)
@@ -169,7 +169,7 @@ bool PublisherApp::publish()
if (!is_stopped())
{
/* Initialize your structure here */
- WeighRsp sample_;
+ WeighingSystem::ScaleInfo sample_;
ret = (RETCODE_OK == writer_->write(&sample_));
}
return ret;
@@ -184,4 +184,4 @@ void PublisherApp::stop()
{
stop_.store(true);
cv_.notify_one();
-}
\ No newline at end of file
+}
diff --git a/demo/Subscriber.cxx b/demo/Subscriber.cxx
index bc10fe1..7d7bf4e 100644
--- a/demo/Subscriber.cxx
+++ b/demo/Subscriber.cxx
@@ -32,7 +32,7 @@
#include
#include
-#include "SystemPubSubTypes.hpp"
+#include "WeighingDDSTypePubSubTypes.hpp"
using namespace eprosima::fastdds::dds;
@@ -43,7 +43,7 @@ SubscriberApp::SubscriberApp(
, subscriber_(nullptr)
, topic_(nullptr)
, reader_(nullptr)
- , type_(new WeighReqPubSubType())
+ , type_(new WeighingSystem::ScaleInfoPubSubType())
, samples_received_(0)
, stop_(false)
{
@@ -127,7 +127,7 @@ void SubscriberApp::on_subscription_matched(
void SubscriberApp::on_data_available(
DataReader* reader)
{
- WeighRsp sample_;
+ WeighingSystem::ScaleInfo sample_;
SampleInfo info;
while ((!is_stopped()) && (RETCODE_OK == reader->take_next_sample(&sample_, &info)))
{
@@ -156,4 +156,4 @@ void SubscriberApp::stop()
{
stop_.store(true);
terminate_cv_.notify_all();
-}
\ No newline at end of file
+}
diff --git a/demo/Subscriber.hpp b/demo/Subscriber.hpp
index 81132dc..f6d8448 100644
--- a/demo/Subscriber.hpp
+++ b/demo/Subscriber.hpp
@@ -29,7 +29,7 @@
#include
#include
-#include "System.hpp"
+#include "WeighingDDSType.hpp"
class SubscriberApp : public eprosima::fastdds::dds::DataReaderListener
{
@@ -72,4 +72,4 @@ private:
std::condition_variable terminate_cv_;
};
-#endif // FAST_DDS_GENERATED__SUBSCRIBERAPP_HPP
\ No newline at end of file
+#endif // FAST_DDS_GENERATED__SUBSCRIBERAPP_HPP
diff --git a/fastddsgen.jar b/fastddsgen.jar
new file mode 100644
index 0000000..16ef944
Binary files /dev/null and b/fastddsgen.jar differ
diff --git a/gatectrl/Subscriber.cxx b/gatectrl/Subscriber.cxx
index 6eb439b..8f9904e 100644
--- a/gatectrl/Subscriber.cxx
+++ b/gatectrl/Subscriber.cxx
@@ -212,9 +212,22 @@ void SubscriberApp::run(std::shared_ptr handler)
{
if(!MsgData::BarCommandUpdate_queue_.empty())
{
+
WeighingSystem::BarCommandUpdate cmd = std::move(MsgData::BarCommandUpdate_queue_.front());
MsgData::BarCommandUpdate_queue_.pop();
lock.unlock();
+
+ // std::cout << "[DEBUG] DDS Received: "
+ // << "FrontBarSignalUp=" << cmd.FrontBarSignalUp() << ", "
+ // << "FrontBarSignalDown=" << cmd.FrontBarSignalDown() << ", "
+ // << "FrontBarEnable=" << cmd.FrontBarEnable() << ", "
+ // << "BackBarSignalUp=" << cmd.BackBarSignalUp() << ", "
+ // << "BackBarSignalDown=" << cmd.BackBarSignalDown() << ", "
+ // << "BackBarEnable=" << cmd.BackBarEnable()
+ // << std::endl;
+
+
+
std::vector port;
if (!std::filesystem::exists(getExeDir() / "frontbar.lock"))
{
diff --git a/gatectrl/main.cxx b/gatectrl/main.cxx
index d1f1e93..26407f4 100644
--- a/gatectrl/main.cxx
+++ b/gatectrl/main.cxx
@@ -34,6 +34,43 @@
#include "msg.hpp"
#include "DEBUG.hpp"
+
+// ── 拦车器测试函数 ──
+void bar_test(std::shared_ptr handler, const std::string& bar_name)
+{
+ DEBUG(bar_name + " test started...");
+
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+ DEBUG("3 seconds elapsed, raising " + bar_name + "...");
+
+ std::vector ports;
+ ports.push_back(bar_name + "BarUp");
+ handler->CtrlBar(ports);
+
+ // 等待 CtrlBar 内部所有消息发送完成
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+
+ DEBUG("5 seconds elapsed, lowering " + bar_name + "...");
+
+ ports.clear();
+ ports.push_back(bar_name + "BarDown");
+ handler->CtrlBar(ports);
+
+ DEBUG(bar_name + " test completed.");
+}
+
+void front_bar_test(std::shared_ptr handler)
+{
+ bar_test(handler, "Front");
+}
+
+void back_bar_test(std::shared_ptr handler)
+{
+ bar_test(handler, "Back");
+}
+
+
+
using eprosima::fastdds::dds::Log;
std::function stop_handler;
@@ -87,6 +124,14 @@ int main(int argc, char** argv)
{
domain_id = atoi(argv[++i]);
}
+ else if (strcmp(argv[i], "--test_front_bar") == 0)
+ {
+ // 启用前拦车器测试功能
+ }
+ else if (strcmp(argv[i], "--test_back_bar") == 0)
+ {
+ // 启用后拦车器测试功能
+ }
else if (strcmp(argv[i], "--interface") == 0 && i + 1 < argc)
{
interface = argv[++i];
@@ -122,7 +167,8 @@ int main(int argc, char** argv)
<< " --port Set port name (e.g., can0)\n"
<< " --device Set device name (e.g., 5serial)\n"
<< " --version Show software Version\n"
- << " --help Show this help message\n";
+ << " --help Show this help message\n"
+ << " --test_front_bar Test front bar (raise after 3s, lower after 3s)\n";
return EXIT_SUCCESS;
}
else
@@ -136,7 +182,8 @@ int main(int argc, char** argv)
<< " --port Set port name (e.g., can0)\n"
<< " --device Set device name (e.g., 5serial)\n"
<< " --version Show software Version\n"
- << " --help Show this help message\n";
+ << " --help Show this help message\n"
+ << " --test_front_bar Test front bar (raise after 3s, lower after 3s)\n";
return EXIT_FAILURE;
}
}
@@ -149,6 +196,33 @@ int main(int argc, char** argv)
dev->device = device;
dev->device_id = device_id;
+
+ // ── 拦车器测试模式 ──
+ bool test_front_bar = false;
+ bool test_back_bar = false;
+ for (int i = 1; i < argc; i++)
+ {
+ if (strcmp(argv[i], "--test_front_bar") == 0)
+ {
+ test_front_bar = true;
+ }
+ else if (strcmp(argv[i], "--test_back_bar") == 0)
+ {
+ test_back_bar = true;
+ }
+ }
+
+ std::thread test_thread;
+ if (test_front_bar)
+ {
+ test_thread = std::thread(front_bar_test, dev);
+ }
+ else if (test_back_bar)
+ {
+ test_thread = std::thread(back_bar_test, dev);
+ }
+
+
std::thread sub_thread(&SubscriberApp::run, sub, dev);
std::thread pub_thread(&PublisherApp::run, pub, dev);
@@ -169,6 +243,11 @@ int main(int argc, char** argv)
signal(SIGHUP, signal_handler);
#endif // _WIN32
+ if (test_front_bar || test_back_bar)
+ {
+ test_thread.join();
+ }
+
sub_thread.join();
pub_thread.join();
diff --git a/httpserver/Publisher.cxx b/httpserver/Publisher.cxx
index 0b47d14..7ad7061 100644
--- a/httpserver/Publisher.cxx
+++ b/httpserver/Publisher.cxx
@@ -26,6 +26,7 @@
#include
#include
+
#include
#include
#include
@@ -154,6 +155,10 @@ void PublisherApp::run(std::shared_ptr handler)
if (handler->PostMsg.empty() != true)
{
+
+ std::cout << "[HTTPServer] 原始数据: " << handler->PostMsg << std::endl;
+
+
json j = json::parse(handler->PostMsg);
DEBUG("车牌: " << j["AlarmInfoPlate"]["result"]["PlateResult"]["license"]);
diff --git a/ioctrl/MsgHandler.cxx b/ioctrl/MsgHandler.cxx
index 5f255cc..85343ce 100644
--- a/ioctrl/MsgHandler.cxx
+++ b/ioctrl/MsgHandler.cxx
@@ -4,179 +4,64 @@
#include
#include
#include
+#include // for O_WRONLY
+#include
#include "MsgHandler.hpp"
MsgHandler::MsgHandler() : fd(-1) {}
-void MsgHandler::HandleDdsMsg(const std::map& msg)
-{
- auto cmd = msg.find("cmd");
-
- if (cmd != msg.end())
- {
- if (cmd->second == "config")
- {
- auto port = msg.find("port");
- auto baudrate = msg.find("baudrate");
- auto device = msg.find("device");
- if ((port != msg.end()) && (baudrate != msg.end()) && (device != msg.end()))
- {
- OpenPort(port->second, baudrate->second);
- this->device = device->second;
- }
- }
- else if (cmd->second == "open")
- {
- if (this->device == "5serial")
- {
- std::vector data;
- data.insert(data.end(), {this->device_id, 0x50, 1, 1});
- SendDeviceMsg(data);
- }
- }
- else if (cmd->second == "write")
- {
- if (this->device == "5serial")
- {
- std::vector data;
- data.resize(8, 1);
- data.insert(data.begin(), {this->device_id, 0x51, 1});
- for (const auto &port : this->iomap.omap)
- {
- data[port.second.first+2] = port.second.second;
- }
-
- for (auto &m : msg)
- {
- auto port = this->iomap.omap.find(m.first);
- if (port != this->iomap.omap.end())
- {
- if (m.second == "1")
- {
- port->second.second = 1;
- }
- else if (m.second == "0")
- {
- port->second.second = 0;
- }
- data[port->second.first+2] = port->second.second;
- }
- }
- SendDeviceMsg(data);
- }
- }
- else if (cmd->second == "pluse")
- {
- if (this->device == "5serial")
- {
- std::vector data;
- data.resize(8, 1);
- data.insert(data.begin(), {this->device_id, 0x51, 1});
- for (const auto &port : this->iomap.omap)
- {
- data[port.second.first+2] = port.second.second;
- }
-
- for (auto &m : msg)
- {
- auto port = this->iomap.omap.find(m.first);
- if (port != this->iomap.omap.end())
- {
- if (m.second == "1")
- {
- port->second.second = 1;
- }
- else if (m.second == "0")
- {
- port->second.second = 0;
- }
- data[port->second.first+2] = port->second.second;
- }
- }
- SendDeviceMsg(data);
-
- std::this_thread::sleep_for(std::chrono::seconds(1));
- for (auto &m : msg)
- {
- auto port = this->iomap.omap.find(m.first);
- if (port != this->iomap.omap.end())
- {
- if (m.second == "1")
- {
- port->second.second = 0;
- }
- else if (m.second == "0")
- {
- port->second.second = 1;
- }
- data[port->second.first+2] = port->second.second;
- }
- }
- SendDeviceMsg(data);
- }
- }
- else if (cmd->second == "read")
- {
- if (this->device == "5serial")
- {
- std::vector data;
- data.insert(data.end(), {this->device_id, 0x52, 1});
- data.insert(data.end(), 1);
- SendDeviceMsg(data);
- }
- }
- }
+static int gpio_export(int n)
+{
+ int fd = open("/sys/class/gpio/export", O_WRONLY);
+ if (fd < 0) return -1;
+ char buf[16]; int len = snprintf(buf, sizeof(buf), "%d", n);
+ write(fd, buf, len);
+ close(fd);
+ usleep(100000);
+ return 0;
}
-int MsgHandler::ParseDeviceMsg(std::vector& data, InternalSystem::IoCtrlRsp& rsp)
+static int gpio_set_dir(int n, const char* dir)
{
- if (data[0] == this->device_id)
- {
- switch(data[1])
- {
- case 0x50:
- rsp.msg()["open"] = std::to_string(data[3]);
- break;
- case 0x51:
- rsp.msg()["write"] = std::to_string(data[3]);
- break;
- case 0x52:
- rsp.msg()["read"] = "0";
- for (auto &p : this->iomap.imap)
- {
- // if (p.second.second != data[p.second.first+2])
- // {
- p.second.second = data[p.second.first+2];
- rsp.msg()[p.first] = std::to_string(p.second.second);
- // }
- }
- break;
- }
- return 1;
- }
+ char path[64]; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", n);
+ int fd = open(path, O_WRONLY);
+ if (fd < 0) return -1;
+ write(fd, dir, strlen(dir));
+ close(fd);
return 0;
}
-int MsgHandler::HandleDeviceMsg(InternalSystem::IoCtrlRsp& rsp)
+static int gpio_write(int n, int val)
{
- std::vector m_RecvData;
-
- if(RecvDeviceMsg(m_RecvData, 100) > 0)
- {
- for (int num : m_RecvData)
- {
- std::cout << std::hex << std::setw(2) << std::setfill('0')
- << num << " ";
- }
- std::cout << std::endl;
- return(ParseDeviceMsg(m_RecvData, rsp));
- }
+ char path[64]; snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", n);
+ int fd = open(path, O_WRONLY);
+ if (fd < 0) return -1;
+ char b = val ? '1' : '0';
+ write(fd, &b, 1);
+ close(fd);
return 0;
}
+
bool MsgHandler::OpenPort(const std::string& port, const std::string& baudrate)
{
+ std::cout << "[debug] OpenPort device=" << this->device
+ << " omap.size=" << this->iomap.omap.size() << std::endl;
+
+ if (this->device == "gpio")
+ {
+ // ★ 前拦车器两个 GPIO:先显式 export + direction + 写 0(不依赖 map 顺序)
+ gpio_export(48);
+ gpio_set_dir(48, "out");
+ gpio_write(48, 0);
+
+ gpio_export(49);
+ gpio_set_dir(49, "out");
+ gpio_write(49, 0);
+
+ return true;
+ }
return true;
}
@@ -270,3 +155,62 @@ int MsgHandler::RecvDeviceMsg(std::vector& data, int timeoutMs)
return RecvMsg(data.data(), data.size(), timeoutMs);
}
+void MsgHandler::HandleBarCommand(const WeighingSystem::BarCommandUpdate& cmd)
+{
+ if (this->device != "gpio") return;
+
+ // 前拦车器升杆
+ if (cmd.FrontBarEnable() && cmd.FrontBarSignalUp())
+ {
+ auto up = this->iomap.omap.find("frontbarrup");
+ if (up != this->iomap.omap.end())
+ {
+ // ① 抬杆前:先 init 48 + 49 全部拉低
+ std::cout << "[GPIO] >>> init 48+49 before raise" << std::endl;
+ this->InitFrontBarGpioPair();
+
+ // ② 抬杆:48 置 1
+ int n = up->second.first;
+ std::cout << "[GPIO] " << n << " <- 1 (raise start)" << std::endl;
+ int rc = gpio_write(n, 1);
+ std::cout << "[GPIO] " << n << " <- 1 rc=" << rc << std::endl;
+ up->second.second = 1;
+
+ // ③ 保持 10 秒
+ std::cout << "[GPIO] hold raise 10s..." << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+
+ // ④ 抬杆后:再 init 一次,强制两脚回 0
+ std::cout << "[GPIO] >>> init 48+49 after 10s (reset to 0)" << std::endl;
+ this->InitFrontBarGpioPair();
+ up->second.second = 0;
+ std::cout << "[GPIO] reset done" << std::endl;
+ }
+ }
+}
+
+
+void MsgHandler::InitFrontBarGpioPair()
+{
+ // 强制重新 init frontbarrup (48) 和 frontbardown (49)
+ auto up = iomap.omap.find("frontbarrup");
+ auto dn = iomap.omap.find("frontbardown");
+
+ if (up != iomap.omap.end())
+ {
+ int n = up->second.first; // 48
+ gpio_export(n);
+ gpio_set_dir(n, "out");
+ gpio_write(n, 0);
+ std::cout << "[GPIO] " << n << " init <- 0" << std::endl;
+ }
+
+ if (dn != iomap.omap.end())
+ {
+ int n = dn->second.first; // 49
+ gpio_export(n);
+ gpio_set_dir(n, "out");
+ gpio_write(n, 0);
+ std::cout << "[GPIO] " << n << " init <- 0" << std::endl;
+ }
+}
\ No newline at end of file
diff --git a/ioctrl/MsgHandler.hpp b/ioctrl/MsgHandler.hpp
index 10add06..a3fecc0 100644
--- a/ioctrl/MsgHandler.hpp
+++ b/ioctrl/MsgHandler.hpp
@@ -6,7 +6,7 @@
#include
#include