You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
776 lines
29 KiB
C++
776 lines
29 KiB
C++
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
/*!
|
|
* @file Publisher.cxx
|
|
* This file contains the implementation of the publisher functions.
|
|
*
|
|
* This file was generated by the tool fastddsgen.
|
|
*/
|
|
|
|
#include "Publisher.hpp"
|
|
|
|
#include <condition_variable>
|
|
#include <csignal>
|
|
#include <stdexcept>
|
|
#include <iomanip>
|
|
#include <chrono>
|
|
#include <thread>
|
|
#include <cmath> // 新增:用于 std::fabs
|
|
|
|
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
|
|
#include <fastdds/dds/log/Log.hpp>
|
|
#include <fastdds/dds/publisher/DataWriter.hpp>
|
|
#include <fastdds/dds/publisher/Publisher.hpp>
|
|
#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>
|
|
#include <fastdds/dds/publisher/qos/PublisherQos.hpp>
|
|
|
|
#include "WeighingDDSTypePubSubTypes.hpp"
|
|
#include "msg.hpp"
|
|
#include "DEBUG.hpp"
|
|
|
|
|
|
// // 【新增】红外对射状态打印函数
|
|
// #include <iostream>
|
|
// void print_infrared_status()
|
|
// {
|
|
// while (!DdsMsgData::stop_flag_)
|
|
// {
|
|
// {
|
|
// std::lock_guard<std::mutex> lock(DdsMsgData::infrared_mtx_);
|
|
// std::cout << "[红外对射状态] Front: "
|
|
// << DdsMsgData::latest_infrared_.FrontResistanceSignal()
|
|
// << " Back: "
|
|
// << DdsMsgData::latest_infrared_.BackResistanceSignal()
|
|
// << std::endl;
|
|
// }
|
|
// std::this_thread::sleep_for(std::chrono::seconds(2));
|
|
// }
|
|
// }
|
|
|
|
|
|
using namespace eprosima::fastdds::dds;
|
|
|
|
PublisherApp::PublisherApp(
|
|
const int& domain_id)
|
|
: factory_(nullptr)
|
|
, participant_(nullptr)
|
|
, publisher_(nullptr)
|
|
, bar_topic_(nullptr)
|
|
, bar_writer_(nullptr)
|
|
, bar_type_(new WeighingSystem::BarCommandUpdatePubSubType())
|
|
, light_topic_(nullptr)
|
|
, light_writer_(nullptr)
|
|
, light_type_(new WeighingSystem::LightsCommandUpdatePubSubType())
|
|
, summary_topic_(nullptr)
|
|
, summary_writer_(nullptr)
|
|
, summary_type_(new WeighingSystem::SummaryUpdatePubSubType())
|
|
, print_topic_(nullptr)
|
|
, print_writer_(nullptr)
|
|
, 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");
|
|
pqos.wire_protocol().builtin.discovery_config.leaseDuration = Duration_t(60, 0);
|
|
pqos.wire_protocol().builtin.discovery_config.leaseDuration_announcementperiod = Duration_t(30, 0);
|
|
factory_ = DomainParticipantFactory::get_shared_instance();
|
|
participant_ = factory_->create_participant(domain_id, pqos, nullptr, StatusMask::none());
|
|
if (participant_ == nullptr)
|
|
{
|
|
throw std::runtime_error("Core Participant initialization failed");
|
|
}
|
|
|
|
// Register the type
|
|
bar_type_.register_type(participant_);
|
|
light_type_.register_type(participant_);
|
|
summary_type_.register_type(participant_);
|
|
print_type_.register_type(participant_);
|
|
|
|
// Create the publisher
|
|
PublisherQos pub_qos = PUBLISHER_QOS_DEFAULT;
|
|
participant_->get_default_publisher_qos(pub_qos);
|
|
publisher_ = participant_->create_publisher(pub_qos, nullptr, StatusMask::none());
|
|
if (publisher_ == nullptr)
|
|
{
|
|
throw std::runtime_error("Core Publisher initialization failed");
|
|
}
|
|
|
|
// Create the topic
|
|
TopicQos topic_qos = TOPIC_QOS_DEFAULT;
|
|
participant_->get_default_topic_qos(topic_qos);
|
|
bar_topic_ = participant_->create_topic("BarCommandUpdate", bar_type_.get_type_name(), topic_qos);
|
|
if (bar_topic_ == nullptr)
|
|
{
|
|
throw std::runtime_error("BarCommandUpdate Topic initialization failed");
|
|
}
|
|
|
|
// Create the data writer
|
|
DataWriterQos writer_qos = DATAWRITER_QOS_DEFAULT;
|
|
publisher_->get_default_datawriter_qos(writer_qos);
|
|
writer_qos.reliability().kind = ReliabilityQosPolicyKind::RELIABLE_RELIABILITY_QOS;
|
|
writer_qos.reliability().max_blocking_time = Duration_t(1, 0);
|
|
writer_qos.durability().kind = DurabilityQosPolicyKind::VOLATILE_DURABILITY_QOS;
|
|
writer_qos.history().kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
|
|
writer_qos.history().depth = 1;
|
|
writer_qos.resource_limits().max_samples = 200;
|
|
writer_qos.resource_limits().max_instances = 1;
|
|
writer_qos.resource_limits().max_samples_per_instance = 100;
|
|
writer_qos.data_sharing().off();
|
|
bar_writer_ = publisher_->create_datawriter(bar_topic_, writer_qos, this, StatusMask::all());
|
|
if (bar_writer_ == nullptr)
|
|
{
|
|
throw std::runtime_error("WeighingSystem::BarUpdate DataWriter initialization failed");
|
|
}
|
|
|
|
// Create the topic
|
|
topic_qos = TOPIC_QOS_DEFAULT;
|
|
participant_->get_default_topic_qos(topic_qos);
|
|
light_topic_ = participant_->create_topic("LightsCommandUpdate", light_type_.get_type_name(), topic_qos);
|
|
if (light_topic_ == nullptr)
|
|
{
|
|
throw std::runtime_error("LightsCommandUpdate Topic initialization failed");
|
|
}
|
|
|
|
// Create the data writer
|
|
writer_qos = DATAWRITER_QOS_DEFAULT;
|
|
publisher_->get_default_datawriter_qos(writer_qos);
|
|
writer_qos.reliability().kind = ReliabilityQosPolicyKind::RELIABLE_RELIABILITY_QOS;
|
|
writer_qos.reliability().max_blocking_time = Duration_t(1, 0);
|
|
writer_qos.durability().kind = DurabilityQosPolicyKind::VOLATILE_DURABILITY_QOS;
|
|
writer_qos.history().kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
|
|
writer_qos.history().depth = 1;
|
|
writer_qos.resource_limits().max_samples = 200;
|
|
writer_qos.resource_limits().max_instances = 1;
|
|
writer_qos.resource_limits().max_samples_per_instance = 100;
|
|
writer_qos.data_sharing().off();
|
|
light_writer_ = publisher_->create_datawriter(light_topic_, writer_qos, this, StatusMask::all());
|
|
if (light_writer_ == nullptr)
|
|
{
|
|
throw std::runtime_error("WeighingSystem::LightsUpdate DataWriter initialization failed");
|
|
}
|
|
|
|
// Create the topic
|
|
topic_qos = TOPIC_QOS_DEFAULT;
|
|
participant_->get_default_topic_qos(topic_qos);
|
|
summary_topic_ = participant_->create_topic("SummaryUpdate", summary_type_.get_type_name(), topic_qos);
|
|
if (summary_topic_ == nullptr)
|
|
{
|
|
throw std::runtime_error("SummaryUpdate Topic initialization failed");
|
|
}
|
|
|
|
// Create the data writer
|
|
writer_qos = DATAWRITER_QOS_DEFAULT;
|
|
publisher_->get_default_datawriter_qos(writer_qos);
|
|
writer_qos.reliability().kind = ReliabilityQosPolicyKind::RELIABLE_RELIABILITY_QOS;
|
|
writer_qos.reliability().max_blocking_time = Duration_t(1, 0);
|
|
writer_qos.durability().kind = DurabilityQosPolicyKind::VOLATILE_DURABILITY_QOS;
|
|
writer_qos.history().kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
|
|
writer_qos.history().depth = 1;
|
|
writer_qos.resource_limits().max_samples = 200;
|
|
writer_qos.resource_limits().max_instances = 1;
|
|
writer_qos.resource_limits().max_samples_per_instance = 100;
|
|
writer_qos.data_sharing().off();
|
|
summary_writer_ = publisher_->create_datawriter(summary_topic_, writer_qos, this, StatusMask::all());
|
|
if (summary_writer_ == nullptr)
|
|
{
|
|
throw std::runtime_error("WeighingSystem::SummaryUpdate DataWriter initialization failed");
|
|
}
|
|
|
|
// Create the topic
|
|
topic_qos = TOPIC_QOS_DEFAULT;
|
|
participant_->get_default_topic_qos(topic_qos);
|
|
print_topic_ = participant_->create_topic("PrintReq", print_type_.get_type_name(), topic_qos);
|
|
if (print_topic_ == nullptr)
|
|
{
|
|
throw std::runtime_error("PrintReq Topic initialization failed");
|
|
}
|
|
|
|
// Create the data writer
|
|
writer_qos = DATAWRITER_QOS_DEFAULT;
|
|
publisher_->get_default_datawriter_qos(writer_qos);
|
|
writer_qos.reliability().kind = ReliabilityQosPolicyKind::RELIABLE_RELIABILITY_QOS;
|
|
writer_qos.reliability().max_blocking_time = Duration_t(1, 0);
|
|
writer_qos.durability().kind = DurabilityQosPolicyKind::VOLATILE_DURABILITY_QOS;
|
|
writer_qos.history().kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
|
|
writer_qos.history().depth = 1;
|
|
writer_qos.resource_limits().max_samples = 200;
|
|
writer_qos.resource_limits().max_instances = 1;
|
|
writer_qos.resource_limits().max_samples_per_instance = 100;
|
|
writer_qos.data_sharing().off();
|
|
print_writer_ = publisher_->create_datawriter(print_topic_, writer_qos, this, StatusMask::all());
|
|
if (print_writer_ == nullptr)
|
|
{
|
|
throw std::runtime_error("InternalSystem::PrintReq DataWriter initialization failed");
|
|
}
|
|
}
|
|
|
|
PublisherApp::~PublisherApp()
|
|
{
|
|
if (nullptr != participant_)
|
|
{
|
|
// Delete DDS entities contained within the DomainParticipant
|
|
participant_->delete_contained_entities();
|
|
|
|
// Delete DomainParticipant
|
|
factory_->delete_participant(participant_);
|
|
}
|
|
}
|
|
|
|
void PublisherApp::on_publication_matched(
|
|
DataWriter* writer,
|
|
const PublicationMatchedStatus& info)
|
|
{
|
|
if (info.current_count_change == 1)
|
|
{
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
matched_ = info.current_count;
|
|
}
|
|
DEBUG(writer->get_topic()->get_name() << " Publisher matched.");
|
|
cv_.notify_one();
|
|
}
|
|
else if (info.current_count_change == -1)
|
|
{
|
|
{
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
matched_ = info.current_count;
|
|
}
|
|
DEBUG(writer->get_topic()->get_name() << " Publisher unmatched.");
|
|
}
|
|
else
|
|
{
|
|
DEBUG(info.current_count_change << " is not a valid value for PublicationMatchedStatus current count change");
|
|
}
|
|
}
|
|
|
|
bool PublisherApp::bar_ctrl(const std::map<std::string, std::string>& ctrl)
|
|
{
|
|
WeighingSystem::BarCommandUpdate cmd;
|
|
|
|
for (const auto &[port, opt] : ctrl)
|
|
{
|
|
if (port == "FrontBar")
|
|
{
|
|
if (opt == "up")
|
|
{
|
|
cmd.FrontBarSignalUp() = 1;
|
|
cmd.FrontBarSignalDown() = 0;
|
|
}
|
|
else
|
|
{
|
|
cmd.FrontBarSignalUp() = 0;
|
|
cmd.FrontBarSignalDown() = 1;
|
|
}
|
|
cmd.FrontBarEnable() = 1;
|
|
}
|
|
else if (port == "BackBar")
|
|
{
|
|
if (opt == "up")
|
|
{
|
|
cmd.BackBarSignalUp() = 1;
|
|
cmd.BackBarSignalDown() = 0;
|
|
}
|
|
else
|
|
{
|
|
cmd.BackBarSignalUp() = 0;
|
|
cmd.BackBarSignalDown() = 1;
|
|
}
|
|
cmd.BackBarEnable() = 1;
|
|
}
|
|
}
|
|
|
|
DEBUG("send bar ctrl cmd");
|
|
bar_writer_->write(&cmd);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PublisherApp::light_ctrl(const std::map<std::string, std::string>& ctrl)
|
|
{
|
|
WeighingSystem::LightsCommandUpdate cmd;
|
|
|
|
for (const auto &[port, opt] : ctrl)
|
|
{
|
|
if (port == "FrontLED")
|
|
{
|
|
if (opt == "red")
|
|
{
|
|
cmd.FrontLEDSignal() = 1;
|
|
}
|
|
else
|
|
{
|
|
cmd.FrontLEDSignal() = 2;
|
|
}
|
|
cmd.FrontLEDEnable() = 1;
|
|
}
|
|
else if (port == "BackLED")
|
|
{
|
|
if (opt == "red")
|
|
{
|
|
cmd.BackLEDSignal() = 1;
|
|
}
|
|
else
|
|
{
|
|
cmd.BackLEDSignal() = 2;
|
|
}
|
|
cmd.BackLEDEnable() = 1;
|
|
}
|
|
}
|
|
|
|
DEBUG("send light ctrl cmd");
|
|
light_writer_->write(&cmd);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PublisherApp::print_receipt(const std::map<std::string, std::string>& msg)
|
|
{
|
|
WeighingSystem::PrintReq req;
|
|
|
|
req.msg() = msg;
|
|
|
|
for (auto &m : req.msg())
|
|
{
|
|
DEBUG("first: " << m.first << " second: " << m.second);
|
|
}
|
|
|
|
print_writer_->write(&req);
|
|
|
|
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 3
|
|
#define WEIGH_STABLE_WAIT 4
|
|
|
|
void PublisherApp::run()
|
|
{
|
|
std::string license_no;
|
|
float stable_weight = 0;
|
|
float stable_weight1 = 0;
|
|
//float stable_weight2 = 0;
|
|
int weigh_state = WEIGH_IDLE;
|
|
std::chrono::steady_clock::time_point stable_start_time;
|
|
bool stable_timer_running = false; // 稳定计时是否在跑
|
|
float stable_weight_at_wait = 0; // 记录进入WEIGH_STABLE_WAIT时的稳定重量
|
|
|
|
// 【新增】启动红外对射状态打印线程
|
|
//std::thread infrared_thread(print_infrared_status);
|
|
|
|
while (!is_stopped())
|
|
{
|
|
// 【调试】每 20 帧打印一次状态机关键变量
|
|
static int dbg_cnt = 0;
|
|
if (++dbg_cnt % 20 == 0)
|
|
{
|
|
DEBUG("[HEARTBEAT] state=" << weigh_state
|
|
<< " lic=[" << license_no << "]"
|
|
<< " sw=" << stable_weight
|
|
<< " sw1=" << stable_weight1
|
|
<< " tr=" << stable_timer_running);
|
|
}
|
|
|
|
std::unique_lock<std::mutex> dds_lock(DdsMsgData::queue_cv_mtx_, std::try_to_lock);
|
|
if (dds_lock.owns_lock())
|
|
{
|
|
if (!DdsMsgData::LicenseSnapUpdate_queue_.empty())
|
|
{
|
|
WeighingSystem::LicenseSnapUpdate info = std::move(DdsMsgData::LicenseSnapUpdate_queue_.front());
|
|
DdsMsgData::LicenseSnapUpdate_queue_.pop();
|
|
dds_lock.unlock();
|
|
|
|
DEBUG("车牌: " << info.License());
|
|
DEBUG("类型: " << info.NewTag());
|
|
|
|
//if (license_no.empty() == true)
|
|
if (true) // 收到车牌识别就触发,不做条件判断
|
|
{
|
|
license_no = info.License();
|
|
weigh_state = WEIGH_LIC;
|
|
// 识别到车牌,抬起前拦车器
|
|
std::map<std::string, std::string> ctrl;
|
|
ctrl["FrontBar"] = "up";
|
|
bar_ctrl(ctrl);
|
|
}
|
|
}
|
|
else if (!DdsMsgData::ScaleInfo_queue_.empty())
|
|
{
|
|
WeighingSystem::ScaleInfo info = std::move(DdsMsgData::ScaleInfo_queue_.front());
|
|
DdsMsgData::ScaleInfo_queue_.pop();
|
|
dds_lock.unlock();
|
|
|
|
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<std::string, std::string> ctrl;
|
|
// ctrl["FrontBar"] = "down";
|
|
// bar_ctrl(ctrl);
|
|
// weigh_state = WEIGH_IDLE;
|
|
// }
|
|
// }
|
|
|
|
if (info.HasVehicle() == 0)
|
|
{
|
|
// else if (license_no.empty() != true)
|
|
// {
|
|
// license_no.clear();
|
|
// }
|
|
}
|
|
|
|
}
|
|
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();
|
|
|
|
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();
|
|
|
|
auto formatFloat = [](float value) -> std::string
|
|
{
|
|
std::ostringstream oss;
|
|
oss << std::fixed << std::setprecision(2) << value;
|
|
return oss.str();
|
|
};
|
|
|
|
DEBUG("==== WeightInfoOk 接收 ====");
|
|
DEBUG(" IsPrintTicker = " << info.IsPrintTicker());
|
|
DEBUG(" GrossDeviceID = " << info.GrossDeviceID());
|
|
DEBUG(" GrossDeviceName = " << info.GrossDeviceName());
|
|
DEBUG(" TareDeviceID = " << info.TareDeviceID());
|
|
DEBUG(" TareDeviceName = " << info.TareDeviceName());
|
|
DEBUG(" EnterpriseName = " << info.EnterpriseName());
|
|
DEBUG(" BillNumber = " << info.BillNumber());
|
|
DEBUG(" CarNumber = " << info.CarNumber());
|
|
DEBUG(" Supplier = " << info.Supplier());
|
|
DEBUG(" GoodsType = " << info.GoodsType());
|
|
DEBUG(" GrossWeight = " << info.GrossWeight());
|
|
DEBUG(" GrossTime = " << info.GrossTime());
|
|
DEBUG(" GrossOperater = " << info.GrossOperater());
|
|
DEBUG(" Tare = " << info.Tare());
|
|
DEBUG(" TareTime = " << info.TareTime());
|
|
DEBUG(" TareOperater = " << info.TareOperater());
|
|
DEBUG(" Suttle = " << info.Suttle());
|
|
DEBUG(" duduction1 = " << info.duduction1());
|
|
DEBUG(" duduction2 = " << info.duduction2());
|
|
DEBUG(" duduction3 = " << info.duduction3());
|
|
DEBUG(" INCoalYard = " << info.INCoalYard());
|
|
DEBUG(" OutCoalYard = " << info.OutCoalYard());
|
|
DEBUG(" BatchNumber = " << info.BatchNumber());
|
|
DEBUG(" Warning = " << info.Warning());
|
|
DEBUG(" Tips = " << info.Tips());
|
|
DEBUG(" TicketType = " << info.TicketType());
|
|
DEBUG("============================");
|
|
|
|
if (info.IsPrintTicker() == true)
|
|
{
|
|
std::map<std::string, std::string> 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["OrderNumber"] = info.OrderNumber();
|
|
print_msg["TrainNumber"] = info.VehicleAndVesselNumber();
|
|
print_msg["Customer"] = info.ReceiveCompany();
|
|
print_msg["Transporter"] = info.TransportCompany();
|
|
|
|
|
|
print_receipt(print_msg);
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
}
|
|
weigh_state = WEIGH_LEAVE;
|
|
std::map<std::string, std::string> 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;
|
|
// }
|
|
else
|
|
{
|
|
dds_lock.unlock();
|
|
}
|
|
}
|
|
|
|
// logic
|
|
// 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");
|
|
// {
|
|
// WeighingSystem::SummaryUpdate info;
|
|
// info.License() = license_no;
|
|
// info.StableValue() = stable_weight2;
|
|
// summary_writer_->write(&info);
|
|
// }
|
|
// 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;
|
|
// }
|
|
switch (weigh_state)
|
|
{
|
|
case WEIGH_IDLE:
|
|
break;
|
|
case WEIGH_LIC:
|
|
DEBUG("[STATE] WEIGH_LIC sw=" << stable_weight << " lic=[" << license_no << "]");
|
|
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, wait for card...");
|
|
// 重量归零,重置计时器
|
|
stable_timer_running = false;
|
|
}
|
|
else
|
|
{
|
|
// 读取前红外对射状态
|
|
long front_ir = 0;
|
|
{
|
|
std::lock_guard<std::mutex> lock(DdsMsgData::infrared_mtx_);
|
|
front_ir = DdsMsgData::latest_infrared_.FrontResistanceSignal();
|
|
}
|
|
|
|
if (front_ir != 0) // 红外被遮挡(==1),关闭计时器
|
|
{
|
|
stable_timer_running = false;
|
|
DEBUG("Front infrared blocked (sig=" << front_ir
|
|
<< "), timer closed.");
|
|
}
|
|
else // 红外无遮挡(==0),启动/继续计时
|
|
{
|
|
if (!stable_timer_running)
|
|
{
|
|
stable_start_time = std::chrono::steady_clock::now();
|
|
stable_timer_running = true;
|
|
DEBUG("Infrared clear, starting 10s timer...");
|
|
}
|
|
auto now = std::chrono::steady_clock::now();
|
|
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - stable_start_time).count();
|
|
}
|
|
}
|
|
break;
|
|
case WEIGH_STABLE_WAIT:
|
|
// 第一次进入时记录当前重量为基准
|
|
if (stable_weight_at_wait == 0)
|
|
{
|
|
stable_weight_at_wait = stable_weight;
|
|
}
|
|
// 等待司机下车刷卡,通过重量变化 > 30KG 检测司机下车
|
|
if (stable_weight > 0 && stable_weight_at_wait > 0)
|
|
{
|
|
float weight_diff = std::abs(stable_weight - stable_weight_at_wait);
|
|
if (weight_diff > 30)
|
|
{
|
|
DEBUG("Weight changed by " << weight_diff << " kg, driver may have left, waiting for card...");
|
|
stable_weight_at_wait = stable_weight; // 更新基准重量
|
|
}
|
|
}
|
|
else if (stable_weight == 0)
|
|
{
|
|
DEBUG("Scale is empty, waiting for card...");
|
|
stable_weight_at_wait = 0;
|
|
}
|
|
break;
|
|
case WEIGH_LEAVE:
|
|
break;
|
|
default:
|
|
weigh_state = WEIGH_IDLE;
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
// Wait for period or stop event
|
|
std::unique_lock<std::mutex> period_lock(mutex_);
|
|
cv_.wait_for(period_lock, std::chrono::milliseconds(period_ms_), [this]()
|
|
{
|
|
return is_stopped();
|
|
});
|
|
}
|
|
|
|
// // 【新增】停止红外打印线程
|
|
// DdsMsgData::stop_flag_ = true;
|
|
// infrared_thread.join();
|
|
|
|
}
|
|
|
|
|
|
bool PublisherApp::publish()
|
|
{
|
|
bool ret = false;
|
|
// Wait for the data endpoints discovery
|
|
std::unique_lock<std::mutex> matched_lock(mutex_);
|
|
cv_.wait(matched_lock, [&]()
|
|
{
|
|
// at least one has been discovered
|
|
return ((matched_ > 0) || is_stopped());
|
|
});
|
|
|
|
if (!is_stopped())
|
|
{
|
|
/* Initialize your structure here */
|
|
WeighingSystem::BarCommandUpdate sample_;
|
|
ret = (RETCODE_OK == bar_writer_->write(&sample_));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool PublisherApp::is_stopped()
|
|
{
|
|
return stop_.load();
|
|
}
|
|
|
|
void PublisherApp::stop()
|
|
{
|
|
stop_.store(true);
|
|
cv_.notify_one();
|
|
}
|