Line data Source code
1 : /**
2 : * @file DaphneMezzModule_test.cxx
3 : *
4 : * Testing configurations sender for the daphne v3
5 : *
6 : * This is part of the DUNE DAQ Software Suite, copyright 2020.
7 : * Licensing/copyright details are in the COPYING file that you should have
8 : * received with this code.
9 : *
10 : */
11 :
12 : #include "DaphneV3Interface.hpp"
13 :
14 : #include "daphnemodules/daphne_control_high.pb.h"
15 : #include <zmq.hpp>
16 :
17 : #include <chrono>
18 : #include <cstdlib>
19 : #include <cstring>
20 : #include <iostream>
21 : #include <random>
22 : #include <stdexcept>
23 : #include <string>
24 : #include <vector>
25 :
26 : using namespace daphne;
27 : using namespace dunedaq::daphnemodules;
28 :
29 : // ------------- small helpers -------------
30 : static std::vector<zmq::message_t>
31 : recv_multipart(zmq::socket_t& s)
32 : {
33 : std::vector<zmq::message_t> frames;
34 : while (true) {
35 : zmq::message_t part;
36 : auto ok = s.recv(part, zmq::recv_flags::none);
37 : if (!ok || *ok <= 0)
38 : throw std::runtime_error("No response from slow controller");
39 : frames.emplace_back(std::move(part));
40 : if (!s.get(zmq::sockopt::rcvmore))
41 : break;
42 : }
43 : return frames;
44 : }
45 :
46 : static inline uint64_t
47 0 : now_ns()
48 : {
49 0 : using namespace std::chrono;
50 0 : return duration_cast<nanoseconds>(steady_clock::now().time_since_epoch()).count();
51 : }
52 :
53 : static inline std::pair<uint64_t, uint64_t>
54 0 : next_ids()
55 : {
56 0 : static std::mt19937_64 rng{ std::random_device{}() };
57 0 : static uint64_t seq = 1;
58 0 : uint64_t t = now_ns();
59 0 : uint64_t task = (t << 16) ^ (rng() & 0xFFFF);
60 0 : uint64_t msg = (t << 1) ^ (++seq);
61 0 : task &= ((1ull << 63) - 1);
62 0 : msg &= ((1ull << 63) - 1);
63 0 : return { task, msg };
64 : }
65 :
66 : static void
67 0 : usage(const char* prog)
68 : {
69 0 : std::cerr << "Usage: " << prog << " [--ip <addr>] [--port <num>] [--route <name>]\n"
70 : << " " << prog << " [ip] [port]\n"
71 : << "Env: DAPHNE_IP, DAPHNE_PORT\n"
72 0 : << "Default: 10.73.137.161:9000, route=mezz/0\n";
73 0 : }
74 :
75 : int
76 0 : main(int argc, char** argv)
77 : {
78 : // ---- Defaults
79 0 : std::string ip = "10.73.137.161";
80 0 : int port = 9000;
81 0 : std::string route = "mezz/0";
82 :
83 : // ---- Env
84 0 : if (const char* eip = std::getenv("DAPHNE_IP"); eip && *eip)
85 0 : ip = eip;
86 0 : if (const char* ep = std::getenv("DAPHNE_PORT"); ep && *ep) {
87 0 : try {
88 0 : port = std::stoi(ep);
89 0 : } catch (...) {
90 0 : }
91 : }
92 :
93 : // ---- CLI flags (priority over env)
94 0 : for (int i = 1; i < argc; ++i) {
95 0 : if (!std::strcmp(argv[i], "--help") || !std::strcmp(argv[i], "-h")) {
96 0 : usage(argv[0]);
97 : return 0;
98 : }
99 0 : if (!std::strcmp(argv[i], "--ip") && i + 1 < argc) {
100 0 : ip = argv[++i];
101 0 : continue;
102 : }
103 0 : if (!std::strcmp(argv[i], "--port") && i + 1 < argc) {
104 0 : try {
105 0 : port = std::stoi(argv[++i]);
106 0 : } catch (...) {
107 0 : }
108 0 : continue;
109 : }
110 0 : if (!std::strcmp(argv[i], "--route") && i + 1 < argc) {
111 0 : route = argv[++i];
112 0 : continue;
113 : }
114 : }
115 : // ---- Positional args (fallback if flags not used)
116 0 : if (argc >= 2 && argv[1][0] != '-')
117 0 : ip = argv[1];
118 0 : if (argc >= 3 && argv[2][0] != '-') {
119 0 : try {
120 0 : port = std::stoi(argv[2]);
121 0 : } catch (...) {
122 0 : }
123 : }
124 :
125 0 : const std::string address = ip + ":" + std::to_string(port);
126 0 : const std::string endpoint = "tcp://" + address;
127 0 : std::cerr << "[SMOKE-V2] connecting to " << endpoint << " route=" << route << "\n";
128 :
129 0 : DaphneV3Interface iface(address, route);
130 :
131 0 : GOOGLE_PROTOBUF_VERIFY_VERSION;
132 :
133 : // ---- Build ConfigureRequest (same payload you used before)
134 0 : ConfigureRequest cfg;
135 0 : cfg.set_daphne_address(ip);
136 0 : cfg.set_slot(0);
137 0 : cfg.set_timeout_ms(500);
138 0 : cfg.set_biasctrl(1300);
139 0 : cfg.set_self_trigger_threshold(0x1F40);
140 0 : cfg.set_self_trigger_xcorr(0x68);
141 0 : cfg.set_tp_conf(0x0010DB35);
142 0 : cfg.set_compensator(0xFFFFFFFFFFull);
143 0 : cfg.set_inverters(0xFF00000000ull);
144 :
145 0 : for (uint32_t ch = 0; ch < 40; ++ch) {
146 0 : auto* c = cfg.add_channels();
147 0 : c->set_id(ch);
148 0 : c->set_trim(0);
149 0 : c->set_offset(2275);
150 0 : c->set_gain(1);
151 : }
152 0 : for (uint32_t afe = 0; afe < 5; ++afe) {
153 0 : auto* a = cfg.add_afes();
154 0 : a->set_id(afe);
155 0 : a->set_attenuators(1600);
156 0 : a->set_v_bias(0);
157 0 : a->mutable_adc()->set_resolution(true);
158 0 : a->mutable_adc()->set_output_format(true);
159 0 : a->mutable_adc()->set_sb_first(false);
160 0 : a->mutable_pga()->set_lpf_cut_frequency(4);
161 0 : a->mutable_pga()->set_integrator_disable(true);
162 0 : a->mutable_pga()->set_gain(0);
163 0 : a->mutable_lna()->set_clamp(0);
164 0 : a->mutable_lna()->set_gain(2);
165 0 : a->mutable_lna()->set_integrator_disable(true);
166 : }
167 :
168 : // ---- Wrap in V2 envelope
169 0 : ControlEnvelopeV2 req;
170 0 : req.set_version(2);
171 0 : req.set_dir(DIR_REQUEST);
172 0 : req.set_type(MT2_CONFIGURE_FE_REQ);
173 0 : req.set_payload(cfg.SerializeAsString());
174 0 : {
175 0 : auto [task_id, msg_id] = next_ids();
176 0 : req.set_task_id(task_id);
177 0 : req.set_msg_id(msg_id);
178 0 : req.set_timestamp_ns(now_ns());
179 0 : if (!route.empty())
180 0 : req.set_route(route);
181 : }
182 :
183 0 : try {
184 : // zmq::context_t ctx(1);
185 : // zmq::socket_t sock(ctx, zmq::socket_type::dealer);
186 : // sock.set(zmq::sockopt::routing_id, "zmq-config-smoke-v2");
187 : // sock.set(zmq::sockopt::rcvtimeo, 4000);
188 : // sock.set(zmq::sockopt::sndtimeo, 4000);
189 : // sock.connect(endpoint);
190 :
191 : // send
192 : // {
193 : // std::string bytes = req.SerializeAsString();
194 : // zmq::message_t msg(bytes.size());
195 : // std::memcpy(msg.data(), bytes.data(), bytes.size());
196 : // if (!sock.send(msg, zmq::send_flags::none)) {
197 : // std::cerr << "send() timed out\n"; return 2;
198 : // }
199 : // }
200 :
201 : // // recv
202 : // auto frames = recv_multipart(sock);
203 : // const zmq::message_t& payload = frames.back();
204 :
205 : // ControlEnvelopeV2 rep;
206 : // if (!rep.ParseFromArray(payload.data(), static_cast<int>(payload.size()))) {
207 : // std::cerr << "Failed to parse ControlEnvelopeV2 reply\n"; return 3;
208 : // }
209 :
210 : // // validate V2 transport
211 : // bool ok_dir = (rep.dir() == DIR_RESPONSE);
212 : // bool ok_type = (rep.type() == MT2_CONFIGURE_FE_RESP);
213 : // bool ok_tid = (rep.task_id() == req.task_id());
214 : // bool ok_corr = (rep.correl_id() == req.msg_id());
215 : // if (!ok_dir || !ok_type || !ok_tid || !ok_corr) {
216 : // std::cerr << "Correlation/type mismatch:"
217 : // << "\n dir: got " << rep.dir() << " expect " << DIR_RESPONSE
218 : // << "\n type: got " << rep.type() << " expect " << MT2_CONFIGURE_FE_RESP
219 : // << "\n task: got " << rep.task_id() << " expect " << req.task_id()
220 : // << "\n corr: got " << rep.correl_id()<< " expect " << req.msg_id()
221 : // << "\n";
222 : // return 4;
223 : // }
224 :
225 : // // decode payload
226 : // ConfigureResponse resp;
227 : // if (!resp.ParseFromString(rep.payload())) {
228 : // std::cerr << "Failed to parse ConfigureResponse\n"; return 5;
229 : // }
230 :
231 0 : auto resp = iface.send<ConfigureResponse>(cfg.SerializeAsString(), MT2_CONFIGURE_FE_REQ, MT2_CONFIGURE_FE_RESP);
232 :
233 : // std::cout << "[V2 meta]\n";
234 : // std::cout << " task_id : " << rep.task_id() << "\n";
235 : // std::cout << " msg_id : " << rep.msg_id() << "\n";
236 : // std::cout << " correl_id : " << rep.correl_id() << "\n";
237 : // std::cout << " timestamp_ns : " << rep.timestamp_ns() << "\n";
238 : // if (!rep.route().empty())
239 : // std::cout << " route : " << rep.route() << "\n";
240 : // std::cout << "\n";
241 0 : std::cout << "Success: " << std::boolalpha << resp.success() << "\n";
242 0 : std::cout << "Message:\n" << resp.message() << "\n";
243 :
244 0 : google::protobuf::ShutdownProtobufLibrary();
245 0 : return resp.success() ? 0 : 6;
246 :
247 0 : } catch (const std::exception& e) {
248 0 : std::cerr << "Exception: " << e.what() << "\n";
249 0 : return 7;
250 0 : }
251 0 : }
|