Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
U
uniset2
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
UniSet project repositories
uniset2
Commits
3615f9fd
Commit
3615f9fd
authored
Feb 22, 2016
by
Pavel Vainerman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(MQTTPublisher): реализовал возможность преобразовывать value
в text публикуемых событий
parent
93ae5782
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
234 additions
and
12 deletions
+234
-12
test.xml
conf/test.xml
+7
-1
MQTTPublisher.cc
extensions/MQTTPublisher/MQTTPublisher.cc
+127
-10
MQTTPublisher.h
extensions/MQTTPublisher/MQTTPublisher.h
+58
-1
UniSetTypes.h
include/UniSetTypes.h
+6
-0
UniSetTypes.cc
src/ObjectRepository/UniSetTypes.cc
+18
-0
test_utypes.cc
tests/test_utypes.cc
+18
-0
No files found.
conf/test.xml
View file @
3615f9fd
...
@@ -274,7 +274,13 @@
...
@@ -274,7 +274,13 @@
<item
id=
"109"
iotype=
"DI"
name=
"MM1_Not_Respond_S"
priority=
"Medium"
textname=
"multimaster test sensor"
/>
<item
id=
"109"
iotype=
"DI"
name=
"MM1_Not_Respond_S"
priority=
"Medium"
textname=
"multimaster test sensor"
/>
<item
id=
"110"
iotype=
"DI"
name=
"MM2_Not_Respond_S"
priority=
"Medium"
textname=
"multimaster test sensor"
/>
<item
id=
"110"
iotype=
"DI"
name=
"MM2_Not_Respond_S"
priority=
"Medium"
textname=
"multimaster test sensor"
/>
<item
id=
"111"
iotype=
"AI"
name=
"MQTT_AI_AS"
textname=
"MQTT test AI"
mqtt=
"1"
/>
<item
id=
"111"
iotype=
"AI"
name=
"MQTT_AI_AS"
textname=
"MQTT test AI"
mqtt=
"1"
>
<mqtt>
<msg
value=
"1"
text=
"Hello %v"
/>
<range
min=
"2"
max=
"5"
text=
"Range Hello %v %r (min=%rmin max=%rmax)"
/>
<range
min=
"2"
max=
"3"
text=
"Range Hello %t = %v"
/>
</mqtt>
</item>
<item
id=
"112"
iotype=
"DI"
name=
"MQTT_DI_S"
textname=
"MQTT test DI"
mqtt=
"1"
/>
<item
id=
"112"
iotype=
"DI"
name=
"MQTT_DI_S"
textname=
"MQTT test DI"
mqtt=
"1"
/>
</sensors>
</sensors>
...
...
extensions/MQTTPublisher/MQTTPublisher.cc
View file @
3615f9fd
...
@@ -75,6 +75,16 @@ MQTTPublisher::MQTTPublisher(UniSetTypes::ObjectId objId, xmlNode* cnode, UniSet
...
@@ -75,6 +75,16 @@ MQTTPublisher::MQTTPublisher(UniSetTypes::ObjectId objId, xmlNode* cnode, UniSet
if
(
smTestID
==
DefaultObjectId
)
if
(
smTestID
==
DefaultObjectId
)
smTestID
=
sid
;
smTestID
=
sid
;
UniXML
::
iterator
i
(
sit
);
if
(
!
i
.
goChildren
()
)
continue
;
if
(
!
i
.
find
(
"mqtt"
)
)
continue
;
MQTTTextInfo
mi
(
topicsensors
,
sit
,
i
);
textpublist
.
emplace
(
sid
,
std
::
move
(
mi
)
);
}
}
if
(
publist
.
empty
()
)
if
(
publist
.
empty
()
)
...
@@ -132,6 +142,36 @@ void MQTTPublisher::sysCommand(const SystemMessage* sm)
...
@@ -132,6 +142,36 @@ void MQTTPublisher::sysCommand(const SystemMessage* sm)
}
}
}
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
string
MQTTPublisher
::
replace
(
const
std
::
string
&
text
,
MQTTPublisher
::
MQTTTextInfo
*
ti
,
MQTTPublisher
::
RangeInfo
*
ri
,
long
value
)
{
std
::
string
txt
(
text
);
ostringstream
v
;
v
<<
value
;
ostringstream
id
;
id
<<
ti
->
sid
;
ostringstream
r
;
r
<<
"["
<<
ri
->
rmin
<<
":"
<<
ri
->
rmax
<<
"]"
;
ostringstream
smin
;
smin
<<
ri
->
rmin
;
ostringstream
smax
;
smax
<<
ri
->
rmax
;
txt
=
replace_all
(
txt
,
"%v"
,
v
.
str
());
txt
=
replace_all
(
txt
,
"%n"
,
ti
->
xmlnode
.
getProp
(
"name"
));
txt
=
replace_all
(
txt
,
"%t"
,
ti
->
xmlnode
.
getProp
(
"textname"
));
txt
=
replace_all
(
txt
,
"%i"
,
id
.
str
());
txt
=
replace_all
(
txt
,
"%rmin"
,
smin
.
str
());
txt
=
replace_all
(
txt
,
"%rmax"
,
smax
.
str
());
txt
=
replace_all
(
txt
,
"%r"
,
r
.
str
());
return
std
::
move
(
txt
);
}
//--------------------------------------------------------------------------------
void
MQTTPublisher
::
help_print
(
int
argc
,
const
char
*
const
*
argv
)
void
MQTTPublisher
::
help_print
(
int
argc
,
const
char
*
const
*
argv
)
{
{
cout
<<
" Default prefix='mqtt'"
<<
endl
;
cout
<<
" Default prefix='mqtt'"
<<
endl
;
...
@@ -243,23 +283,100 @@ void MQTTPublisher::askSensors( UniversalIO::UIOCommand cmd )
...
@@ -243,23 +283,100 @@ void MQTTPublisher::askSensors( UniversalIO::UIOCommand cmd )
void
MQTTPublisher
::
sensorInfo
(
const
UniSetTypes
::
SensorMessage
*
sm
)
void
MQTTPublisher
::
sensorInfo
(
const
UniSetTypes
::
SensorMessage
*
sm
)
{
{
auto
i
=
publist
.
find
(
sm
->
id
);
auto
i
=
publist
.
find
(
sm
->
id
);
if
(
i
!=
publist
.
end
()
)
{
ostringstream
m
;
m
<<
sm
->
value
;
if
(
i
==
publist
.
end
()
)
string
tmsg
(
m
.
str
());
return
;
ostringstream
m
;
//subscribe(NULL, i.second.pubname.c_str())
;
m
<<
sm
->
value
;
myinfo
<<
"(sensorInfo): publish: topic='"
<<
i
->
second
.
pubname
<<
"' msg='"
<<
tmsg
.
c_str
()
<<
"'"
<<
endl
;
string
tmsg
(
m
.
str
()
);
int
ret
=
publish
(
NULL
,
i
->
second
.
pubname
.
c_str
(),
tmsg
.
size
(),
tmsg
.
c_str
(),
1
,
false
);
//subscribe(NULL, i.second.pubname.c_str());
if
(
ret
!=
MOSQ_ERR_SUCCESS
)
myinfo
<<
"(sensorInfo): publish: topic='"
<<
i
->
second
.
pubname
<<
"' msg='"
<<
tmsg
.
c_str
()
<<
"'"
<<
endl
;
{
mycrit
<<
myname
<<
"(sensorInfo): PUBLISH FAILED: err("
<<
ret
<<
"): "
<<
mosqpp
::
strerror
(
ret
)
<<
endl
;
}
}
int
ret
=
publish
(
NULL
,
i
->
second
.
pubname
.
c_str
(),
tmsg
.
size
(),
tmsg
.
c_str
(),
1
,
false
);
auto
t
=
textpublist
.
find
(
sm
->
id
);
if
(
t
!=
textpublist
.
end
()
)
{
auto
rlist
=
t
->
second
.
rlist
;
for
(
auto
&&
r
:
rlist
)
{
if
(
r
.
check
(
sm
->
value
)
)
{
string
tmsg
=
replace
(
r
.
text
,
&
(
t
->
second
),
&
r
,
sm
->
value
);
//subscribe(NULL, i.second.pubname.c_str());
myinfo
<<
"(sensorInfo): publish: topic='"
<<
t
->
second
.
pubname
<<
"' msg='"
<<
tmsg
<<
"'"
<<
endl
;
int
ret
=
publish
(
NULL
,
t
->
second
.
pubname
.
c_str
(),
tmsg
.
size
(),
tmsg
.
c_str
(),
1
,
false
);
if
(
ret
!=
MOSQ_ERR_SUCCESS
)
if
(
ret
!=
MOSQ_ERR_SUCCESS
)
{
mycrit
<<
myname
<<
"(sensorInfo): PUBLISH FAILED: err("
<<
ret
<<
"): "
<<
mosqpp
::
strerror
(
ret
)
<<
endl
;
}
}
}
}
}
// -----------------------------------------------------------------------------
MQTTPublisher
::
MQTTTextInfo
::
MQTTTextInfo
(
const
string
&
rootsec
,
UniXML
::
iterator
s
,
UniXML
::
iterator
i
)
:
xmlnode
(
s
)
{
auto
conf
=
uniset_conf
();
sid
=
conf
->
getSensorID
(
s
.
getProp
(
"name"
));
string
sname
(
s
.
getProp
(
"name"
));
if
(
sid
==
DefaultObjectId
)
{
{
mycrit
<<
myname
<<
"(sensorInfo): PUBLISH FAILED: err("
<<
ret
<<
"): "
<<
mosqpp
::
strerror
(
ret
)
<<
endl
;
ostringstream
err
;
err
<<
"(MQTTTextInfo): Unknown ID for "
<<
sname
;
throw
SystemError
(
err
.
str
());
}
}
std
::
string
subtopic
(
i
.
getProp
(
"subtopic"
));
if
(
!
subtopic
.
empty
()
)
pubname
=
rootsec
+
"/"
+
subtopic
;
else
pubname
=
rootsec
+
"/"
+
sname
+
"/textevent"
;
if
(
!
i
.
goChildren
()
)
{
ostringstream
err
;
err
<<
"(MQTTTextInfo): INIT FAIL! empty list <mqtt> for "
<<
sname
;
throw
SystemError
(
err
.
str
());
}
for
(
;
i
.
getCurrent
();
i
++
)
{
long
min
=
0
;
long
max
=
0
;
if
(
i
.
getName
()
==
"range"
)
{
min
=
i
.
getIntProp
(
"min"
);
max
=
i
.
getIntProp
(
"max"
);
if
(
min
>
max
)
std
::
swap
(
min
,
max
);
}
else
{
min
=
max
=
i
.
getIntProp
(
"value"
);
}
RangeInfo
r
(
min
,
max
,
i
.
getProp
(
"text"
));
rlist
.
push_back
(
std
::
move
(
r
)
);
}
}
// -----------------------------------------------------------------------------
bool
MQTTPublisher
::
RangeInfo
::
check
(
long
val
)
const
{
return
(
val
>=
rmin
&&
val
<=
rmax
);
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
extensions/MQTTPublisher/MQTTPublisher.h
View file @
3615f9fd
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
- \ref sec_MQTT_Comm
- \ref sec_MQTT_Comm
- \ref sec_MQTT_Conf
- \ref sec_MQTT_Conf
- \ref sec_MQTT_Text
\section sec_MQTT_Comm Общее описание MQTTPublisher
\section sec_MQTT_Comm Общее описание MQTTPublisher
...
@@ -52,6 +53,36 @@
...
@@ -52,6 +53,36 @@
Для запуска издателя, неоходимо наличие в configure.xml секции: <ObjectName name="ObjectName" ...параметры">.
Для запуска издателя, неоходимо наличие в configure.xml секции: <ObjectName name="ObjectName" ...параметры">.
\todo Доделать контрольный таймер (контроль наличия соединения с сервером)
\todo Доделать контрольный таймер (контроль наличия соединения с сервером)
\section sec_MQTT_Text Генерирование текстовых сообщений
В данном классе реализована возможность сопоставлять значения датчиков текстовым сообщениям, посылаемым на сервер.
Для этого необходимо в настроечной секции для датчика создать секцию <mqtt>
\code
<item id="10" name="MySensor1" .....>
<mqtt subtopic="myevent">
<msg value="12" text="My text for value %v"/>
<msg value="13" text="My text for value %v"/>
<msg value="14" text="My text for value %v"/>
<range min="10" max="20" text="My text for value %r. Value = %v"
<mqtt>
</item>
\endcode
- \b range - задаёт диапазон включающий [min,max]
При этом в тексте можно применять следующие "подстановки":
- \b %v - текущее значение
- \b %n - name
- \b %t - textname
- \b %i - ID
- \b %r - заданный диапазон (range). Заменяется на "[min:max]". Действует только для диапазонов.
- \b %rmin - минимальное значение диапазона (range min). Действует только для диапазонов.
- \b %rmax - максимальное значение диапазона (range max). Действует только для диапазонов.
\note Если заданные "одиночные" значения совпадают с диапазоном, то будет сгенерировано несколько сообщений.
Поле \b subtopic - задаёт подраздел в корневом топике (см. topicsensors). Т.е. полный топик для публикации текстовых сообщений
будет иметь вид ROOTPROJECT/topicsensors/sensorname/textevent или если задано поле \subtopic то
события будут опубликованы в ROOTPROJECT/topicsensors/subtopic
*/
*/
class
MQTTPublisher
:
class
MQTTPublisher
:
protected
mosqpp
::
mosquittopp
,
protected
mosqpp
::
mosquittopp
,
...
@@ -79,7 +110,6 @@ class MQTTPublisher:
...
@@ -79,7 +110,6 @@ class MQTTPublisher:
return
mylog
;
return
mylog
;
}
}
virtual
void
on_connect
(
int
rc
)
override
;
virtual
void
on_connect
(
int
rc
)
override
;
virtual
void
on_message
(
const
struct
mosquitto_message
*
message
)
override
;
virtual
void
on_message
(
const
struct
mosquitto_message
*
message
)
override
;
virtual
void
on_subscribe
(
int
mid
,
int
qos_count
,
const
int
*
granted_qos
)
override
;
virtual
void
on_subscribe
(
int
mid
,
int
qos_count
,
const
int
*
granted_qos
)
override
;
...
@@ -106,7 +136,34 @@ class MQTTPublisher:
...
@@ -106,7 +136,34 @@ class MQTTPublisher:
typedef
std
::
unordered_map
<
UniSetTypes
::
ObjectId
,
MQTTInfo
>
MQTTMap
;
typedef
std
::
unordered_map
<
UniSetTypes
::
ObjectId
,
MQTTInfo
>
MQTTMap
;
struct
RangeInfo
{
RangeInfo
(
long
min
,
long
max
,
const
std
::
string
&
t
)
:
rmin
(
min
),
rmax
(
max
),
text
(
t
){}
long
rmin
;
long
rmax
;
std
::
string
text
;
bool
check
(
long
val
)
const
;
};
struct
MQTTTextInfo
{
UniSetTypes
::
ObjectId
sid
;
std
::
string
pubname
;
UniXML
::
iterator
xmlnode
;
MQTTTextInfo
(
const
std
::
string
&
rootsec
,
UniXML
::
iterator
s
,
UniXML
::
iterator
i
);
// одиночные сообщения просто имитируются min=max=val
std
::
list
<
RangeInfo
>
rlist
;
// список сообщений..
};
typedef
std
::
unordered_map
<
UniSetTypes
::
ObjectId
,
MQTTTextInfo
>
MQTTTextMap
;
std
::
string
replace
(
const
std
::
string
&
text
,
MQTTTextInfo
*
ti
,
RangeInfo
*
r
,
long
value
);
MQTTMap
publist
;
MQTTMap
publist
;
MQTTTextMap
textpublist
;
private
:
private
:
...
...
include/UniSetTypes.h
View file @
3615f9fd
...
@@ -201,6 +201,12 @@ namespace UniSetTypes
...
@@ -201,6 +201,12 @@ namespace UniSetTypes
/*! проверка является текст в строке - числом..*/
/*! проверка является текст в строке - числом..*/
bool
is_digit
(
const
std
::
string
&
s
);
bool
is_digit
(
const
std
::
string
&
s
);
/*! замена всех вхождений подстроки
* \param src - исходная строка
* \param from - подстрока которая ищется (для замены)
* \param to - строка на которую будет сделана замена
*/
std
::
string
replace_all
(
const
std
::
string
&
src
,
const
std
::
string
&
from
,
const
std
::
string
&
to
);
// ---------------------------------------------------------------
// ---------------------------------------------------------------
// Работа с командной строкой
// Работа с командной строкой
...
...
src/ObjectRepository/UniSetTypes.cc
View file @
3615f9fd
...
@@ -572,3 +572,21 @@ std::ostream& UniSetTypes::operator<<( std::ostream& os, const IONotifyControlle
...
@@ -572,3 +572,21 @@ std::ostream& UniSetTypes::operator<<( std::ostream& os, const IONotifyControlle
return
os
<<
"Unknown"
;
return
os
<<
"Unknown"
;
}
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
std
::
string
UniSetTypes
::
replace_all
(
const
std
::
string
&
src
,
const
std
::
string
&
from
,
const
std
::
string
&
to
)
{
string
res
(
src
);
if
(
from
.
empty
()
)
return
std
::
move
(
res
);
size_t
pos
=
res
.
find
(
from
,
pos
);
while
(
pos
!=
std
::
string
::
npos
)
{
res
.
replace
(
pos
,
from
.
length
(),
to
);
pos
+=
to
.
length
();
pos
=
res
.
find
(
from
,
pos
);
}
return
std
::
move
(
res
);
}
// -------------------------------------------------------------------------
tests/test_utypes.cc
View file @
3615f9fd
...
@@ -156,3 +156,21 @@ TEST_CASE("UniSetTypes: getObjectsList", "[utypes][getolist]" )
...
@@ -156,3 +156,21 @@ TEST_CASE("UniSetTypes: getObjectsList", "[utypes][getolist]" )
REQUIRE
(
v
[
4
].
node
==
1001
);
REQUIRE
(
v
[
4
].
node
==
1001
);
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
TEST_CASE
(
"UniSetTypes: replace_all"
,
"[utypes][replace_all]"
)
{
const
std
::
string
str1
(
"Text %p test text %p"
);
std
::
string
res
=
UniSetTypes
::
replace_all
(
str1
,
"%p"
,
"my"
);
REQUIRE
(
res
==
"Text my test text my"
);
const
std
::
string
str2
(
"Text %rlong test text %rlong"
);
res
=
UniSetTypes
::
replace_all
(
str2
,
"%rlong"
,
"2"
);
REQUIRE
(
res
==
"Text 2 test text 2"
);
res
=
UniSetTypes
::
replace_all
(
str2
,
""
,
"my"
);
REQUIRE
(
res
==
str2
);
res
=
UniSetTypes
::
replace_all
(
str2
,
"not found"
,
"my"
);
REQUIRE
(
res
==
str2
);
}
// -----------------------------------------------------------------------------
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment