UniSet 2.41.2
JSEngine.h
1/*
2 * Copyright (c) 2025 Pavel Vainerman.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation, version 2.1.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Lesser Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16// --------------------------------------------------------------------------
17#ifndef JSEngine_H_
18// --------------------------------------------------------------------------
19#include <unordered_map>
20extern "C" {
21#include "quickjs/quickjs.h"
22}
23#include "UInterface.h"
24#include "JHttpServer.h"
25// --------------------------------------------------------------------------
26namespace uniset
27{
28 // ----------------------------------------------------------------------
29 struct JSOptions
30 {
31 size_t jsLoopCount = { 5 };
32 size_t httpLoopCount = { 5 };
33 size_t httpMaxQueueSize = { 100 };
34 size_t httpMaxThreads = { 3 };
35 size_t httpMaxRequestQueue = { 50 };
36 std::chrono::milliseconds httpResponseTimeout = { std::chrono::milliseconds(5000) };
37 std::chrono::milliseconds httpQueueWaitTimeout = {std::chrono::milliseconds(5000) };
38 bool esmModuleMode = { false };
39 };
40 // ----------------------------------------------------------------------
41 class JSEngine
42 {
43 public:
44 explicit JSEngine( const std::string& jsfile,
45 std::vector<std::string>& searchPaths,
46 std::shared_ptr<UInterface>& ui,
47 JSOptions& opts );
48 virtual ~JSEngine();
49
50 inline std::shared_ptr<DebugStream> log() noexcept
51 {
52 return mylog;
53 }
54
55 inline std::shared_ptr<DebugStream> js_log() noexcept
56 {
57 return jslog;
58 }
59
60 inline std::shared_ptr<DebugStream> http_log() noexcept
61 {
62 return httpserv->log();
63 }
64
65 void init();
66 bool isActive();
67
68 void start();
69 void stop();
70 void askSensors( UniversalIO::UIOCommand cmd );
71 void sensorInfo( const uniset::SensorMessage* sm );
72 void updateOutputs();
73 void step();
74
75 protected:
76 void initJS();
77 void freeJS();
78 void initGlobal( JSContext* ctx );
79 void exportAllFunctionsFromTimerModule();
80 void createUInterfaceObject();
81 void createUnisetObject();
82 void createResponsePrototype( JSContext* ctx );
83 void createRequestAtoms(JSContext* ctx);
84 void createRequestPrototype(JSContext* ctx);
85 void jsLoop();
86 void preStop();
87
88 private:
89 JSValue jsReqProto_ = { JS_UNDEFINED };
90 JSValue jsResProto_ = { JS_UNDEFINED };
91
92 bool reqAtomsInited_ = false;
93 struct JSReqAtom
94 {
95 JSAtom method, uri, version, url, path, query, headers, body;
96 } reqAtoms_{};
97
98 std::atomic_bool activated = { false };
99 std::shared_ptr<DebugStream> mylog;
100 std::string jsfile;
101 std::vector<std::string> searchPaths;
102 std::shared_ptr<UInterface> ui;
103 JSRuntime* rt = { nullptr };
104 JSContext* ctx = { nullptr };
105 uint8_t* jsbuf = { nullptr };
106 std::shared_ptr<DebugStream> jslog = { nullptr };
107 std::shared_ptr<uniset::JHttpServer> httpserv = { nullptr };
108 JSOptions opts;
109 std::shared_ptr<uniset::ObjectIndex> oind;
110
111 struct jsSensor
112 {
114 std::string name;
115 bool set( JSContext* ctx, JSValue& global, int64_t v );
116 };
117
118 std::unordered_map<uniset::ObjectId, jsSensor> inputs;
119 std::unordered_map<uniset::ObjectId, jsSensor> outputs;
120 std::list<JSValue> stepFunctions;
121 std::list<JSValue> stopFunctions;
122
123 JSValue jsFnStep = { JS_UNDEFINED };
124 JSValue jsFnStart = { JS_UNDEFINED };
125 JSValue jsFnStop = { JS_UNDEFINED };
126 JSValue jsFnTimers = { JS_UNDEFINED };
127 JSValue jsFnOnSensor = { JS_UNDEFINED };
128 JSValue jsGlobal = { JS_UNDEFINED };
129 JSValue jsModule = { JS_UNDEFINED };
130 JSValue jsFnHttpRequest = { JS_UNDEFINED };
131 JHttpServer::HandlerFn httpHandleFn;
132
133 JSValue js_ui_getValue(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
134 JSValue js_ui_askSensor(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
135 JSValue js_ui_setValue(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
136 JSValue js_uniset_StepCb(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
137 JSValue js_uniset_StopCb(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
138 JSValue js_uniset_httpStart(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
139 JSValue js_log(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
140 JSValue js_log_level(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
141
142 // Статические обертки для вызова нестатических методов
143 static JSValue jsUiGetValue_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
144 static JSValue jsUiAskSensor_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
145 static JSValue jsUiSetValue_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
146 static JSValue jsLog_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
147 static JSValue jsLogLevel_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
148 static JSValue jsUniSetStepCb_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
149 static JSValue jsUniSetStopCb_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
150 static JSValue jsUniSetHttpStart_wrapper(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
151
152 // http convert
153 static JSValue jsMakeRequest(JSContext* ctx, JSValueConst& jsReqProto_, JSReqAtom& atom, const JHttpServer::RequestSnapshot& r);
154 static JSValue jsMakeResponse(JSContext* ctx, JSValueConst& jsResProto_, JHttpServer::ResponseAdapter* ad);
155 static void jsApplyResponseObject(JSContext* ctx, JSValue ret, JHttpServer::ResponseSnapshot& out);
156 static void jsApplyResponseAdapter( const JHttpServer::ResponseAdapter& ad, JHttpServer::ResponseSnapshot& out );
157
158 // "синтаксический сахар" для логов
159#ifndef myinfo
160#define myinfo if( log()->debugging(Debug::INFO) ) log()->info()
161#endif
162#ifndef mywarn
163#define mywarn if( log()->debugging(Debug::WARN) ) log()->warn()
164#endif
165#ifndef mycrit
166#define mycrit if( log()->debugging(Debug::CRIT) ) log()->crit()
167#endif
168#ifndef mylog1
169#define mylog1 if( log()->debugging(Debug::LEVEL1) ) log()->level1()
170#endif
171#ifndef mylog2
172#define mylog2 if( log()->debugging(Debug::LEVEL2) ) log()->level2()
173#endif
174#ifndef mylog3
175#define mylog3 if( log()->debugging(Debug::LEVEL3) ) log()->level3()
176#endif
177#ifndef mylog4
178#define mylog4 if( log()->debugging(Debug::LEVEL4) ) log()->level4()
179#endif
180#ifndef mylog5
181#define mylog5 if( log()->debugging(Debug::LEVEL5) ) log()->level5()
182#endif
183#ifndef mylog6
184#define mylog6 if( log()->debugging(Debug::LEVEL6) ) log()->level6()
185#endif
186#ifndef mylog7
187#define mylog7 if( log()->debugging(Debug::LEVEL7) ) log()->level7()
188#endif
189#ifndef mylog8
190#define mylog8 if( log()->debugging(Debug::LEVEL8) ) log()->level8()
191#endif
192#ifndef mylog9
193#define mylog9 if( log()->debugging(Debug::LEVEL9) ) log()->level9()
194#endif
195#ifndef mylogany
196#define mylogany log()->any()
197#endif
198 };
199 // ----------------------------------------------------------------------
200} // end of namespace uniset
201// --------------------------------------------------------------------------
202#endif
Определения MessageType.h:127
Определения Calibration.h:27
long ObjectId
Определения UniSetTypes_i.idl:30
Определения JHttpServer.h:77
Определения JHttpServer.h:94
Определения JHttpServer.h:86
Определения JSEngine.h:30