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.

525 lines
18 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 <thread>
#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 "SystemPubSubTypes.hpp"
#include "msg.hpp"
#include "DEBUG.hpp"
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 InternalSystem::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)
{
InternalSystem::PrintReq req;
req.msg() = msg;
for (auto &m : req.msg())
{
DEBUG("first: " << m.first << " second: " << m.second);
}
print_writer_->write(&req);
return true;
}
void PublisherApp::run()
{
uint8_t send_sum = 0;
std::string license_no = "";
float stable_weight = 0;
while (!is_stopped())
{
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 == "")
{
license_no = info.NewTag();
}
}
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() == 1)
{
stable_weight = info.StableValue();
}
else
{
stable_weight = 0;
send_sum = 0;
}
if (info.HasVehicle() == 0)
{
license_no = "";
}
}
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();
};
if (info.IsPrintTicker() == true)
{
std::map<std::string, std::string> print_msg;
print_msg["Title"] = "过衡单";
print_msg["DeviceID"] = std::to_string(info.DeviceID());
print_msg["DeviceName"] = info.DeviceName();
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_receipt(print_msg);
}
}
else if (!DdsMsgData::WeightInfoError_queue_.empty())
{
WeighingSystem::WeightInfoError info = std::move(DdsMsgData::WeightInfoError_queue_.front());
DdsMsgData::WeightInfoError_queue_.pop();
dds_lock.unlock();
send_sum = 0;
}
else
{
dds_lock.unlock();
}
}
// logic
if (send_sum == 0)
{
if ((stable_weight != 0) && (license_no != ""))
{
DEBUG("send summary");
WeighingSystem::SummaryUpdate info;
info.License() = license_no;
info.StableValue() = stable_weight;
summary_writer_->write(&info);
send_sum = 1;
}
}
// 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();
});
}
}
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();
}