Commit 36839d01 authored by Pavel Vainerman's avatar Pavel Vainerman

backported to p9 as 2.9.4-alt0.M90P.0.1 (with rpmbph script)

parents c4d818e4 ddb69cc9
......@@ -26,8 +26,8 @@
%define oname uniset2
Name: libuniset2
Version: 2.9.3
Release: alt1.M90P.2
Version: 2.9.4
Release: alt0.M90P.0.1
Summary: UniSet - library for building distributed industrial control systems
License: LGPL-2.1
......@@ -185,6 +185,7 @@ Obsoletes: %name-extentions-devel
%description extension-common-devel
Libraries needed to develop for uniset extensions
%if_enabled api
%if_enabled uresolver
%package extension-uresolver
Group: Development/Tools
......@@ -193,6 +194,16 @@ Summary: CORBA object reference resolver based on http
%description extension-uresolver
CORBA object reference resolver based on http
%endif
%endif
%if_enabled api
%package extension-wsgate
Group: Development/Tools
Summary: Websocket gate for uniset
%description extension-wsgate
Websocket gate for uniset
%endif
%if_enabled mysql
%package extension-mysql
......@@ -537,6 +548,11 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
%_bindir/%oname-httpresolver*
%endif
%if_enabled api
%files extension-wsgate
%_bindir/%oname-wsgate*
%endif
%files extension-common-devel
%dir %_includedir/%oname/extensions
%_includedir/%oname/extensions/*.*
......@@ -560,7 +576,7 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
# history of current unpublished changes
%changelog
* Fri Feb 12 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt1.M90P.2
* Fri Mar 05 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.4-alt0.M90P.0.1
- backport to ALTLinux p9 (by rpmbph script)
* Sun Jan 31 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt2
......@@ -569,6 +585,9 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
* Thu Jan 14 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt1
- minor fixes (supported old omniORB)
* Wed Jan 13 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt0.1
- test build for websocketgate
* Sat Jan 09 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.2-alt1
- admin: added 'sinfo' function
- admin: freezeValue -> freeze/unfreeze
......
......@@ -594,6 +594,10 @@ AC_CONFIG_FILES([Makefile
extensions/HttpResolver/Makefile
extensions/HttpResolver/tests/Makefile
extensions/UWebSocketGate/Makefile
<<<<<<< HEAD
=======
extensions/UWebSocketGate/tests/Makefile
>>>>>>> 2.9.4-alt0.1
testsuite/Makefile
wrappers/Makefile
wrappers/python/lib/Makefile
......
......@@ -7,7 +7,11 @@ SUBDIRS = lib include SharedMemory SharedMemory/tests IOControl IOControl/tests
ModbusMaster ModbusSlave SMViewer UniNetwork UNetUDP UNetUDP/tests \
DBServer-MySQL DBServer-SQLite DBServer-PostgreSQL MQTTPublisher \
RRDServer tests ModbusMaster/tests ModbusSlave/tests LogDB LogDB/tests \
<<<<<<< HEAD
Backend-OpenTSDB HttpResolver HttpResolver/tests UWebSocketGate
=======
Backend-OpenTSDB HttpResolver HttpResolver/tests UWebSocketGate UWebSocketGate/tests
>>>>>>> 2.9.4-alt0.1
pkgconfigdir = $(libdir)/pkgconfig
......
<<<<<<< HEAD
=======
if ENABLE_REST_API
>>>>>>> 2.9.4-alt0.1
bin_PROGRAMS = @PACKAGE@-wsgate
@PACKAGE@_wsgate_LDADD = $(top_builddir)/lib/libUniSet2.la
@PACKAGE@_wsgate_SOURCES = UWebSocketGate.cc main.cc
include $(top_builddir)/include.mk
<<<<<<< HEAD
=======
endif
>>>>>>> 2.9.4-alt0.1
......@@ -66,6 +66,7 @@ UWebSocketGate::UWebSocketGate( uniset::ObjectId id, xmlNode* cnode, const strin
sigINT.set<UWebSocketGate, &UWebSocketGate::onTerminate>(this);
iocheck.set<UWebSocketGate, &UWebSocketGate::checkMessages>(this);
<<<<<<< HEAD
#ifndef DISABLE_REST_API
wsHeartbeatTime_sec = (float)conf->getArgPInt("--" + prefix + "ws-heartbeat-time", it.getProp("wsPingTime"), wsHeartbeatTime_sec) / 1000.0;
wsSendTime_sec = (float)conf->getArgPInt("--" + prefix + "ws-send-time", it.getProp("wsSendTime"), wsSendTime_sec) / 1000.0;
......@@ -73,6 +74,27 @@ UWebSocketGate::UWebSocketGate( uniset::ObjectId id, xmlNode* cnode, const strin
httpHost = conf->getArgParam("--" + prefix + "httpserver-host", "localhost");
httpPort = conf->getArgPInt("--" + prefix + "httpserver-port", 8080);
=======
maxMessagesProcessing = conf->getArgPInt("--" + prefix + "max-messages-processing", conf->getField("maxMessagesProcessing"), maxMessagesProcessing);
if( maxMessagesProcessing < 0 )
maxMessagesProcessing = 100;
check_sec = (float)conf->getArgPInt("--" + prefix + "msg-check-time", it.getProp("msgCheckTime"), int(check_sec * 1000.0)) / 1000.0;
int sz = conf->getArgPInt("--uniset-object-size-message-queue", conf->getField("SizeOfMessageQueue"), 10000);
if( sz > 0 )
setMaxSizeOfMessageQueue(sz);
#ifndef DISABLE_REST_API
wsHeartbeatTime_sec = (float)conf->getArgPInt("--" + prefix + "ws-heartbeat-time", it.getProp("wsHeartbeatTimeTime"), int(wsHeartbeatTime_sec * 1000)) / 1000.0;
wsSendTime_sec = (float)conf->getArgPInt("--" + prefix + "ws-send-time", it.getProp("wsSendTime"), int(wsSendTime_sec * 1000.0)) / 1000.0;
wsMaxSend = conf->getArgPInt("--" + prefix + "ws-max-send", it.getProp("wsMaxSend"), wsMaxSend);
wsMaxCmd = conf->getArgPInt("--" + prefix + "ws-max-cmd", it.getProp("wsMaxCmd"), wsMaxCmd);
httpHost = conf->getArgParam("--" + prefix + "httpserver-host", "localhost");
httpPort = conf->getArgPInt("--" + prefix + "httpserver-port", 8081);
>>>>>>> 2.9.4-alt0.1
httpCORS_allow = conf->getArgParam("--" + prefix + "httpserver-cors-allow", "*");
mylog1 << myname << "(init): http server parameters " << httpHost << ":" << httpPort << endl;
......@@ -146,20 +168,38 @@ void UWebSocketGate::checkMessages( ev::timer& t, int revents )
if( EV_ERROR & revents )
return;
<<<<<<< HEAD
auto m = receiveMessage();
if( m )
processingMessage(m.get());
=======
for( int i = 0; i < maxMessagesProcessing; i++ )
{
auto m = receiveMessage();
if( !m )
break;
processingMessage(m.get());
}
>>>>>>> 2.9.4-alt0.1
}
//--------------------------------------------------------------------------------------------
void UWebSocketGate::sensorInfo( const SensorMessage* sm )
{
uniset_rwmutex_wrlock lock(wsocksMutex);
<<<<<<< HEAD
=======
mylog5 << myname << "(sensorInfo): sid=" << sm->id << " val=" << sm->value << endl;
>>>>>>> 2.9.4-alt0.1
for( auto&& s : wsocks )
s->sensorInfo(sm);
}
//--------------------------------------------------------------------------------------------
<<<<<<< HEAD
UWebSocketGate::RespondFormat UWebSocketGate::from_string(const string& str)
{
if( str == "json" )
......@@ -192,13 +232,34 @@ UTCPCore::Buffer* UWebSocketGate::to_json( const SensorMessage* sm, const std::s
{
Poco::JSON::Object::Ptr json = new Poco::JSON::Object();
=======
Poco::JSON::Object::Ptr UWebSocketGate::UWebSocket::to_short_json( sinfo* si )
{
Poco::JSON::Object::Ptr json = new Poco::JSON::Object();
json->set("type", "ShortSensorInfo");
json->set("error", si->err);
json->set("id", si->id);
json->set("value", si->value);
return json;
}
//--------------------------------------------------------------------------------------------
Poco::JSON::Object::Ptr UWebSocketGate::to_json( const SensorMessage* sm, const std::string& err )
{
Poco::JSON::Object::Ptr json = new Poco::JSON::Object();
json->set("type", "SensorInfo");
>>>>>>> 2.9.4-alt0.1
json->set("error", err);
json->set("id", sm->id);
json->set("value", sm->value);
json->set("name", uniset::ORepHelpers::getShortName(uniset_conf()->oind->getMapName(sm->id)));
json->set("sm_tv_sec", sm->sm_tv.tv_sec);
json->set("sm_tv_nsec", sm->sm_tv.tv_nsec);
<<<<<<< HEAD
json->set("type", uniset::iotype2str(sm->sensor_type));
=======
json->set("iotype", uniset::iotype2str(sm->sensor_type));
>>>>>>> 2.9.4-alt0.1
json->set("undefined", sm->undefined );
json->set("supplier", sm->supplier );
json->set("tv_sec", sm->tm.tv_sec);
......@@ -212,6 +273,7 @@ UTCPCore::Buffer* UWebSocketGate::to_json( const SensorMessage* sm, const std::s
calibr->set("rmax", sm->ci.maxRaw);
calibr->set("precision", sm->ci.precision);
<<<<<<< HEAD
ostringstream out;
json->stringify(out);
return new UTCPCore::Buffer(out.str());
......@@ -238,6 +300,9 @@ UTCPCore::Buffer* UWebSocketGate::to_txt( const SensorMessage* sm, const std::st
UTCPCore::Buffer* UWebSocketGate::to_raw( const SensorMessage* sm, const std::string& err )
{
return new UTCPCore::Buffer( (const unsigned char*)(sm), sizeof(*sm) );
=======
return json;
>>>>>>> 2.9.4-alt0.1
}
//--------------------------------------------------------------------------------------------
std::shared_ptr<UWebSocketGate> UWebSocketGate::init_wsgate( int argc, const char* const* argv, const std::string& prefix )
......@@ -256,13 +321,21 @@ std::shared_ptr<UWebSocketGate> UWebSocketGate::init_wsgate( int argc, const cha
void UWebSocketGate::help_print()
{
cout << "Default: prefix='ws'" << endl;
<<<<<<< HEAD
cout << "--prefix-name name - Имя. Для поиска настроечной секции в configure.xml" << endl;
=======
cout << "--prefix-name name - Имя. Для поиска настроечной секции в configure.xml" << endl;
cout << "--uniset-object-size-message-queue num - Размер uniset-очереди сообщений" << endl;
cout << "--prefix-msg-check-time msec - Период опроса uniset-очереди сообщений, для обработки новых сообщений. По умолчанию: 10 мсек" << endl;
cout << "--prefix-max-messages-processing num - Количество uniset-сообщений обрабатывамых за один раз. По умолчанию 50. По умолчанию: 100" << endl;
>>>>>>> 2.9.4-alt0.1
cout << "websockets: " << endl;
cout << "--prefix-ws-max num - Максимальное количество websocket-ов" << endl;
cout << "--prefix-ws-heartbeat-time msec - Период сердцебиения в соединении. По умолчанию: 3000 мсек" << endl;
cout << "--prefix-ws-send-time msec - Период посылки сообщений. По умолчанию: 500 мсек" << endl;
cout << "--prefix-ws-max num - Максимальное число сообщений посылаемых за один раз. По умолчанию: 200" << endl;
<<<<<<< HEAD
cout << "http: " << endl;
cout << "--prefix-httpserver-host ip - IP на котором слушает http сервер. По умолчанию: localhost" << endl;
......@@ -270,6 +343,16 @@ void UWebSocketGate::help_print()
cout << "--prefix-httpserver-max-queued num - Размер очереди запросов к http серверу. По умолчанию: 100" << endl;
cout << "--prefix-httpserver-max-threads num - Разрешённое количество потоков для http-сервера. По умолчанию: 3" << endl;
cout << "--prefix-httpserver-cors-allow addr - (CORS): Access-Control-Allow-Origin. Default: *" << endl;
=======
cout << "--prefix-ws-cmd num - Максимальное число команд обрабатываемых за один раз. По умолчанию: 100" << endl;
cout << "http: " << endl;
cout << "--prefix-httpserver-host ip - IP на котором слушает http сервер. По умолчанию: localhost" << endl;
cout << "--prefix-httpserver-port num - Порт на котором принимать запросы. По умолчанию: 8080" << endl;
cout << "--prefix-httpserver-max-queued num - Размер очереди запросов к http серверу. По умолчанию: 100" << endl;
cout << "--prefix-httpserver-max-threads num - Разрешённое количество потоков для http-сервера. По умолчанию: 3" << endl;
cout << "--prefix-httpserver-cors-allow addr - (CORS): Access-Control-Allow-Origin. Default: *" << endl;
>>>>>>> 2.9.4-alt0.1
}
// -----------------------------------------------------------------------------
void UWebSocketGate::run( bool async )
......@@ -426,6 +509,7 @@ void UWebSocketGate::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net
// проверка подключения к страничке со списком websocket-ов
if( !seg.empty() && seg[0] == "wsgate" )
{
<<<<<<< HEAD
if( seg.size() > 2 )
{
if( seg[1] == "json" || seg[1] == "txt" || seg[1] == "raw" )
......@@ -469,11 +553,37 @@ void UWebSocketGate::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net
return;
}
=======
ostringstream params;
auto qp = uri.getQueryParameters();
int i = 0;
for( const auto& p : qp )
{
if( i > 0 )
params << "&";
params << p.first;
if( !p.second.empty() )
params << "=" << p.second;
i++;
}
httpWebSocketConnectPage(out, req, resp, params.str());
out.flush();
return;
>>>>>>> 2.9.4-alt0.1
}
// default page
httpWebSocketPage(out, req, resp);
<<<<<<< HEAD
=======
>>>>>>> 2.9.4-alt0.1
out.flush();
}
// -----------------------------------------------------------------------------
......@@ -508,7 +618,11 @@ void UWebSocketGate::onWebSocketSession(Poco::Net::HTTPServerRequest& req, Poco:
mylog3 << req.getHost() << ": WSOCKET: " << uri.getQuery() << endl;
<<<<<<< HEAD
// example: ws://host:port/wsgate/?s1,s2,s3,s4&format=[json,txt,raw]
=======
// example: ws://host:port/wsgate/?s1,s2,s3,s4
>>>>>>> 2.9.4-alt0.1
if( seg.empty() || seg[0] != "wsgate" )
{
resp.setStatus(HTTPResponse::HTTP_BAD_REQUEST);
......@@ -516,7 +630,11 @@ void UWebSocketGate::onWebSocketSession(Poco::Net::HTTPServerRequest& req, Poco:
resp.setStatusAndReason(HTTPResponse::HTTP_BAD_REQUEST);
resp.setContentLength(0);
std::ostream& err = resp.send();
<<<<<<< HEAD
err << "Bad request. Must be: ws://host:port/wsgate/?s1,s2,s3,s4&format=[json,txt,raw]";
=======
err << "Bad request. Must be: ws://host:port/wsgate/?s1,s2,s3,s4";
>>>>>>> 2.9.4-alt0.1
err.flush();
return;
}
......@@ -577,22 +695,30 @@ std::shared_ptr<UWebSocketGate::UWebSocket> UWebSocketGate::newWebSocket( Poco::
std::shared_ptr<UWebSocket> ws;
<<<<<<< HEAD
RespondFormat fmt = RespondFormat::JSON;
=======
>>>>>>> 2.9.4-alt0.1
std::string slist("");
for( const auto& p : qp )
{
<<<<<<< HEAD
// обрабатываем только первый встреченный параметр
if( p.first == "format" )
fmt = from_string(p.second);
else if( p.second.empty() && !p.first.empty() )
=======
if( p.second.empty() && !p.first.empty() )
>>>>>>> 2.9.4-alt0.1
slist += ("," + p.first);
}
if( qp.size() == 1 && qp[0].first.empty() )
slist = qp[0].first;
<<<<<<< HEAD
// auto idlist = uniset::explode(slist);
#warning DEBUG
auto idlist = uniset::explode("34,23,54");
......@@ -611,6 +737,24 @@ std::shared_ptr<UWebSocketGate::UWebSocket> UWebSocketGate::newWebSocket( Poco::
return nullptr;
}
=======
auto idlist = uniset::explode(slist);
// if( idlist.empty() )
// {
// resp->setStatus(HTTPResponse::HTTP_BAD_REQUEST);
// resp->setContentType("text/html");
// resp->setStatusAndReason(HTTPResponse::HTTP_BAD_REQUEST);
// resp->setContentLength(0);
// std::ostream& err = resp->send();
// err << "Error: no list of sensors for '" << slist << "'. Use: http://host:port/wsgate/?s1,s2,s3";
// err.flush();
// mywarn << myname << "(newWebSocket): error: no list of sensors for '" << slist << "'" << endl;
// return nullptr;
// }
>>>>>>> 2.9.4-alt0.1
{
uniset_rwmutex_wrlock lock(wsocksMutex);
......@@ -618,6 +762,7 @@ std::shared_ptr<UWebSocketGate::UWebSocket> UWebSocketGate::newWebSocket( Poco::
ws->setHearbeatTime(wsHeartbeatTime_sec);
ws->setSendPeriod(wsSendTime_sec);
ws->setMaxSendCount(wsMaxSend);
<<<<<<< HEAD
ws->mylog = mylog;
ws->setRespondFormat(fmt);
......@@ -629,6 +774,15 @@ std::shared_ptr<UWebSocketGate::UWebSocket> UWebSocketGate::newWebSocket( Poco::
si.id = i;
si.cmd = "ask";
ws->add(si);
=======
ws->setMaxCmdCount(wsMaxCmd);
ws->mylog = mylog;
for( const auto& i : idlist.getList() )
{
mylog3 << myname << ": ask sid=" << i << endl;
ws->ask(i);
>>>>>>> 2.9.4-alt0.1
}
wsocks.emplace_back(ws);
......@@ -655,7 +809,11 @@ void UWebSocketGate::delWebSocket(std::shared_ptr<UWebSocket>& ws )
}
}
// -----------------------------------------------------------------------------
<<<<<<< HEAD
const std::string UWebSocketGate::UWebSocket::ping_str = { "." };
=======
const std::string UWebSocketGate::UWebSocket::ping_str = { "{\"data\": [{\"type\": \"Ping\"}]}" };
>>>>>>> 2.9.4-alt0.1
UWebSocketGate::UWebSocket::UWebSocket(Poco::Net::HTTPServerRequest* _req,
Poco::Net::HTTPServerResponse* _resp):
......@@ -716,10 +874,47 @@ void UWebSocketGate::UWebSocket::send( ev::timer& t, int revents )
if( EV_ERROR & revents )
return;
<<<<<<< HEAD
for( size_t i = 0; !wbuf.empty() && i < maxsend && !cancelled; i++ )
write();
// read(iorecv,revents);
=======
if( !jbuf.empty() )
{
// сперва формируем очередной пакет(поток байт) из накопившихся данных для отправки
ostringstream out;
out << "{\"data\":[";
size_t i = 0;
for( ; !jbuf.empty() && !cancelled; i++ )
{
if( i > 0 )
out << ",";
auto json = jbuf.front();
jbuf.pop();
if( !json )
continue;
json->stringify(out);
}
out << "]}";
wbuf.emplace( new UTCPCore::Buffer(std::move(out.str())) );
mylog4 << req->clientAddress().toString() << "(write): batch " << i << " objects" << endl;
}
// реальная посылка данных
for( size_t i = 0; !wbuf.empty() && i < maxsend && !cancelled; i++ )
{
write();
}
>>>>>>> 2.9.4-alt0.1
}
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::ping( ev::timer& t, int revents )
......@@ -810,21 +1005,38 @@ void UWebSocketGate::UWebSocket::read( ev::io& io, int revents )
}
}
// -----------------------------------------------------------------------------
<<<<<<< HEAD
void UWebSocketGate::UWebSocket::add( const sinfo& si )
{
smap[si.id] = si;
=======
void UWebSocketGate::UWebSocket::ask( uniset::ObjectId id )
{
sinfo s;
s.id = id;
s.cmd = "ask";
qcmd.push(s);
>>>>>>> 2.9.4-alt0.1
}
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::del( uniset::ObjectId id )
{
<<<<<<< HEAD
auto s = smap.find(id);
if( s != smap.end() )
s->second.cmd = "del";
=======
sinfo s;
s.id = id;
s.cmd = "del";
qcmd.push(s);
>>>>>>> 2.9.4-alt0.1
}
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::set( uniset::ObjectId id, long value )
{
<<<<<<< HEAD
auto s = smap.find(id);
if( s != smap.end() )
......@@ -832,6 +1044,21 @@ void UWebSocketGate::UWebSocket::set( uniset::ObjectId id, long value )
s->second.value = value;
s->second.cmd = "set";
}
=======
sinfo s;
s.id = id;
s.value = value;
s.cmd = "set";
qcmd.push(s);
}
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::get( uniset::ObjectId id )
{
sinfo s;
s.id = id;
s.cmd = "get";
qcmd.push(s);
>>>>>>> 2.9.4-alt0.1
}
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::sensorInfo( const uniset::SensorMessage* sm )
......@@ -844,13 +1071,21 @@ void UWebSocketGate::UWebSocket::sensorInfo( const uniset::SensorMessage* sm )
if( s == smap.end() )
return;
<<<<<<< HEAD
if( wbuf.size() > maxsize )
=======
if( jbuf.size() > maxsize )
>>>>>>> 2.9.4-alt0.1
{
mywarn << req->clientAddress().toString() << " lost messages..." << endl;
return;
}
<<<<<<< HEAD
wbuf.emplace(UWebSocketGate::format(sm, s->second.err, fmt));
=======
jbuf.emplace(UWebSocketGate::to_json(sm, s->second.err));
>>>>>>> 2.9.4-alt0.1
if( ioping.is_active() )
ioping.stop();
......@@ -858,21 +1093,59 @@ void UWebSocketGate::UWebSocket::sensorInfo( const uniset::SensorMessage* sm )
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::doCommand( const std::shared_ptr<UInterface>& ui )
{
<<<<<<< HEAD
for( auto&& io : smap )
{
auto& s = io.second;
=======
for( size_t i = 0; i < maxcmd && !qcmd.empty(); i++ )
{
auto s = qcmd.front();
qcmd.pop();
>>>>>>> 2.9.4-alt0.1
try
{
if( s.cmd == "" )
continue;
<<<<<<< HEAD
if( s.cmd == "ask" )
ui->askSensor(s.id, UniversalIO::UIONotify);
else if( s.cmd == "del" )
ui->askSensor(s.id, UniversalIO::UIODontNotify);
else if( s.cmd == "set" )
ui->setValue(s.id, s.value);
=======
mylog3 << req->clientAddress().toString() << "(doCommand): "
<< s.cmd << " sid=" << s.id
<< " value=" << s.value
<< endl;
if( s.cmd == "ask" )
{
ui->askSensor(s.id, UniversalIO::UIONotify);
smap[s.id] = s;
}
else if( s.cmd == "del" )
{
ui->askSensor(s.id, UniversalIO::UIODontNotify);
auto it = smap.find(s.id);
if( it != smap.end() )
smap.erase(it);
}
else if( s.cmd == "set" )
{
ui->setValue(s.id, s.value);
}
else if( s.cmd == "get" )
{
s.value = ui->getValue(s.id);
s.err = "";
sendShortResponse(s);
}
>>>>>>> 2.9.4-alt0.1
s.err = "";
s.cmd = "";
......@@ -880,17 +1153,53 @@ void UWebSocketGate::UWebSocket::doCommand( const std::shared_ptr<UInterface>& u
catch( std::exception& ex )
{
mycrit << "(UWebSocket::doCommand): " << ex.what() << endl;
<<<<<<< HEAD
sendError(s, ex.what());
=======
s.err = ex.what();
sendResponse(s);
>>>>>>> 2.9.4-alt0.1
}
}
}
// -----------------------------------------------------------------------------
<<<<<<< HEAD
void UWebSocketGate::UWebSocket::sendError( sinfo& si, const std::string& err )
{
uniset::SensorMessage sm(si.id, 0);
// sm.undefined = true;
si.err = err;
sensorInfo(&sm);
=======
void UWebSocketGate::UWebSocket::sendShortResponse( sinfo& si )
{
if( jbuf.size() > maxsize )
{
mywarn << req->clientAddress().toString() << " lost messages..." << endl;
return;
}
jbuf.emplace(to_short_json(&si));
if( ioping.is_active() )
ioping.stop();
}
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::sendResponse( sinfo& si )
{
uniset::SensorMessage sm(si.id, si.value);
if( jbuf.size() > maxsize )
{
mywarn << req->clientAddress().toString() << " lost messages..." << endl;
return;
}
jbuf.emplace(UWebSocketGate::to_json(&sm, si.err));
if( ioping.is_active() )
ioping.stop();
>>>>>>> 2.9.4-alt0.1
}
// -----------------------------------------------------------------------------
void UWebSocketGate::UWebSocket::onCommand( const string& cmdtxt )
......@@ -911,6 +1220,10 @@ void UWebSocketGate::UWebSocket::onCommand( const string& cmdtxt )
for( const auto& i : idlist )
set(i.si.id, i.val);
<<<<<<< HEAD
=======
// уведомление о новой команде
>>>>>>> 2.9.4-alt0.1
cmdsignal->send();
}
else if( cmd == "ask" )
......@@ -921,6 +1234,7 @@ void UWebSocketGate::UWebSocket::onCommand( const string& cmdtxt )
auto idlist = uniset::explode(params);
for( const auto& id : idlist.getList() )
<<<<<<< HEAD
{
sinfo s;
s.id = id;
......@@ -929,6 +1243,11 @@ void UWebSocketGate::UWebSocket::onCommand( const string& cmdtxt )
}
// даём команду на перезаказ датчиков
=======
ask(id);
// уведомление о новой команде
>>>>>>> 2.9.4-alt0.1
cmdsignal->send();
}
else if( cmd == "del" )
......@@ -941,7 +1260,24 @@ void UWebSocketGate::UWebSocket::onCommand( const string& cmdtxt )
for( const auto& id : idlist.getList() )
del(id);
<<<<<<< HEAD
// даём команду на перезаказ датчиков
=======
// уведомление о новой команде
cmdsignal->send();
}
else if( cmd == "get" )
{
myinfo << "(websocket): " << req->clientAddress().toString()
<< "(get): " << params << endl;
auto idlist = uniset::explode(params);
for( const auto& id : idlist.getList() )
get(id);
// уведомление о новой команде
>>>>>>> 2.9.4-alt0.1
cmdsignal->send();
}
}
......@@ -970,7 +1306,11 @@ void UWebSocketGate::UWebSocket::write()
int flags = WebSocket::FRAME_TEXT;
<<<<<<< HEAD
if( msg->len == 1 ) // это пинг состоящий из "."
=======
if( msg->len == ping_str.size() )
>>>>>>> 2.9.4-alt0.1
flags = WebSocket::FRAME_FLAG_FIN | WebSocket::FRAME_OP_PING;
try
......@@ -1089,9 +1429,16 @@ void UWebSocketGate::UWebSocket::setMaxSendCount( size_t val )
maxsend = val;
}
// -----------------------------------------------------------------------------
<<<<<<< HEAD
void UWebSocketGate::UWebSocket::setRespondFormat( UWebSocketGate::RespondFormat f )
{
fmt = f;
=======
void UWebSocketGate::UWebSocket::setMaxCmdCount( size_t val )
{
if( val > 0 )
maxcmd = val;
>>>>>>> 2.9.4-alt0.1
}
// -----------------------------------------------------------------------------
void UWebSocketGate::httpWebSocketPage( std::ostream& ostr, Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPServerResponse& resp )
......@@ -1113,12 +1460,16 @@ void UWebSocketGate::httpWebSocketPage( std::ostream& ostr, Poco::Net::HTTPServe
ostr << " <li><a target='_blank' href=\"http://"
<< req.serverAddress().toString()
<<<<<<< HEAD
<< "/wsgate/json\">42,30,1042 [json]</a></li>"
<< endl;
ostr << " <li><a target='_blank' href=\"http://"
<< req.serverAddress().toString()
<< "/wsgate/txt\">42,30,1042 [txt]</a></li>"
=======
<< "/wsgate/?42,30,1042\">42,30,1042</a></li>"
>>>>>>> 2.9.4-alt0.1
<< endl;
ostr << "</ul>" << endl;
......@@ -1162,7 +1513,11 @@ void UWebSocketGate::httpWebSocketConnectPage( ostream& ostr,
ostr << "{" << endl;
ostr << " if (\"WebSocket\" in window)" << endl;
ostr << " {" << endl;
<<<<<<< HEAD
ostr << " var ws = new WebSocket(\"ws://" << req.serverAddress().toString() << "/wsgate/\");" << endl;
=======
ostr << " var ws = new WebSocket(\"ws://" << req.serverAddress().toString() << "/wsgate/?" << params << "\");" << endl;
>>>>>>> 2.9.4-alt0.1
ostr << "setInterval(send_cmd, 1000);" << endl;
ostr << " var l = document.getElementById('logname');" << endl;
ostr << " l.innerHTML = '*'" << endl;
......@@ -1189,7 +1544,11 @@ void UWebSocketGate::httpWebSocketConnectPage( ostream& ostr,
ostr << " }" << endl;
ostr << "function send_cmd() {" << endl;
<<<<<<< HEAD
ostr << " ws.send( 'set:12,32,34' );" << endl;
=======
// ostr << " ws.send( 'set:12,32,34' );" << endl;
>>>>>>> 2.9.4-alt0.1
ostr << "}" << endl;
ostr << "}" << endl;
......
......@@ -55,13 +55,21 @@ namespace uniset
об изменнии датчиков, а так же изменять состояние (см. \ref sec_UWebSocketGate_Command).
Подключение к websocket-у доступно по адресу:
\code
<<<<<<< HEAD
ws://host:port/wsgate/?s1,s2,s3,s4&format=[json,txt,raw]
=======
ws://host:port/wsgate/
>>>>>>> 2.9.4-alt0.1
\endcode
Помимо этого UWebSocketGate работает в режиме мониторинга изменений датчиков.
Для этого достаточно зайти на страничку по адресу:
\code
<<<<<<< HEAD
http://host:port/wsgate/?s1,s2,s3,s4&format=[json,txt,raw]
=======
http://host:port/wsgate/?s1,s2,s3,s4
>>>>>>> 2.9.4-alt0.1
\endcode
\section sec_UWebSocketGate_Conf Конфигурирование UWebSocketGate
......@@ -75,7 +83,93 @@ namespace uniset
\section sec_UWebSocketGate_DETAIL UWebSocketGate: Технические детали
Вся релизация построена на "однопоточном" eventloop. Если датчики долго не меняются, то периодически посылается "ping" сообщение.
<<<<<<< HEAD
\section sec_UWebSocketGate_Command Команды
=======
\section sec_UWebSocketGate_Messages Сообщения
Общий формат сообщений
\code
{
"data": [
{
"type": "SensorInfo",
...
},
{
"type": "SensorInfo",
...
},
{
"type": "OtherType",
...
},
{
"type": "YetAnotherType",
...
},
]}
\endcode
Example
\code
{
"data": [
{
"type": "SensorInfo",
"tv_nsec": 343079769,
"tv_sec": 1614521238,
"value": 63
"sm_tv_nsec": 976745544,
"sm_tv_sec": 1614520060,
"sm_type": "AI",
"error": "",
"id": 10,
"name": "AI_AS",
"node": 3000,
"supplier": 5003,
"undefined": false,
"calibration": {
"cmax": 0,
"cmin": 0,
"precision": 3,
"rmax": 0,
"rmin": 0
},
}]
}
\endcode
\section sec_UWebSocketGate_Get Get
Функция get возвращает результат в укороченном формате
\code
{
"data": [
{
"type": "ShortSensorInfo",
"value": 63
"error": "",
"id": 10,
},
}]
}
\endcode
\section sec_UWebSocketGate_Ping Ping
Для того, чтобы соединение не закрывалось при отсутствии данных, каждые ping_sec посылается
специальное сообщение
\code
{
"data": [
{"type": "Ping"}
]
}
\endcode
По умолчанию каждый 3 секунды, но время можно задавать параметром "wsHeartbeatTime" (msec)
или аргументом командной строки
--prefix-ws-heartbeat-time msec
\section sec_UWebSocketGate_Command Команды
>>>>>>> 2.9.4-alt0.1
Через websocket можно посылать команды.
На текущий момент формат команды строковый.
Т.е. для подачи команды, необходимо послать просто строку.
......@@ -84,9 +178,13 @@ namespace uniset
- "set:id1=val1,id2=val2,name3=val4,..." - выставить значение датчиков
- "ask:id1,id2,name3,..." - подписаться на уведомления об изменении датчиков (sensorInfo)
- "del:id1,id2,name3,..." - отказаться от уведомления об изменении датчиков
<<<<<<< HEAD
\todo Разобраться с "ping" сообщением для формата json..
\todo Настройка check_sec из командной строки и configure.xml
=======
- "get:id1,id2,name3,..." - получить текущее значение датчиков (разовое сообщение ShortSensorInfo)
>>>>>>> 2.9.4-alt0.1
*/
class UWebSocketGate:
public UniSetObject,
......@@ -149,7 +247,12 @@ namespace uniset
void checkMessages( ev::timer& t, int revents );
virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
ev::timer iocheck;
<<<<<<< HEAD
double check_sec = { 0.3 };
=======
double check_sec = { 0.05 };
int maxMessagesProcessing = { 100 };
>>>>>>> 2.9.4-alt0.1
std::shared_ptr<DebugStream> mylog;
......@@ -162,6 +265,7 @@ namespace uniset
double wsHeartbeatTime_sec = { 3.0 };
double wsSendTime_sec = { 0.5 };
size_t wsMaxSend = { 200 };
<<<<<<< HEAD
enum class RespondFormat
{
......@@ -177,6 +281,11 @@ namespace uniset
static UTCPCore::Buffer* to_json( const uniset::SensorMessage* sm, const std::string& err );
static UTCPCore::Buffer* to_txt( const uniset::SensorMessage* sm, const std::string& err );
static UTCPCore::Buffer* to_raw( const uniset::SensorMessage* sm, const std::string& err );
=======
size_t wsMaxCmd = { 100 };
static Poco::JSON::Object::Ptr to_json( const uniset::SensorMessage* sm, const std::string& err );
>>>>>>> 2.9.4-alt0.1
/*! класс реализует работу с websocket через eventloop
* Из-за того, что поступление логов может быть достаточно быстрым
......@@ -209,11 +318,22 @@ namespace uniset
long value = { 0 }; // set value
};
<<<<<<< HEAD
void add( const sinfo& si );
void del( uniset::ObjectId id );
void set( uniset::ObjectId id, long value );
void sensorInfo( const uniset::SensorMessage* sm );
void doCommand( const std::shared_ptr<UInterface>& ui );
=======
void ask( uniset::ObjectId id );
void del( uniset::ObjectId id );
void get( uniset::ObjectId id );
void set( uniset::ObjectId id, long value );
void sensorInfo( const uniset::SensorMessage* sm );
void doCommand( const std::shared_ptr<UInterface>& ui );
static Poco::JSON::Object::Ptr to_short_json( sinfo* si );
>>>>>>> 2.9.4-alt0.1
void term();
......@@ -223,19 +343,32 @@ namespace uniset
void setHearbeatTime( const double& sec );
void setSendPeriod( const double& sec );
void setMaxSendCount( size_t val );
<<<<<<< HEAD
void setRespondFormat( RespondFormat f );
=======
void setMaxCmdCount( size_t val );
>>>>>>> 2.9.4-alt0.1
std::shared_ptr<DebugStream> mylog;
protected:
void write();
<<<<<<< HEAD
void sendError( sinfo& si, const std::string& err );
=======
void sendResponse( sinfo& si );
void sendShortResponse( sinfo& si );
>>>>>>> 2.9.4-alt0.1
void onCommand( const std::string& cmd );
ev::timer iosend;
double send_sec = { 0.5 };
size_t maxsend = { 200 };
<<<<<<< HEAD
=======
size_t maxcmd = { 100 };
>>>>>>> 2.9.4-alt0.1
ev::timer ioping;
double ping_sec = { 3.0 };
......@@ -252,13 +385,25 @@ namespace uniset
std::atomic_bool cancelled = { false };
std::unordered_map<uniset::ObjectId, sinfo> smap;
<<<<<<< HEAD
RespondFormat fmt = { RespondFormat::JSON };
=======
std::queue<sinfo> qcmd; // очередь команд
>>>>>>> 2.9.4-alt0.1
Poco::Net::HTTPServerRequest* req;
Poco::Net::HTTPServerResponse* resp;
<<<<<<< HEAD
// очередь данных на посылку..
std::queue<UTCPCore::Buffer*> wbuf;
=======
// очередь json-на отправку
std::queue<Poco::JSON::Object::Ptr> jbuf;
// очередь данных на посылку..
std::queue<uniset::UTCPCore::Buffer*> wbuf;
>>>>>>> 2.9.4-alt0.1
size_t maxsize; // рассчитывается сходя из max_send (см. конструктор)
};
......
if HAVE_TESTS
noinst_PROGRAMS = tests-with-sm
tests_with_sm_SOURCES = tests_with_sm.cc test_uwebsocketgate.cc $(top_builddir)/extensions/UWebSocketGate/UWebSocketGate.cc
tests_with_sm_LDADD = $(top_builddir)/lib/libUniSet2.la $(top_builddir)/extensions/lib/libUniSet2Extensions.la \
$(top_builddir)/extensions/SharedMemory/libUniSet2SharedMemory.la \
$(SIGC_LIBS) $(POCO_LIBS)
tests_with_sm_CPPFLAGS = -I$(top_builddir)/include -I$(top_builddir)/extensions/include \
-I$(top_builddir)/extensions/UWebSocketGate \
-I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(POCO_CFLAGS)
include $(top_builddir)/testsuite/testsuite-common.mk
check-local: atconfig package.m4 $(TESTSUITE) uwebsocketgate-tests.at
$(SHELL) $(TESTSUITE) $(TESTSUITEFLAGS)
clean-local:
rm -rf $(CLEANFILES)
rm -rf $(COVERAGE_REPORT_DIR)
include $(top_builddir)/include.mk
endif
#include <catch.hpp>
// -----------------------------------------------------------------------------
#include <time.h>
#include <limits>
#include <memory>
#include <iostream>
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPMessage.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/JSON/Parser.h"
#include "UniSetTypes.h"
#include "UInterface.h"
// -----------------------------------------------------------------------------
using Poco::Net::HTTPClientSession;
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPMessage;
using Poco::Net::WebSocket;
using namespace std;
using namespace uniset;
// -----------------------------------------------------------------------------
static int port = 8081;
static string addr("127.0.0.1");
static std::shared_ptr<UInterface> ui;
// -----------------------------------------------------------------------------
static void InitTest()
{
auto conf = uniset_conf();
CHECK( conf != nullptr );
if( !ui )
{
ui = std::make_shared<UInterface>();
// UI понадобиться для проверки записанных в SM значений.
CHECK( ui->getObjectIndex() != nullptr );
CHECK( ui->getConf() == conf );
}
}
// -----------------------------------------------------------------------------
TEST_CASE("[UWebSocketGate]: set", "[uwebsocketgate]")
{
InitTest();
HTTPClientSession cs(addr, port);
HTTPRequest request(HTTPRequest::HTTP_GET, "/wsgate", HTTPRequest::HTTP_1_1);
HTTPResponse response;
WebSocket ws(cs, request, response);
std::string cmd("set:1=10,2=20,3=30");
ws.sendFrame(cmd.data(), (int)cmd.size());
msleep(50);
REQUIRE( ui->getValue(1) == 10 );
REQUIRE( ui->getValue(2) == 20 );
REQUIRE( ui->getValue(3) == 30 );
cmd = "set:1=11,2=21,3=31";
ws.sendFrame(cmd.data(), (int)cmd.size());
msleep(50);
REQUIRE( ui->getValue(1) == 11 );
REQUIRE( ui->getValue(2) == 21 );
REQUIRE( ui->getValue(3) == 31 );
}
// -----------------------------------------------------------------------------
TEST_CASE("[UWebSocketGate]: ask", "[uwebsocketgate]")
{
InitTest();
HTTPClientSession cs(addr, port);
HTTPRequest request(HTTPRequest::HTTP_GET, "/wsgate", HTTPRequest::HTTP_1_1);
HTTPResponse response;
WebSocket ws(cs, request, response);
ui->setValue(1, 1);
ui->setValue(2, 42);
ui->setValue(3, 42);
std::string cmd("ask:1,2,3");
ws.sendFrame(cmd.data(), (int)cmd.size());
char buffer[1024] = {};
int flags;
ws.receiveFrame(buffer, sizeof(buffer), flags);
REQUIRE(flags == WebSocket::FRAME_TEXT);
Poco::JSON::Parser parser;
auto result = parser.parse(buffer);
Poco::JSON::Object::Ptr json = result.extract<Poco::JSON::Object::Ptr>();
REQUIRE(json);
// {
// "data": [
// {"type": "SensorInfo"...},
// {"type": "SensorInfo"...},
// {"type": "SensorInfo"...}
// ...
// ]
// }
auto jdata = json->get("data").extract<Poco::JSON::Array::Ptr>();
REQUIRE(jdata);
REQUIRE(jdata->size() == 3);
for( int i = 0; i < 3; i++ )
{
auto j = jdata->getObject(i);
REQUIRE(j);
REQUIRE( j->get("type").convert<std::string>() == "SensorInfo" );
long id = j->get("id").convert<long>();
if( id == 1 )
{
REQUIRE( j->get("iotype").convert<std::string>() == "DI" );
REQUIRE( j->get("value").convert<long>() == 1 );
}
else
{
REQUIRE( j->get("iotype").convert<std::string>() == "AI" );
REQUIRE( j->get("value").convert<long>() == 42 );
}
}
// sensorInfo
ui->setValue(2, 84);
memset(buffer, 0, sizeof(buffer));
ws.receiveFrame(buffer, sizeof(buffer), flags);
REQUIRE(flags == WebSocket::FRAME_TEXT);
result = parser.parse(buffer);
json = result.extract<Poco::JSON::Object::Ptr>();
REQUIRE(json);
jdata = json->get("data").extract<Poco::JSON::Array::Ptr>();
REQUIRE(jdata);
REQUIRE(jdata->size() == 1);
auto j = jdata->getObject(0);
REQUIRE(j);
REQUIRE( j->get("type").convert<std::string>() == "SensorInfo" );
REQUIRE( j->get("iotype").convert<std::string>() == "AI" );
REQUIRE( j->get("value").convert<long>() == 84 );
}
// -----------------------------------------------------------------------------
TEST_CASE("[UWebSocketGate]: del", "[uwebsocketgate]")
{
InitTest();
HTTPClientSession cs(addr, port);
HTTPRequest request(HTTPRequest::HTTP_GET, "/wsgate", HTTPRequest::HTTP_1_1);
HTTPResponse response;
WebSocket ws(cs, request, response);
ui->setValue(1, 1);
std::string cmd("ask:1");
ws.sendFrame(cmd.data(), (int)cmd.size());
char buffer[1024] = {};
int flags;
ws.receiveFrame(buffer, sizeof(buffer), flags);
REQUIRE(flags == WebSocket::FRAME_TEXT);
cmd = ("del:1");
ws.sendFrame(cmd.data(), (int)cmd.size());
msleep(100);
ui->setValue(1, 0);
memset(buffer, 0, sizeof(buffer));
ws.receiveFrame(buffer, sizeof(buffer), flags);
string str(buffer);
REQUIRE( str.find("Ping") != string::npos );
}
// -----------------------------------------------------------------------------
TEST_CASE("[UWebSocketGate]: get", "[uwebsocketgate]")
{
InitTest();
HTTPClientSession cs(addr, port);
HTTPRequest request(HTTPRequest::HTTP_GET, "/wsgate", HTTPRequest::HTTP_1_1);
HTTPResponse response;
WebSocket ws(cs, request, response);
ui->setValue(1, 111);
ui->setValue(2, 222);
ui->setValue(3, 333);
std::string cmd("get:1,2,3");
ws.sendFrame(cmd.data(), (int)cmd.size());
char buffer[1024] = {};
int flags;
memset(buffer, 0, sizeof(buffer));
ws.receiveFrame(buffer, sizeof(buffer), flags);
REQUIRE(flags == WebSocket::FRAME_TEXT);
Poco::JSON::Parser parser;
auto result = parser.parse(buffer);
Poco::JSON::Object::Ptr json = result.extract<Poco::JSON::Object::Ptr>();
REQUIRE(json);
// {
// "data": [
// {"type": "ShortSensorInfo"...},
// {"type": "ShortSensorInfo"...},
// {"type": "ShortSensorInfo"...},
// ...
// ]
// }
auto jdata = json->get("data").extract<Poco::JSON::Array::Ptr>();
REQUIRE(jdata);
REQUIRE(jdata->size() == 3);
for( int i = 0; i < 3; i++ )
{
auto j = jdata->getObject(i);
REQUIRE(j);
REQUIRE( j->get("type").convert<std::string>() == "ShortSensorInfo" );
long id = j->get("id").convert<long>();
if( id == 1 )
{
REQUIRE( j->get("value").convert<long>() == 111 );
}
else if( id == 2 )
{
REQUIRE( j->get("value").convert<long>() == 222 );
}
else if( id == 3 )
{
REQUIRE( j->get("value").convert<long>() == 333 );
}
}
}
// -----------------------------------------------------------------------------
#define CATCH_CONFIG_RUNNER
#include <catch.hpp>
#include <string>
#include "Debug.h"
#include "UniSetActivator.h"
#include "PassiveTimer.h"
#include "SharedMemory.h"
#include "Extensions.h"
#include "UWebSocketGate.h"
// --------------------------------------------------------------------------
using namespace std;
using namespace uniset;
using namespace uniset::extensions;
// --------------------------------------------------------------------------
int main(int argc, const char* argv[] )
{
try
{
Catch::Session session;
if( argc > 1 && ( strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ) )
{
cout << "--confile - Использовать указанный конф. файл. По умолчанию configure.xml" << endl;
SharedMemory::help_print(argc, argv);
cout << endl << endl << "--------------- CATCH HELP --------------" << endl;
session.showHelp("test_with_sm");
return 0;
}
int returnCode = session.applyCommandLine( argc, argv, Catch::Session::OnUnusedOptions::Ignore );
if( returnCode != 0 ) // Indicates a command line error
return returnCode;
auto conf = uniset_init(argc, argv);
bool apart = findArgParam("--apart", argc, argv) != -1;
auto shm = SharedMemory::init_smemory(argc, argv);
if( !shm )
return 1;
auto ws = UWebSocketGate::init_wsgate(argc, argv, "ws-");
if( !ws )
return 1;
auto act = UniSetActivator::Instance();
act->add(shm);
act->add(ws);
SystemMessage sm(SystemMessage::StartUp);
act->broadcast( sm.transport_msg() );
act->run(true);
int tout = 6000;
PassiveTimer pt(tout);
while( !pt.checkTime() && !act->exist() && !ws->exist() )
msleep(100);
if( !act->exist() )
{
cerr << "(tests_with_sm): SharedMemory not exist! (timeout=" << tout << ")" << endl;
return 1;
}
if( !ws->exist() )
{
cerr << "(tests_with_sm): UWebSocketGate not exist! (timeout=" << tout << ")" << endl;
return 1;
}
return session.run();
}
catch( const SystemError& err )
{
cerr << "(tests_with_sm): " << err << endl;
}
catch( const uniset::Exception& ex )
{
cerr << "(tests_with_sm): " << ex << endl;
}
catch( const std::exception& e )
{
cerr << "(tests_with_sm): " << e.what() << endl;
}
catch(...)
{
cerr << "(tests_with_sm): catch(...)" << endl;
}
return 1;
}
#!/bin/sh
# '--' - нужен для отделения аргументов catch, от наших..
cd ../../../Utilities/Admin/
./uniset2-start.sh -f ./create_links.sh
./uniset2-start.sh -f ./create
./uniset2-start.sh -f ./exist | grep -q UNISET_PLC/Controllers || exit 1
cd -
./uniset2-start.sh -f ./tests-with-sm $* -- --confile uwebsocketgate-test-configure.xml --e-startup-pause 10 \
--ws-name UWebSocketGate1 --ws-httpserverhost-addr 127.0.0.1 --ws-httpserver-port 8081
#--ws-log-add-levels any
m4_include(package.m4)
AT_COLOR_TESTS
AT_INIT([UWebSocketGate tests])
m4_include(uwebsocketgate-tests.at)
../../../Utilities/scripts/uniset2-functions.sh
\ No newline at end of file
../../../Utilities/scripts/uniset2-start.sh
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<UNISETPLC xmlns:xi="http://www.w3.org/2001/XInclude">
<UserData/>
<!-- Общие(стартовые) параметры по UniSet -->
<UniSet>
<NameService host="localhost" port="2809"/>
<LocalNode name="LocalhostNode"/>
<RootSection name="UNISET_PLC"/>
<CountOfNet name="1"/>
<RepeatCount name="3"/>
<RepeatTimeoutMS name="50"/>
<WatchDogTime name="0"/>
<PingNodeTime name="0"/>
<AutoStartUpTime name="1"/>
<DumpStateTime name="10"/>
<SleepTickMS name="500"/>
<UniSetDebug levels="" name="ulog"/>
<ConfDir name="./"/>
<DataDir name="./"/>
<BinDir name="./"/>
<LogDir name="./"/>
<DocDir name="./"/>
<LockDir name="./"/>
<Services></Services>
</UniSet>
<dlog name="dlog"/>
<settings>
<SharedMemory name="SharedMemory" shmID="SharedMemory"/>
<UWebSocketGate name="UWebSocketGate1"/>
</settings>
<ObjectsMap idfromfile="1">
<!--
Краткие пояснения к полям секции 'sensors'
==========================================
node - узел на котором физически находится данный датчик
iotype - тип датчика
priority - приоритет сообщения об изменении данного датчика
textname - текстовое имя датчика
-->
<nodes port="2809">
<item id="3000" infserver="InfoServer" ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел"/>
</nodes>
<!-- ************************ Датчики ********************** -->
<sensors name="Sensors">
<item id="1" iotype="DI" name="DI1_S" textname="DI sensor 1"/>
<item id="2" iotype="AI" name="AI1_S" textname="AI sensor 1" default="2" undefined_value="65635"/>
<item id="3" iotype="AI" name="AI2_S" textname="AI sensor 2" default="3"/>
</sensors>
<thresholds/>
<controllers name="Controllers">
<item id="5000" name="SharedMemory"/>
</controllers>
<!-- ******************* Идентификаторы сервисов ***************** -->
<services name="Services">
</services>
<!-- ******************* Идентификаторы объектов ***************** -->
<objects name="UniObjects">
<item id="6000" name="TestProc"/>
<item id="6004" name="UWebSocketGate1"/>
</objects>
</ObjectsMap>
<messages idfromfile="1" name="messages"/>
</UNISETPLC>
AT_SETUP([UWebSocketGate tests])
AT_CHECK([$abs_top_builddir/testsuite/at-test-launch.sh $abs_top_builddir/extensions/UWebSocketGate/tests tests_with_sm.sh],[0],[ignore],[ignore])
AT_CLEANUP
......@@ -14,3 +14,4 @@ m4_include(../extensions/LogicProcessor/tests/lproc-tests.at)
m4_include(../extensions/IOControl/tests/iocontrol-tests.at)
m4_include(../extensions/LogDB/tests/logdb-tests.at)
m4_include(../extensions/HttpResolver/tests/uresolver-tests.at)
m4_include(../extensions/UWebSocketGate/tests/uwebsocketgate-tests.at)
......@@ -297,6 +297,17 @@
./extensions/UniNetwork/uninet.cc
./extensions/UWebSocketGate/main.cc
./extensions/UWebSocketGate/Makefile.am
<<<<<<< HEAD
=======
./extensions/UWebSocketGate.old/main.cc
./extensions/UWebSocketGate.old/Makefile.am
./extensions/UWebSocketGate.old/UWebSocketGate.cc
./extensions/UWebSocketGate.old/UWebSocketGate.h
./extensions/UWebSocketGate.old/UWebSocketGateSugar.h
./extensions/UWebSocketGate/tests/Makefile.am
./extensions/UWebSocketGate/tests/tests_with_sm.cc
./extensions/UWebSocketGate/tests/test_uwebsocketgate.cc
>>>>>>> 2.9.4-alt0.1
./extensions/UWebSocketGate/UWebSocketGate.cc
./extensions/UWebSocketGate/UWebSocketGate.h
./extensions/UWebSocketGate/UWebSocketGateSugar.h
......@@ -390,7 +401,6 @@
./include/UTCPStream.h
./include/VMonitor.h
./include/WDTInterface.h
./lib/dummy.cc
./lib/Makefile.am
./Makefile.am
./src/Communications/ComPort485F.cc
......@@ -555,6 +565,8 @@
./tests/umutex.cc
./tests/UniXmlTest/Makefile.am
./tests/UniXmlTest/XmlTest.cc
./tests/wasm-test/main.cc
./tests/wasm-test/Makefile.am
./uniset-config.h
./Utilities/Admin/admin.cc
./Utilities/Admin/c.cc
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment