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 @@ ...@@ -26,8 +26,8 @@
%define oname uniset2 %define oname uniset2
Name: libuniset2 Name: libuniset2
Version: 2.9.3 Version: 2.9.4
Release: alt1.M90P.2 Release: alt0.M90P.0.1
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
License: LGPL-2.1 License: LGPL-2.1
...@@ -185,6 +185,7 @@ Obsoletes: %name-extentions-devel ...@@ -185,6 +185,7 @@ Obsoletes: %name-extentions-devel
%description extension-common-devel %description extension-common-devel
Libraries needed to develop for uniset extensions Libraries needed to develop for uniset extensions
%if_enabled api
%if_enabled uresolver %if_enabled uresolver
%package extension-uresolver %package extension-uresolver
Group: Development/Tools Group: Development/Tools
...@@ -193,6 +194,16 @@ Summary: CORBA object reference resolver based on http ...@@ -193,6 +194,16 @@ Summary: CORBA object reference resolver based on http
%description extension-uresolver %description extension-uresolver
CORBA object reference resolver based on http CORBA object reference resolver based on http
%endif %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 %if_enabled mysql
%package extension-mysql %package extension-mysql
...@@ -537,6 +548,11 @@ rm -f %buildroot%_docdir/%oname/html/*.md5 ...@@ -537,6 +548,11 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
%_bindir/%oname-httpresolver* %_bindir/%oname-httpresolver*
%endif %endif
%if_enabled api
%files extension-wsgate
%_bindir/%oname-wsgate*
%endif
%files extension-common-devel %files extension-common-devel
%dir %_includedir/%oname/extensions %dir %_includedir/%oname/extensions
%_includedir/%oname/extensions/*.* %_includedir/%oname/extensions/*.*
...@@ -560,7 +576,7 @@ rm -f %buildroot%_docdir/%oname/html/*.md5 ...@@ -560,7 +576,7 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
# history of current unpublished changes # history of current unpublished changes
%changelog %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) - backport to ALTLinux p9 (by rpmbph script)
* Sun Jan 31 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt2 * Sun Jan 31 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt2
...@@ -569,6 +585,9 @@ rm -f %buildroot%_docdir/%oname/html/*.md5 ...@@ -569,6 +585,9 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
* Thu Jan 14 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt1 * Thu Jan 14 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.3-alt1
- minor fixes (supported old omniORB) - 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 * Sat Jan 09 2021 Pavel Vainerman <pv@altlinux.ru> 2.9.2-alt1
- admin: added 'sinfo' function - admin: added 'sinfo' function
- admin: freezeValue -> freeze/unfreeze - admin: freezeValue -> freeze/unfreeze
......
...@@ -594,6 +594,10 @@ AC_CONFIG_FILES([Makefile ...@@ -594,6 +594,10 @@ AC_CONFIG_FILES([Makefile
extensions/HttpResolver/Makefile extensions/HttpResolver/Makefile
extensions/HttpResolver/tests/Makefile extensions/HttpResolver/tests/Makefile
extensions/UWebSocketGate/Makefile extensions/UWebSocketGate/Makefile
<<<<<<< HEAD
=======
extensions/UWebSocketGate/tests/Makefile
>>>>>>> 2.9.4-alt0.1
testsuite/Makefile testsuite/Makefile
wrappers/Makefile wrappers/Makefile
wrappers/python/lib/Makefile wrappers/python/lib/Makefile
......
...@@ -7,7 +7,11 @@ SUBDIRS = lib include SharedMemory SharedMemory/tests IOControl IOControl/tests ...@@ -7,7 +7,11 @@ SUBDIRS = lib include SharedMemory SharedMemory/tests IOControl IOControl/tests
ModbusMaster ModbusSlave SMViewer UniNetwork UNetUDP UNetUDP/tests \ ModbusMaster ModbusSlave SMViewer UniNetwork UNetUDP UNetUDP/tests \
DBServer-MySQL DBServer-SQLite DBServer-PostgreSQL MQTTPublisher \ DBServer-MySQL DBServer-SQLite DBServer-PostgreSQL MQTTPublisher \
RRDServer tests ModbusMaster/tests ModbusSlave/tests LogDB LogDB/tests \ RRDServer tests ModbusMaster/tests ModbusSlave/tests LogDB LogDB/tests \
<<<<<<< HEAD
Backend-OpenTSDB HttpResolver HttpResolver/tests UWebSocketGate Backend-OpenTSDB HttpResolver HttpResolver/tests UWebSocketGate
=======
Backend-OpenTSDB HttpResolver HttpResolver/tests UWebSocketGate UWebSocketGate/tests
>>>>>>> 2.9.4-alt0.1
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
......
<<<<<<< HEAD
=======
if ENABLE_REST_API
>>>>>>> 2.9.4-alt0.1
bin_PROGRAMS = @PACKAGE@-wsgate bin_PROGRAMS = @PACKAGE@-wsgate
@PACKAGE@_wsgate_LDADD = $(top_builddir)/lib/libUniSet2.la @PACKAGE@_wsgate_LDADD = $(top_builddir)/lib/libUniSet2.la
@PACKAGE@_wsgate_SOURCES = UWebSocketGate.cc main.cc @PACKAGE@_wsgate_SOURCES = UWebSocketGate.cc main.cc
include $(top_builddir)/include.mk include $(top_builddir)/include.mk
<<<<<<< HEAD
=======
endif
>>>>>>> 2.9.4-alt0.1
...@@ -55,13 +55,21 @@ namespace uniset ...@@ -55,13 +55,21 @@ namespace uniset
об изменнии датчиков, а так же изменять состояние (см. \ref sec_UWebSocketGate_Command). об изменнии датчиков, а так же изменять состояние (см. \ref sec_UWebSocketGate_Command).
Подключение к websocket-у доступно по адресу: Подключение к websocket-у доступно по адресу:
\code \code
<<<<<<< HEAD
ws://host:port/wsgate/?s1,s2,s3,s4&format=[json,txt,raw] ws://host:port/wsgate/?s1,s2,s3,s4&format=[json,txt,raw]
=======
ws://host:port/wsgate/
>>>>>>> 2.9.4-alt0.1
\endcode \endcode
Помимо этого UWebSocketGate работает в режиме мониторинга изменений датчиков. Помимо этого UWebSocketGate работает в режиме мониторинга изменений датчиков.
Для этого достаточно зайти на страничку по адресу: Для этого достаточно зайти на страничку по адресу:
\code \code
<<<<<<< HEAD
http://host:port/wsgate/?s1,s2,s3,s4&format=[json,txt,raw] 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 \endcode
\section sec_UWebSocketGate_Conf Конфигурирование UWebSocketGate \section sec_UWebSocketGate_Conf Конфигурирование UWebSocketGate
...@@ -75,7 +83,93 @@ namespace uniset ...@@ -75,7 +83,93 @@ namespace uniset
\section sec_UWebSocketGate_DETAIL UWebSocketGate: Технические детали \section sec_UWebSocketGate_DETAIL UWebSocketGate: Технические детали
Вся релизация построена на "однопоточном" eventloop. Если датчики долго не меняются, то периодически посылается "ping" сообщение. Вся релизация построена на "однопоточном" eventloop. Если датчики долго не меняются, то периодически посылается "ping" сообщение.
<<<<<<< HEAD
\section sec_UWebSocketGate_Command Команды \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 можно посылать команды. Через websocket можно посылать команды.
На текущий момент формат команды строковый. На текущий момент формат команды строковый.
Т.е. для подачи команды, необходимо послать просто строку. Т.е. для подачи команды, необходимо послать просто строку.
...@@ -84,9 +178,13 @@ namespace uniset ...@@ -84,9 +178,13 @@ namespace uniset
- "set:id1=val1,id2=val2,name3=val4,..." - выставить значение датчиков - "set:id1=val1,id2=val2,name3=val4,..." - выставить значение датчиков
- "ask:id1,id2,name3,..." - подписаться на уведомления об изменении датчиков (sensorInfo) - "ask:id1,id2,name3,..." - подписаться на уведомления об изменении датчиков (sensorInfo)
- "del:id1,id2,name3,..." - отказаться от уведомления об изменении датчиков - "del:id1,id2,name3,..." - отказаться от уведомления об изменении датчиков
<<<<<<< HEAD
\todo Разобраться с "ping" сообщением для формата json.. \todo Разобраться с "ping" сообщением для формата json..
\todo Настройка check_sec из командной строки и configure.xml \todo Настройка check_sec из командной строки и configure.xml
=======
- "get:id1,id2,name3,..." - получить текущее значение датчиков (разовое сообщение ShortSensorInfo)
>>>>>>> 2.9.4-alt0.1
*/ */
class UWebSocketGate: class UWebSocketGate:
public UniSetObject, public UniSetObject,
...@@ -149,7 +247,12 @@ namespace uniset ...@@ -149,7 +247,12 @@ namespace uniset
void checkMessages( ev::timer& t, int revents ); void checkMessages( ev::timer& t, int revents );
virtual void sensorInfo( const uniset::SensorMessage* sm ) override; virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
ev::timer iocheck; ev::timer iocheck;
<<<<<<< HEAD
double check_sec = { 0.3 }; double check_sec = { 0.3 };
=======
double check_sec = { 0.05 };
int maxMessagesProcessing = { 100 };
>>>>>>> 2.9.4-alt0.1
std::shared_ptr<DebugStream> mylog; std::shared_ptr<DebugStream> mylog;
...@@ -162,6 +265,7 @@ namespace uniset ...@@ -162,6 +265,7 @@ namespace uniset
double wsHeartbeatTime_sec = { 3.0 }; double wsHeartbeatTime_sec = { 3.0 };
double wsSendTime_sec = { 0.5 }; double wsSendTime_sec = { 0.5 };
size_t wsMaxSend = { 200 }; size_t wsMaxSend = { 200 };
<<<<<<< HEAD
enum class RespondFormat enum class RespondFormat
{ {
...@@ -177,6 +281,11 @@ namespace uniset ...@@ -177,6 +281,11 @@ namespace uniset
static UTCPCore::Buffer* to_json( const uniset::SensorMessage* sm, const std::string& err ); 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_txt( const uniset::SensorMessage* sm, const std::string& err );
static UTCPCore::Buffer* to_raw( 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 /*! класс реализует работу с websocket через eventloop
* Из-за того, что поступление логов может быть достаточно быстрым * Из-за того, что поступление логов может быть достаточно быстрым
...@@ -209,11 +318,22 @@ namespace uniset ...@@ -209,11 +318,22 @@ namespace uniset
long value = { 0 }; // set value long value = { 0 }; // set value
}; };
<<<<<<< HEAD
void add( const sinfo& si ); void add( const sinfo& si );
void del( uniset::ObjectId id ); void del( uniset::ObjectId id );
void set( uniset::ObjectId id, long value ); void set( uniset::ObjectId id, long value );
void sensorInfo( const uniset::SensorMessage* sm ); void sensorInfo( const uniset::SensorMessage* sm );
void doCommand( const std::shared_ptr<UInterface>& ui ); 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(); void term();
...@@ -223,19 +343,32 @@ namespace uniset ...@@ -223,19 +343,32 @@ namespace uniset
void setHearbeatTime( const double& sec ); void setHearbeatTime( const double& sec );
void setSendPeriod( const double& sec ); void setSendPeriod( const double& sec );
void setMaxSendCount( size_t val ); void setMaxSendCount( size_t val );
<<<<<<< HEAD
void setRespondFormat( RespondFormat f ); void setRespondFormat( RespondFormat f );
=======
void setMaxCmdCount( size_t val );
>>>>>>> 2.9.4-alt0.1
std::shared_ptr<DebugStream> mylog; std::shared_ptr<DebugStream> mylog;
protected: protected:
void write(); void write();
<<<<<<< HEAD
void sendError( sinfo& si, const std::string& err ); 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 ); void onCommand( const std::string& cmd );
ev::timer iosend; ev::timer iosend;
double send_sec = { 0.5 }; double send_sec = { 0.5 };
size_t maxsend = { 200 }; size_t maxsend = { 200 };
<<<<<<< HEAD
=======
size_t maxcmd = { 100 };
>>>>>>> 2.9.4-alt0.1
ev::timer ioping; ev::timer ioping;
double ping_sec = { 3.0 }; double ping_sec = { 3.0 };
...@@ -252,13 +385,25 @@ namespace uniset ...@@ -252,13 +385,25 @@ namespace uniset
std::atomic_bool cancelled = { false }; std::atomic_bool cancelled = { false };
std::unordered_map<uniset::ObjectId, sinfo> smap; std::unordered_map<uniset::ObjectId, sinfo> smap;
<<<<<<< HEAD
RespondFormat fmt = { RespondFormat::JSON }; RespondFormat fmt = { RespondFormat::JSON };
=======
std::queue<sinfo> qcmd; // очередь команд
>>>>>>> 2.9.4-alt0.1
Poco::Net::HTTPServerRequest* req; Poco::Net::HTTPServerRequest* req;
Poco::Net::HTTPServerResponse* resp; Poco::Net::HTTPServerResponse* resp;
<<<<<<< HEAD
// очередь данных на посылку.. // очередь данных на посылку..
std::queue<UTCPCore::Buffer*> wbuf; 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 (см. конструктор) 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) ...@@ -14,3 +14,4 @@ m4_include(../extensions/LogicProcessor/tests/lproc-tests.at)
m4_include(../extensions/IOControl/tests/iocontrol-tests.at) m4_include(../extensions/IOControl/tests/iocontrol-tests.at)
m4_include(../extensions/LogDB/tests/logdb-tests.at) m4_include(../extensions/LogDB/tests/logdb-tests.at)
m4_include(../extensions/HttpResolver/tests/uresolver-tests.at) m4_include(../extensions/HttpResolver/tests/uresolver-tests.at)
m4_include(../extensions/UWebSocketGate/tests/uwebsocketgate-tests.at)
...@@ -297,6 +297,17 @@ ...@@ -297,6 +297,17 @@
./extensions/UniNetwork/uninet.cc ./extensions/UniNetwork/uninet.cc
./extensions/UWebSocketGate/main.cc ./extensions/UWebSocketGate/main.cc
./extensions/UWebSocketGate/Makefile.am ./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.cc
./extensions/UWebSocketGate/UWebSocketGate.h ./extensions/UWebSocketGate/UWebSocketGate.h
./extensions/UWebSocketGate/UWebSocketGateSugar.h ./extensions/UWebSocketGate/UWebSocketGateSugar.h
...@@ -390,7 +401,6 @@ ...@@ -390,7 +401,6 @@
./include/UTCPStream.h ./include/UTCPStream.h
./include/VMonitor.h ./include/VMonitor.h
./include/WDTInterface.h ./include/WDTInterface.h
./lib/dummy.cc
./lib/Makefile.am ./lib/Makefile.am
./Makefile.am ./Makefile.am
./src/Communications/ComPort485F.cc ./src/Communications/ComPort485F.cc
...@@ -555,6 +565,8 @@ ...@@ -555,6 +565,8 @@
./tests/umutex.cc ./tests/umutex.cc
./tests/UniXmlTest/Makefile.am ./tests/UniXmlTest/Makefile.am
./tests/UniXmlTest/XmlTest.cc ./tests/UniXmlTest/XmlTest.cc
./tests/wasm-test/main.cc
./tests/wasm-test/Makefile.am
./uniset-config.h ./uniset-config.h
./Utilities/Admin/admin.cc ./Utilities/Admin/admin.cc
./Utilities/Admin/c.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