OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
serial_protocol.hpp
1#pragma once
3#include <ossia/detail/variant.hpp>
4#include <ossia/network/base/message_queue.hpp>
5#include <ossia/network/base/protocol.hpp>
6#include <ossia/network/context.hpp>
7#include <ossia/network/generic/wrapped_parameter.hpp>
8#include <ossia/network/sockets/line_framing.hpp>
9#include <ossia/network/sockets/no_framing.hpp>
10#include <ossia/network/sockets/serial_socket.hpp>
11#include <ossia/network/sockets/size_prefix_framing.hpp>
12#include <ossia/network/sockets/slip_framing.hpp>
13
14#include <ossia-qt/js_utilities.hpp>
15
16#include <boost/asio/error.hpp>
17#include <boost/asio/streambuf.hpp>
18
19#include <QObject>
20#include <QQmlComponent>
21#include <QSerialPort>
22#include <QThread>
23
24#include <span>
25#include <verdigris>
26
27class QQmlEngine;
28class QQmlComponent;
29
30namespace ossia
31{
32namespace net
33{
34struct serial_parameter_data_base
35{
36 serial_parameter_data_base() = default;
37 serial_parameter_data_base(const serial_parameter_data_base&) = default;
38 serial_parameter_data_base(serial_parameter_data_base&&) = default;
39 serial_parameter_data_base& operator=(const serial_parameter_data_base&) = default;
40 serial_parameter_data_base& operator=(serial_parameter_data_base&&) = default;
41 serial_parameter_data_base(const QJSValue& val)
42 {
43 request = val.property("request");
44 if(!request.isString() && !request.isCallable())
45 {
46 request = val.property("name");
47 }
48
49 if(val.hasProperty("osc_address"))
50 osc_address = val.property("osc_address").toString();
51 }
52
53 QJSValue request;
54 QString osc_address;
55};
56struct serial_parameter_data final
57 : public parameter_data
58 , public serial_parameter_data_base
59{
60 using base_data_type = serial_parameter_data_base;
61 serial_parameter_data() = default;
62 serial_parameter_data(const serial_parameter_data&) = default;
63 serial_parameter_data(serial_parameter_data&&) = default;
64 serial_parameter_data& operator=(const serial_parameter_data&) = default;
65 serial_parameter_data& operator=(serial_parameter_data&&) = default;
66
67 serial_parameter_data(const std::string& name)
68 : parameter_data{name}
69 {
70 }
71
72 serial_parameter_data(const QJSValue& val)
73 : parameter_data{ossia::qt::make_parameter_data(val)}
74 , serial_parameter_data_base{val}
75 {
76 }
77
78 bool valid() const noexcept
79 {
80 return request.isString() || request.isCallable() || type;
81 }
82};
83
84struct no_framing_socket : ossia::net::serial_socket<no_framing>
85{
86 using serial_socket::serial_socket;
87};
88struct size_framing_socket : ossia::net::serial_socket<size_prefix_framing>
89{
90 using serial_socket::serial_socket;
91};
92struct slip_framing_socket : ossia::net::serial_socket<slip_framing>
93{
94 using serial_socket::serial_socket;
95};
96struct line_framing_socket : ossia::net::serial_socket<line_framing>
97{
98 using serial_socket::serial_socket;
99};
100
101using framed_serial_socket = ossia::slow_variant<
102 no_framing_socket, size_framing_socket, slip_framing_socket, line_framing_socket>;
103
104struct serial_protocol_configuration
105{
106 ossia::net::framing framing;
107 std::string line_framing_delimiter;
108
109 serial_configuration transport;
110};
111
112class OSSIA_EXPORT serial_wrapper final : public QObject
113{
114 W_OBJECT(serial_wrapper)
115
116public:
117 serial_wrapper(
118 const network_context_ptr& ctx,
119 const ossia::net::serial_protocol_configuration& port);
120 ~serial_wrapper() noexcept;
121
122 void write(QByteArray arg_1) E_SIGNAL(OSSIA_EXPORT, write, arg_1);
123 void read(QString txt, QByteArray raw) E_SIGNAL(OSSIA_EXPORT, read, txt, raw);
124
125 void on_write(const QByteArray& b) noexcept;
126 W_SLOT(on_write, (const QByteArray&))
127
128 void on_write(std::string_view b) noexcept;
129
130 void on_read(const QByteArray& arr);
131 W_SLOT(on_read)
132
133 void close();
134
135private:
136 framed_serial_socket make_socket(
137 const network_context_ptr& ctx,
138 const ossia::net::serial_protocol_configuration& port);
139 framed_serial_socket m_socket;
140 bool m_open{};
141};
142
143class serial_protocol;
144struct serial_protocol_object;
145
146using serial_parameter = wrapped_parameter<serial_parameter_data>;
147using serial_node = ossia::net::wrapped_node<serial_parameter_data, serial_parameter>;
148class OSSIA_EXPORT serial_protocol final
149 : public QObject
151{
152public:
153 // Param : the name of the serial port
154 serial_protocol(
155 const ossia::net::network_context_ptr&, const QByteArray& code,
156 const ossia::net::serial_configuration& bot);
157 ~serial_protocol() override;
158
159 bool pull(ossia::net::parameter_base&) override;
160 bool push(const ossia::net::parameter_base&, const ossia::value& v) override;
161 bool push_raw(const ossia::net::full_parameter_data& parameter_base) override;
162 bool observe(ossia::net::parameter_base&, bool) override;
163 bool update(ossia::net::node_base& node_base) override;
164
165 void set_device(ossia::net::device_base& dev) override;
166 void stop() override;
167
168 static serial_parameter_data read_data(const QJSValue& js) { return js; }
169
170 static serial_protocol_object load_serial_object_from_qml(
171 serial_protocol& proto, const ossia::net::network_context_ptr& ctx,
172 const ossia::net::serial_configuration& cfg);
173 void create(
174 const ossia::net::network_context_ptr&,
175 const ossia::net::serial_configuration& cfg);
176 void on_read(const QString& txt, const QByteArray&);
177 void do_write(const ossia::net::parameter_base&, const ossia::value& v);
178 void do_write_osc(const serial_parameter&, const ossia::value& v);
179 void do_write_osc_bundle(
180 std::span<std::pair<const serial_parameter*, const ossia::value*>> vec);
181 void do_write_osc_impl(
182 const serial_parameter& addr, const ossia::value& v, std::string& str);
183
184private:
185 void startup_engine();
186 void create_object(QQmlComponent::Status status);
187
188 ossia::net::network_context_ptr m_context;
189 ossia::net::serial_configuration m_cfg;
190
191 QQmlEngine* m_engine{};
192 QQmlComponent* m_component{};
193
194 ossia::net::device_base* m_device{};
195 QObject* m_object{};
196 QJSValue m_jsObj{};
197 QJSValue m_onTextMessage{};
198 QJSValue m_onBinaryMessage{};
199 QJSValue m_onRead{};
200 std::shared_ptr<serial_wrapper> m_port;
201 QByteArray m_code;
202
203 QObject* m_threadWorker{};
204 QThread m_thread{};
205
206 coalescing_queue m_queue;
207 std::optional<double> m_coalesce{};
208 bool m_osc{};
209};
210using serial_device = ossia::net::wrapped_device<serial_node, serial_protocol>;
211
212class OSSIA_EXPORT Serial : public QObject
213{
214};
215
216}
217}
Root of a device tree.
Definition ossia/network/base/device.hpp:58
The node_base class.
Definition node.hpp:48
The parameter_base class.
Definition ossia/network/base/parameter.hpp:48
The protocol_base class.
Definition protocol.hpp:40
The value class.
Definition value.hpp:173
Definition git_info.h:7
Full information about a parameter.
Definition parameter_data.hpp:61