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
089e9ffb
Commit
089e9ffb
authored
Oct 31, 2011
by
Pavel Vainerman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(MBExchange): начал выносить в базовый класс одинаковый
код для MBTCPMaster и RTUExchange
parent
c12314b3
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
526 additions
and
611 deletions
+526
-611
MBTCPMaster.cc
extensions/MBTCPMaster/MBTCPMaster.cc
+24
-266
MBTCPMaster.h
extensions/MBTCPMaster/MBTCPMaster.h
+11
-85
RTUExchange.cc
extensions/RTUExchange/RTUExchange.cc
+18
-197
RTUExchange.h
extensions/RTUExchange/RTUExchange.h
+7
-62
MBExchange.h
extensions/include/MBExchange.h
+121
-0
MBExchange.cc
extensions/lib/MBExchange.cc
+343
-0
Makefile.am
extensions/lib/Makefile.am
+2
-1
No files found.
extensions/MBTCPMaster/MBTCPMaster.cc
View file @
089e9ffb
...
...
@@ -12,20 +12,11 @@ using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
MBTCPMaster
::
MBTCPMaster
(
UniSetTypes
::
ObjectId
objId
,
UniSetTypes
::
ObjectId
shmId
,
SharedMemory
*
ic
,
const
std
::
string
prefix
)
:
UniSetObject_LT
(
objId
),
MBExchange
(
objId
,
shmId
,
ic
,
prefix
),
allInitOK
(
false
),
mb
(
0
),
shm
(
0
),
initPause
(
0
),
force
(
false
),
force_out
(
false
),
mbregFromID
(
false
),
sidExchangeMode
(
DefaultObjectId
),
activated
(
false
),
noQueryOptimization
(
false
),
force_disconnect
(
true
),
prefix
(
prefix
),
no_extimer
(
false
),
force_disconnect
(
true
),
poll_count
(
0
),
pollThread
(
0
)
{
...
...
@@ -34,27 +25,8 @@ pollThread(0)
if
(
objId
==
DefaultObjectId
)
throw
UniSetTypes
::
SystemError
(
"(MBTCPMaster): objId=-1?!! Use --"
+
prefix
+
"-name"
);
// xmlNode* cnode = conf->getNode(myname);
string
conf_name
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-confnode"
,
myname
);
cnode
=
conf
->
getNode
(
conf_name
);
if
(
cnode
==
NULL
)
throw
UniSetTypes
::
SystemError
(
"(MBTCPMaster): Not found node <"
+
conf_name
+
" ...> for "
+
myname
);
shm
=
new
SMInterface
(
shmId
,
&
ui
,
objId
,
ic
);
UniXML_iterator
it
(
cnode
);
// определяем фильтр
s_field
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-filter-field"
);
s_fvalue
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-filter-value"
);
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): read fileter-field='"
<<
s_field
<<
"' filter-value='"
<<
s_fvalue
<<
"'"
<<
endl
;
stat_time
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-statistic-sec"
,
it
.
getProp
(
"statistic_sec"
),
0
);
if
(
stat_time
>
0
)
ptStatistic
.
setTiming
(
stat_time
*
1000
);
// ---------- init MBTCP ----------
string
pname
(
"--"
+
prefix
+
"-gateway-iaddr"
);
iaddr
=
conf
->
getArgParam
(
pname
,
it
.
getProp
(
"gateway_iaddr"
));
...
...
@@ -67,29 +39,14 @@ pollThread(0)
throw
UniSetTypes
::
SystemError
(
myname
+
"(MBMaster): Unknown inet port...(Use: "
+
tmp
+
")"
);
force_disconnect
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-persistent-connection"
,
it
.
getProp
(
"persistent_connection"
))
?
false
:
true
;
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): persisten-connection="
<<
(
!
force_disconnect
)
<<
endl
;
recv_timeout
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-recv-timeout"
,
it
.
getProp
(
"recv_timeout"
),
500
);
int
tout
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-timeout"
,
it
.
getProp
(
"timeout"
),
5000
);
ptTimeout
.
setTiming
(
tout
);
noQueryOptimization
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-no-query-optimization"
,
it
.
getProp
(
"no_query_optimization"
));
mbregFromID
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-reg-from-id"
,
it
.
getProp
(
"reg_from_id"
));
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): mbregFromID="
<<
mbregFromID
<<
endl
;
polltime
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-polltime"
,
it
.
getProp
(
"polltime"
),
100
);
initPause
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-initPause"
,
it
.
getProp
(
"initPause"
),
3000
);
sleepPause_usec
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-sleepPause-usec"
,
it
.
getProp
(
"slepePause"
),
100
);
force
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-force"
,
it
.
getProp
(
"force"
));
force_out
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-force-out"
,
it
.
getProp
(
"force_out"
));
force_disconnect
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-persistent-connection"
,
it
.
getProp
(
"persistent_connection"
))
?
false
:
true
;
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): persisten-connection="
<<
(
!
force_disconnect
)
<<
endl
;
if
(
shm
->
isLocalwork
()
)
{
readConfiguration
();
...
...
@@ -99,60 +56,6 @@ pollThread(0)
else
ic
->
addReadItem
(
sigc
::
mem_fun
(
this
,
&
MBTCPMaster
::
readItem
)
);
// ********** HEARTBEAT *************
string
heart
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-heartbeat-id"
,
it
.
getProp
(
"heartbeat_id"
));
if
(
!
heart
.
empty
()
)
{
sidHeartBeat
=
conf
->
getSensorID
(
heart
);
if
(
sidHeartBeat
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
": ID not found ('HeartBeat') for "
<<
heart
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
int
heartbeatTime
=
getHeartBeatTime
();
if
(
heartbeatTime
)
ptHeartBeat
.
setTiming
(
heartbeatTime
);
else
ptHeartBeat
.
setTiming
(
UniSetTimer
::
WaitUpTime
);
maxHeartBeat
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-heartbeat-max"
,
it
.
getProp
(
"heartbeat_max"
),
10
);
test_id
=
sidHeartBeat
;
}
else
{
test_id
=
conf
->
getSensorID
(
"TestMode_S"
);
if
(
test_id
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
"(init): test_id unknown. 'TestMode_S' not found..."
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): test_id="
<<
test_id
<<
endl
;
string
emode
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-exchange-mode-id"
,
it
.
getProp
(
"exchangeModeID"
));
if
(
!
emode
.
empty
()
)
{
sidExchangeMode
=
conf
->
getSensorID
(
emode
);
if
(
sidExchangeMode
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
": ID not found ('ExchangeMode') for "
<<
emode
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
activateTimeout
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-activate-timeout"
,
20000
);
if
(
dlog
.
debugging
(
Debug
::
INFO
)
)
printMap
(
rmap
);
poll_count
=
-
1
;
pollThread
=
new
ThreadCreator
<
MBTCPMaster
>
(
this
,
&
MBTCPMaster
::
poll_thread
);
}
// -----------------------------------------------------------------------------
...
...
@@ -169,7 +72,6 @@ MBTCPMaster::~MBTCPMaster()
delete
pollThread
;
delete
mb
;
delete
shm
;
}
// -----------------------------------------------------------------------------
void
MBTCPMaster
::
initMB
(
bool
reopen
)
...
...
@@ -216,24 +118,6 @@ void MBTCPMaster::initMB( bool reopen )
}
// -----------------------------------------------------------------------------
void
MBTCPMaster
::
waitSMReady
()
{
// waiting for SM is ready...
int
ready_timeout
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-sm-ready-timeout"
,
"15000"
);
if
(
ready_timeout
==
0
)
ready_timeout
=
15000
;
else
if
(
ready_timeout
<
0
)
ready_timeout
=
UniSetTimer
::
WaitUpTime
;
if
(
!
shm
->
waitSMready
(
ready_timeout
,
50
)
)
{
ostringstream
err
;
err
<<
myname
<<
"(waitSMReady): failed waiting SharedMemory "
<<
ready_timeout
<<
" msec"
;
dlog
[
Debug
::
CRIT
]
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
// -----------------------------------------------------------------------------
void
MBTCPMaster
::
timerInfo
(
TimerMessage
*
tm
)
{
if
(
tm
->
id
==
tmExchange
)
...
...
@@ -248,25 +132,8 @@ void MBTCPMaster::timerInfo( TimerMessage *tm )
void
MBTCPMaster
::
step
()
{
updateRespondSensors
();
if
(
!
activated
)
return
;
if
(
sidHeartBeat
!=
DefaultObjectId
&&
ptHeartBeat
.
checkTime
()
)
{
try
{
shm
->
localSaveValue
(
aitHeartBeat
,
sidHeartBeat
,
maxHeartBeat
,
getId
());
ptHeartBeat
.
reset
();
}
catch
(
Exception
&
ex
)
{
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(step): (hb) "
<<
ex
<<
std
::
endl
;
}
}
MBExchange
::
step
();
}
// -----------------------------------------------------------------------------
void
MBTCPMaster
::
updateRespondSensors
()
{
...
...
@@ -338,18 +205,6 @@ void MBTCPMaster::poll_thread()
}
}
// -----------------------------------------------------------------------------
bool
MBTCPMaster
::
checkProcActive
()
{
uniset_mutex_lock
l
(
actMutex
,
300
);
return
activated
;
}
// -----------------------------------------------------------------------------
void
MBTCPMaster
::
setProcActive
(
bool
st
)
{
uniset_mutex_lock
l
(
actMutex
,
400
);
activated
=
st
;
}
// -----------------------------------------------------------------------------
void
MBTCPMaster
::
poll
()
{
if
(
!
mb
)
...
...
@@ -502,20 +357,8 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
}
}
if
(
exchangeMode
==
emWriteOnly
&&
!
ModbusRTU
::
isWriteFunction
(
p
->
mbfunc
)
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
myname
<<
"(pollRTU): skip.. mode='emWriteOnly'"
<<
endl
;
if
(
!
checkPoll
(
ModbusRTU
::
isWriteFunction
(
p
->
mbfunc
))
)
return
true
;
}
if
(
exchangeMode
==
emReadOnly
&&
ModbusRTU
::
isWriteFunction
(
p
->
mbfunc
)
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
myname
<<
"(pollRTU): skip.. poll mode='emReadOnly'"
<<
endl
;
return
false
;
}
if
(
p
->
q_count
==
0
)
{
...
...
@@ -1317,41 +1160,6 @@ void MBTCPMaster::sigterm( int signo )
UniSetObject_LT
::
sigterm
(
signo
);
}
// ------------------------------------------------------------------------------------------
void
MBTCPMaster
::
readConfiguration
()
{
// readconf_ok = false;
xmlNode
*
root
=
conf
->
getXMLSensorsSection
();
if
(
!
root
)
{
ostringstream
err
;
err
<<
myname
<<
"(readConfiguration): не нашли корневого раздела <sensors>"
;
throw
SystemError
(
err
.
str
());
}
UniXML_iterator
it
(
root
);
if
(
!
it
.
goChildren
()
)
{
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(readConfiguration): раздел <sensors> не содержит секций ?!!
\n
"
;
return
;
}
for
(
;
it
.
getCurrent
();
it
.
goNext
()
)
{
if
(
UniSetTypes
::
check_filter
(
it
,
s_field
,
s_fvalue
)
)
initItem
(
it
);
}
// readconf_ok = true;
}
// ------------------------------------------------------------------------------------------
bool
MBTCPMaster
::
readItem
(
UniXML
&
xml
,
UniXML_iterator
&
it
,
xmlNode
*
sec
)
{
if
(
UniSetTypes
::
check_filter
(
it
,
s_field
,
s_fvalue
)
)
initItem
(
it
);
return
true
;
}
// ------------------------------------------------------------------------------------------
MBTCPMaster
::
RTUDevice
*
MBTCPMaster
::
addDev
(
RTUDeviceMap
&
mp
,
ModbusRTU
::
ModbusAddr
a
,
UniXML_iterator
&
xmlit
)
{
RTUDeviceMap
::
iterator
it
=
mp
.
find
(
a
);
...
...
@@ -1599,20 +1407,6 @@ bool MBTCPMaster::initRegInfo( RegInfo* r, UniXML_iterator& it, MBTCPMaster::RT
return
true
;
}
// ------------------------------------------------------------------------------------------
MBTCPMaster
::
DeviceType
MBTCPMaster
::
getDeviceType
(
const
std
::
string
dtype
)
{
if
(
dtype
.
empty
()
)
return
dtUnknown
;
if
(
dtype
==
"mtr"
||
dtype
==
"MTR"
)
return
dtMTR
;
if
(
dtype
==
"rtu"
||
dtype
==
"RTU"
)
return
dtRTU
;
return
dtUnknown
;
}
// ------------------------------------------------------------------------------------------
bool
MBTCPMaster
::
initRTUDevice
(
RTUDevice
*
d
,
UniXML_iterator
&
it
)
{
d
->
dtype
=
getDeviceType
(
it
.
getProp
(
"tcp_mbtype"
));
...
...
@@ -1881,9 +1675,7 @@ bool MBTCPMaster::initMTRitem( UniXML_iterator& it, RegInfo* p )
// ------------------------------------------------------------------------------------------
void
MBTCPMaster
::
initIterators
()
{
shm
->
initAIterator
(
aitHeartBeat
);
shm
->
initAIterator
(
aitExchangeMode
);
MBExchange
::
initIterators
();
for
(
MBTCPMaster
::
RTUDeviceMap
::
iterator
it1
=
rmap
.
begin
();
it1
!=
rmap
.
end
();
++
it1
)
{
RTUDevice
*
d
(
it1
->
second
);
...
...
@@ -1903,32 +1695,19 @@ void MBTCPMaster::initIterators()
void
MBTCPMaster
::
help_print
(
int
argc
,
const
char
*
const
*
argv
)
{
cout
<<
"Default: prefix='mbtcp'"
<<
endl
;
cout
<<
"--prefix-name name - ObjectId (имя) процесса. По умолчанию: MBTCPMaster1"
<<
endl
;
cout
<<
"--prefix-confnode name - Настроечная секция в конф. файле <name>. "
<<
endl
;
cout
<<
"--prefix-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек."
<<
endl
;
cout
<<
"--prefix-heartbeat-id name - Данный процесс связан с указанным аналоговым heartbeat-дачиком."
<<
endl
;
cout
<<
"--prefix-heartbeat-max val - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10."
<<
endl
;
cout
<<
"--prefix-ready-timeout msec - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')"
<<
endl
;
cout
<<
"--prefix-force 0,1 - Сохранять значения в SM, независимо от, того менялось ли значение"
<<
endl
;
cout
<<
"--prefix-force-out 0,1 - Считывать значения 'выходов' кажый раз SM (а не по изменению)"
<<
endl
;
cout
<<
"--prefix-initPause msec - Задержка перед инициализацией (время на активизация процесса)"
<<
endl
;
cout
<<
"--prefix-no-query-optimization 0,1 - Не оптимизировать запросы (не объединять соседние регистры в один запрос)"
<<
endl
;
cout
<<
"--prefix-reg-from-id 0,1 - Использовать в качестве регистра sensor ID"
<<
endl
;
cout
<<
"--prefix-filter-field name - Считывать список опрашиваемых датчиков, только у которых есть поле field"
<<
endl
;
cout
<<
"--prefix-filter-value val - Считывать список опрашиваемых датчиков, только у которых field=value"
<<
endl
;
cout
<<
"--prefix-statistic-sec sec - Выводить статистику опроса каждые sec секунд"
<<
endl
;
MBExchange
::
help_print
(
argc
,
argv
);
// ---------- init MBTCP ----------
// cout << "--prefix-sm-ready-timeout - время на ожидание старта SM" << endl;
cout
<<
" Настройки протокола TCP: "
<<
endl
;
cout
<<
"--prefix-gateway hostname,IP - IP опрашиваемого узла"
<<
endl
;
cout
<<
"--prefix-gateway-port num - port на опрашиваемом узле"
<<
endl
;
cout
<<
"--prefix-recv-timeout msec - Таймаут на приём одного сообщения
.
"
<<
endl
;
cout
<<
"--prefix-timeout msec - Таймаут для определения отсутсвия соединения
.в
"
<<
endl
;
cout
<<
"--prefix-recv-timeout msec - Таймаут на приём одного сообщения"
<<
endl
;
cout
<<
"--prefix-timeout msec - Таймаут для определения отсутсвия соединения"
<<
endl
;
cout
<<
"--prefix-persistent-connection 0,1 - Не закрывать соединение на каждом цикле опроса"
<<
endl
;
}
// -----------------------------------------------------------------------------
MBTCPMaster
*
MBTCPMaster
::
init_mbmaster
(
int
argc
,
const
char
*
const
*
argv
,
UniSetTypes
::
ObjectId
icID
,
SharedMemory
*
ic
,
MBTCPMaster
*
MBTCPMaster
::
init_mbmaster
(
int
argc
,
const
char
*
const
*
argv
,
UniSetTypes
::
ObjectId
icID
,
SharedMemory
*
ic
,
const
std
::
string
prefix
)
{
string
name
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-name"
,
"MBTCPMaster1"
);
...
...
@@ -2069,18 +1848,18 @@ std::ostream& operator<<( std::ostream& os, MBTCPMaster::RTUDeviceMap& m )
// -----------------------------------------------------------------------------
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
MBTCPMaster
::
RTUDevice
&
d
)
{
os
<<
"addr="
<<
ModbusRTU
::
addr2str
(
d
.
mbaddr
)
<<
" type="
<<
d
.
dtype
<<
" respond_id="
<<
d
.
resp_id
<<
" respond_timeout="
<<
d
.
resp_ptTimeout
.
getInterval
()
<<
" respond_state="
<<
d
.
resp_state
<<
" respond_invert="
<<
d
.
resp_invert
<<
endl
;
os
<<
"addr="
<<
ModbusRTU
::
addr2str
(
d
.
mbaddr
)
<<
" type="
<<
d
.
dtype
<<
" respond_id="
<<
d
.
resp_id
<<
" respond_timeout="
<<
d
.
resp_ptTimeout
.
getInterval
()
<<
" respond_state="
<<
d
.
resp_state
<<
" respond_invert="
<<
d
.
resp_invert
<<
endl
;
os
<<
" regs: "
<<
endl
;
for
(
MBTCPMaster
::
RegMap
::
iterator
it
=
d
.
regmap
.
begin
();
it
!=
d
.
regmap
.
end
();
++
it
)
os
<<
" "
<<
*
(
it
->
second
)
<<
endl
;
os
<<
" regs: "
<<
endl
;
for
(
MBTCPMaster
::
RegMap
::
iterator
it
=
d
.
regmap
.
begin
();
it
!=
d
.
regmap
.
end
();
++
it
)
os
<<
" "
<<
*
(
it
->
second
)
<<
endl
;
return
os
;
}
...
...
@@ -2187,30 +1966,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
if
(
!
save
&&
write_only
)
return
;
if
(
save
&&
exchangeMode
==
emReadOnly
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
"updateP: sid="
<<
p
->
si
.
id
<<
" skip... mode='emReadOnly' "
<<
endl
;
return
;
}
if
(
!
save
&&
exchangeMode
==
emWriteOnly
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
"updateP: sid="
<<
p
->
si
.
id
<<
" skip... mode='emWriteOnly' "
<<
endl
;
if
(
!
checkUpdateSM
(
save
)
)
return
;
}
if
(
save
&&
exchangeMode
==
emSkipSaveToSM
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
"updateP: sid="
<<
p
->
si
.
id
<<
" skip... mode='emSkipSaveToSM' "
<<
endl
;
return
;
}
// если требуется инициализация и она ещё не произведена,
// то игнорируем
if
(
save
&&
!
r
->
mb_initOK
)
...
...
extensions/MBTCPMaster/MBTCPMaster.h
View file @
089e9ffb
...
...
@@ -5,19 +5,8 @@
#include <string>
#include <map>
#include <vector>
#include "IONotifyController.h"
#include "UniSetObject_LT.h"
#include "MBExchange.h"
#include "modbus/ModbusTCPMaster.h"
#include "PassiveTimer.h"
#include "Trigger.h"
#include "Mutex.h"
#include "Calibration.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "IOBase.h"
#include "VTypes.h"
#include "MTR.h"
// -----------------------------------------------------------------------------
/*!
\page page_ModbusTCP Реализация ModbusTCP master
...
...
@@ -190,7 +179,7 @@
связи обновляется в основном потоке (чтобы не зависеть от TCP).
*/
class
MBTCPMaster
:
public
UniSetObject_LT
public
MBExchange
{
public
:
MBTCPMaster
(
UniSetTypes
::
ObjectId
objId
,
UniSetTypes
::
ObjectId
shmID
,
SharedMemory
*
ic
=
0
,
...
...
@@ -207,32 +196,12 @@ class MBTCPMaster:
void
execute
();
static
const
int
NoSafetyState
=-
1
;
/*! Режимы работы процесса обмена */
enum
ExchangeMode
{
emNone
,
/*!< нормальная работа (по умолчанию) */
emWriteOnly
,
/*!< "только посылка данных" (работают только write-функции) */
emReadOnly
,
/*!< "только чтение" (работают только read-функции) */
emSkipSaveToSM
/*!< не писать данные в SM (при этом работают и read и write функции */
};
enum
Timer
{
tmExchange
};
enum
DeviceType
{
dtUnknown
,
/*!< неизвестный */
dtRTU
,
/*!< RTU (default) */
dtMTR
/*!< MTR (DEIF) */
};
static
DeviceType
getDeviceType
(
const
std
::
string
dtype
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
DeviceType
&
dt
);
// -------------------------------------------------------------------------------
// -----------------------------------------------------
struct
RTUDevice
;
struct
RegInfo
;
...
...
@@ -346,7 +315,6 @@ class MBTCPMaster:
void
printMap
(
RTUDeviceMap
&
d
);
// ----------------------------------
static
RegID
genRegID
(
const
ModbusRTU
::
ModbusData
r
,
const
int
fn
);
protected
:
struct
InitRegInfo
...
...
@@ -380,13 +348,7 @@ class MBTCPMaster:
int
port
;
int
recv_timeout
;
xmlNode
*
cnode
;
std
::
string
s_field
;
std
::
string
s_fvalue
;
SMInterface
*
shm
;
void
step
();
virtual
void
step
();
void
poll_thread
();
void
poll
();
bool
pollRTU
(
RTUDevice
*
dev
,
RegMap
::
iterator
&
it
);
...
...
@@ -403,17 +365,12 @@ class MBTCPMaster:
void
timerInfo
(
UniSetTypes
::
TimerMessage
*
tm
);
void
askSensors
(
UniversalIO
::
UIOCommand
cmd
);
void
initOutput
();
void
waitSMReady
(
);
void
initMB
(
bool
reopen
=
false
);
virtual
bool
activateObject
();
// действия при завершении работы
virtual
void
sigterm
(
int
signo
);
void
initMB
(
bool
reopen
=
false
);
void
initIterators
();
bool
initItem
(
UniXML_iterator
&
it
);
bool
readItem
(
UniXML
&
xml
,
UniXML_iterator
&
it
,
xmlNode
*
sec
);
virtual
void
initIterators
();
virtual
bool
initItem
(
UniXML_iterator
&
it
);
void
initDeviceList
();
void
initOffsetList
();
...
...
@@ -430,47 +387,16 @@ class MBTCPMaster:
void
rtuQueryOptimization
(
RTUDeviceMap
&
m
);
void
readConfiguration
();
bool
checkProcActive
();
void
setProcActive
(
bool
st
);
private
:
MBTCPMaster
();
bool
initPause
;
UniSetTypes
::
uniset_mutex
mutex_start
;
bool
force
;
/*!< флаг означающий, что надо сохранять в SM, даже если значение не менялось */
bool
force_out
;
/*!< флаг означающий, принудительного чтения выходов */
bool
mbregFromID
;
int
polltime
;
/*!< переодичность обновления данных, [мсек] */
timeout_t
sleepPause_usec
;
PassiveTimer
ptHeartBeat
;
UniSetTypes
::
ObjectId
sidHeartBeat
;
int
maxHeartBeat
;
IOController
::
AIOStateList
::
iterator
aitHeartBeat
;
UniSetTypes
::
ObjectId
test_id
;
UniSetTypes
::
ObjectId
sidExchangeMode
;
/*!< иденидентификатор для датчика режима работы */
IOController
::
AIOStateList
::
iterator
aitExchangeMode
;
long
exchangeMode
;
/*!< режим работы см. ExchangeMode */
UniSetTypes
::
uniset_mutex
actMutex
;
bool
activated
;
int
activateTimeout
;
bool
noQueryOptimization
;
bool
force_disconnect
;
std
::
string
prefix
;
bool
no_extimer
;
bool
force_disconnect
;
timeout_t
stat_time
;
/*!< время сбора статистики обмена */
int
poll_count
;
PassiveTimer
ptStatistic
;
/*!< таймер для сбора статистики обмена */
private
:
MBTCPMaster
();
// т.к. TCP может "зависнуть" на подключении к недоступному узлу
// делаем опрос в отдельном потоке
ThreadCreator
<
MBTCPMaster
>*
pollThread
;
/*!< поток опроса */
...
...
extensions/RTUExchange/RTUExchange.cc
View file @
089e9ffb
// -----------------------------------------------------------------------------
#include <cmath>
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "RTUExchange.h"
// -----------------------------------------------------------------------------
...
...
@@ -11,40 +10,19 @@ using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
RTUExchange
::
RTUExchange
(
UniSetTypes
::
ObjectId
objId
,
UniSetTypes
::
ObjectId
shmId
,
SharedMemory
*
ic
,
const
std
::
string
prefix_
)
:
UniSetObject_LT
(
objId
),
MBExchange
(
objId
,
shmId
,
ic
,
prefix_
),
mb
(
0
),
defSpeed
(
ComPort
::
ComSpeed0
),
use485F
(
false
),
transmitCtl
(
false
),
shm
(
0
),
initPause
(
0
),
force
(
false
),
force_out
(
false
),
mbregFromID
(
false
),
activated
(
false
),
rs_pre_clean
(
false
),
noQueryOptimization
(
false
),
allNotRespond
(
false
),
prefix
(
prefix_
)
allNotRespond
(
false
)
{
if
(
objId
==
DefaultObjectId
)
throw
UniSetTypes
::
SystemError
(
"(RTUExchange): objId=-1?!! Use --"
+
prefix
+
"-name"
);
// xmlNode* cnode = conf->getNode(myname);
cnode
=
conf
->
getNode
(
myname
);
if
(
cnode
==
NULL
)
throw
UniSetTypes
::
SystemError
(
"(RTUExchange): Not find conf-node for "
+
myname
);
shm
=
new
SMInterface
(
shmId
,
&
ui
,
objId
,
ic
);
UniXML_iterator
it
(
cnode
);
// определяем фильтр
s_field
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-filter-field"
);
s_fvalue
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-filter-value"
);
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): read fileter-field='"
<<
s_field
<<
"' filter-value='"
<<
s_fvalue
<<
"'"
<<
endl
;
// ---------- init RS ----------
// UniXML_iterator it(cnode);
devname
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-dev"
,
it
.
getProp
(
"device"
));
...
...
@@ -69,16 +47,6 @@ prefix(prefix_)
rs_pre_clean
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-pre-clean"
,
it
.
getProp
(
"pre_clean"
));
noQueryOptimization
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-no-query-optimization"
,
it
.
getProp
(
"no_query_optimization"
));
mbregFromID
=
conf
->
getArgInt
(
"--mbs-reg-from-id"
,
it
.
getProp
(
"reg_from_id"
));
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): mbregFromID="
<<
mbregFromID
<<
endl
;
polltime
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-polltime"
,
it
.
getProp
(
"polltime"
),
100
);
initPause
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-initPause"
,
it
.
getProp
(
"initPause"
),
3000
);
force
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-force"
,
it
.
getProp
(
"force"
));
force_out
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-force-out"
,
it
.
getProp
(
"force_out"
));
if
(
shm
->
isLocalwork
()
)
{
readConfiguration
();
...
...
@@ -88,48 +56,11 @@ prefix(prefix_)
else
ic
->
addReadItem
(
sigc
::
mem_fun
(
this
,
&
RTUExchange
::
readItem
)
);
// ********** HEARTBEAT *************
string
heart
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-heartbeat-id"
,
it
.
getProp
(
"heartbeat_id"
));
if
(
!
heart
.
empty
()
)
{
sidHeartBeat
=
conf
->
getSensorID
(
heart
);
if
(
sidHeartBeat
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
": ID not found ('HeartBeat') for "
<<
heart
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
int
heartbeatTime
=
getHeartBeatTime
();
if
(
heartbeatTime
)
ptHeartBeat
.
setTiming
(
heartbeatTime
);
else
ptHeartBeat
.
setTiming
(
UniSetTimer
::
WaitUpTime
);
maxHeartBeat
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-heartbeat-max"
,
it
.
getProp
(
"heartbeat_max"
),
10
);
test_id
=
sidHeartBeat
;
}
else
{
test_id
=
conf
->
getSensorID
(
"TestMode_S"
);
if
(
test_id
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
"(init): test_id unknown. 'TestMode_S' not found..."
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): test_id="
<<
test_id
<<
endl
;
activateTimeout
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-activate-timeout"
,
20000
);
initMB
(
false
);
printMap
(
rmap
);
// abort(
);
if
(
dlog
.
debugging
(
Debug
::
INFO
)
)
printMap
(
rmap
);
}
// -----------------------------------------------------------------------------
RTUExchange
::~
RTUExchange
()
...
...
@@ -150,7 +81,6 @@ RTUExchange::~RTUExchange()
}
delete
mb
;
delete
shm
;
}
// -----------------------------------------------------------------------------
void
RTUExchange
::
initMB
(
bool
reopen
)
...
...
@@ -198,24 +128,6 @@ void RTUExchange::initMB( bool reopen )
}
}
// -----------------------------------------------------------------------------
void
RTUExchange
::
waitSMReady
()
{
// waiting for SM is ready...
int
ready_timeout
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-sm-ready-timeout"
,
"15000"
);
if
(
ready_timeout
==
0
)
ready_timeout
=
15000
;
else
if
(
ready_timeout
<
0
)
ready_timeout
=
UniSetTimer
::
WaitUpTime
;
if
(
!
shm
->
waitSMready
(
ready_timeout
,
50
)
)
{
ostringstream
err
;
err
<<
myname
<<
"(waitSMReady): Не дождались готовности SharedMemory к работе в течение "
<<
ready_timeout
<<
" мсек"
;
dlog
[
Debug
::
CRIT
]
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
// -----------------------------------------------------------------------------
void
RTUExchange
::
timerInfo
(
TimerMessage
*
tm
)
{
if
(
tm
->
id
==
tmExchange
)
...
...
@@ -229,22 +141,7 @@ void RTUExchange::step()
poll
();
}
if
(
!
activated
)
return
;
if
(
sidHeartBeat
!=
DefaultObjectId
&&
ptHeartBeat
.
checkTime
()
)
{
try
{
shm
->
localSaveValue
(
aitHeartBeat
,
sidHeartBeat
,
maxHeartBeat
,
getId
());
ptHeartBeat
.
reset
();
}
catch
(
Exception
&
ex
)
{
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(step): (hb) "
<<
ex
<<
std
::
endl
;
}
}
MBExchange
::
step
();
}
// -----------------------------------------------------------------------------
...
...
@@ -388,7 +285,10 @@ bool RTUExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
<<
" mb_init="
<<
p
->
mb_init
<<
endl
;
}
if
(
!
checkPoll
(
ModbusRTU
::
isWriteFunction
(
p
->
mbfunc
))
)
return
true
;
if
(
p
->
q_count
==
0
)
{
if
(
dlog
.
debugging
(
Debug
::
INFO
)
)
...
...
@@ -886,6 +786,8 @@ void RTUExchange::sensorInfo( UniSetTypes::SensorMessage* sm )
if
(
force_out
)
return
;
MBExchange
::
sensorInfo
(
sm
);
for
(
RTUExchange
::
RTUDeviceMap
::
iterator
it1
=
rmap
.
begin
();
it1
!=
rmap
.
end
();
++
it1
)
{
RTUDevice
*
d
(
it1
->
second
);
...
...
@@ -939,45 +841,9 @@ bool RTUExchange::activateObject()
void
RTUExchange
::
sigterm
(
int
signo
)
{
cerr
<<
myname
<<
": ********* SIGTERM("
<<
signo
<<
") ********"
<<
endl
;
activated
=
false
;
UniSetObject_LT
::
sigterm
(
signo
);
MBExchange
::
sigterm
(
signo
);
}
// ------------------------------------------------------------------------------------------
void
RTUExchange
::
readConfiguration
()
{
// readconf_ok = false;
xmlNode
*
root
=
conf
->
getXMLSensorsSection
();
if
(
!
root
)
{
ostringstream
err
;
err
<<
myname
<<
"(readConfiguration): не нашли корневого раздела <sensors>"
;
throw
SystemError
(
err
.
str
());
}
UniXML_iterator
it
(
root
);
if
(
!
it
.
goChildren
()
)
{
std
::
cerr
<<
myname
<<
"(readConfiguration): раздел <sensors> не содержит секций ?!!
\n
"
;
return
;
}
for
(
;
it
.
getCurrent
();
it
.
goNext
()
)
{
if
(
UniSetTypes
::
check_filter
(
it
,
s_field
,
s_fvalue
)
)
initItem
(
it
);
}
// readconf_ok = true;
}
// ------------------------------------------------------------------------------------------
bool
RTUExchange
::
readItem
(
UniXML
&
xml
,
UniXML_iterator
&
it
,
xmlNode
*
sec
)
{
if
(
UniSetTypes
::
check_filter
(
it
,
s_field
,
s_fvalue
)
)
initItem
(
it
);
return
true
;
}
// ------------------------------------------------------------------------------------------
RTUExchange
::
RTUDevice
*
RTUExchange
::
addDev
(
RTUDeviceMap
&
mp
,
ModbusRTU
::
ModbusAddr
a
,
UniXML_iterator
&
xmlit
)
{
RTUDeviceMap
::
iterator
it
=
mp
.
find
(
a
);
...
...
@@ -1223,24 +1089,6 @@ bool RTUExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, RTUExchange::RT
return
true
;
}
// ------------------------------------------------------------------------------------------
RTUExchange
::
DeviceType
RTUExchange
::
getDeviceType
(
const
std
::
string
dtype
)
{
if
(
dtype
.
empty
()
)
return
dtUnknown
;
if
(
dtype
==
"mtr"
||
dtype
==
"MTR"
)
return
dtMTR
;
if
(
dtype
==
"rtu"
||
dtype
==
"RTU"
)
return
dtRTU
;
if
(
dtype
==
"rtu188"
||
dtype
==
"RTU188"
)
return
dtRTU188
;
return
dtUnknown
;
}
// ------------------------------------------------------------------------------------------
bool
RTUExchange
::
initRTUDevice
(
RTUDevice
*
d
,
UniXML_iterator
&
it
)
{
d
->
dtype
=
getDeviceType
(
it
.
getProp
(
"mbtype"
));
...
...
@@ -1442,7 +1290,7 @@ bool RTUExchange::initRTU188item( UniXML_iterator& it, RegInfo* p )
// -----------------------------------------------------------------------------
void
RTUExchange
::
initIterators
()
{
shm
->
initAIterator
(
aitHeartBeat
);
MBExchange
::
initIterators
(
);
for
(
RTUExchange
::
RTUDeviceMap
::
iterator
it1
=
rmap
.
begin
();
it1
!=
rmap
.
end
();
++
it1
)
{
...
...
@@ -1463,14 +1311,8 @@ void RTUExchange::initIterators()
void
RTUExchange
::
help_print
(
int
argc
,
const
char
*
const
*
argv
)
{
cout
<<
"Default: prefix='rs'"
<<
endl
;
cout
<<
"--prefix-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек."
<<
endl
;
cout
<<
"--prefix-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком."
<<
endl
;
cout
<<
"--prefix-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10."
<<
endl
;
cout
<<
"--prefix-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')"
<<
endl
;
cout
<<
"--prefix-force - Сохранять значения в SM, независимо от, того менялось ли значение"
<<
endl
;
cout
<<
"--prefix-initPause - Задержка перед инициализацией (время на активизация процесса)"
<<
endl
;
cout
<<
"--prefix-sm-ready-timeout - время на ожидание старта SM"
<<
endl
;
cout
<<
" Настройки протокола RS: "
<<
endl
;
MBExchange
::
help_print
(
argc
,
argv
);
// cout << " Настройки протокола RS: " << endl;
cout
<<
"--prefix-dev devname - файл устройства"
<<
endl
;
cout
<<
"--prefix-speed - Скорость обмена (9600,19920,38400,57600,115200)."
<<
endl
;
cout
<<
"--prefix-my-addr - адрес текущего узла"
<<
endl
;
...
...
@@ -1500,30 +1342,6 @@ RTUExchange* RTUExchange::init_rtuexchange( int argc, const char* const* argv, U
return
new
RTUExchange
(
ID
,
icID
,
ic
,
prefix
);
}
// -----------------------------------------------------------------------------
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
RTUExchange
::
DeviceType
&
dt
)
{
switch
(
dt
)
{
case
RTUExchange
:
:
dtRTU
:
os
<<
"RTU"
;
break
;
case
RTUExchange
:
:
dtRTU188
:
os
<<
"RTU188"
;
break
;
case
RTUExchange
:
:
dtMTR
:
os
<<
"MTR"
;
break
;
default
:
os
<<
"Unknown device type ("
<<
(
int
)
dt
<<
")"
;
break
;
}
return
os
;
}
// -----------------------------------------------------------------------------
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
RTUExchange
::
RSProperty
&
p
)
{
os
<<
" ("
<<
ModbusRTU
::
dat2str
(
p
.
reg
->
mbreg
)
<<
")"
...
...
@@ -1750,6 +1568,9 @@ void RTUExchange::updateRSProperty( RSProperty* p, bool write_only )
if
(
!
save
&&
write_only
)
return
;
if
(
!
checkUpdateSM
(
save
)
)
return
;
try
{
if
(
p
->
vType
==
VTypes
::
vtUnknown
)
...
...
extensions/RTUExchange/RTUExchange.h
View file @
089e9ffb
...
...
@@ -5,22 +5,12 @@
#include <string>
#include <map>
#include <vector>
#include "IONotifyController.h"
#include "UniSetObject_LT.h"
#include "MBExchange.h"
#include "modbus/ModbusRTUMaster.h"
#include "PassiveTimer.h"
#include "Trigger.h"
#include "Mutex.h"
#include "Calibration.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "MTR.h"
#include "RTUStorage.h"
#include "IOBase.h"
#include "VTypes.h"
// -----------------------------------------------------------------------------
class
RTUExchange
:
public
UniSetObject_LT
public
MBExchange
{
public
:
RTUExchange
(
UniSetTypes
::
ObjectId
objId
,
UniSetTypes
::
ObjectId
shmID
,
...
...
@@ -35,24 +25,12 @@ class RTUExchange:
/*! глобальная функция для вывода help-а */
static
void
help_print
(
int
argc
,
const
char
*
const
*
argv
);
static
const
int
NoSafetyState
=-
1
;
enum
Timer
{
tmExchange
};
enum
DeviceType
{
dtUnknown
,
/*!< неизвестный */
dtRTU
,
/*!< RTU (default) */
dtRTU188
,
/*!< RTU188 (Fastwell) */
dtMTR
/*!< MTR (DEIF) */
};
static
DeviceType
getDeviceType
(
const
std
::
string
dtype
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
DeviceType
&
dt
);
// -------------------------------------------------------------------------------
// --------------------------------------------------------
struct
RTUDevice
;
struct
RegInfo
;
...
...
@@ -181,13 +159,7 @@ class RTUExchange:
bool
use485F
;
bool
transmitCtl
;
xmlNode
*
cnode
;
std
::
string
s_field
;
std
::
string
s_fvalue
;
SMInterface
*
shm
;
void
step
();
virtual
void
step
();
void
poll
();
bool
pollRTU
(
RTUDevice
*
dev
,
RegMap
::
iterator
&
it
);
...
...
@@ -198,12 +170,11 @@ class RTUExchange:
void
updateRSProperty
(
RSProperty
*
p
,
bool
write_only
=
false
);
virtual
void
processingMessage
(
UniSetTypes
::
VoidMessage
*
msg
);
void
sysCommand
(
UniSetTypes
::
SystemMessage
*
msg
);
void
sensorInfo
(
UniSetTypes
::
SensorMessage
*
sm
);
v
irtual
v
oid
sysCommand
(
UniSetTypes
::
SystemMessage
*
msg
);
v
irtual
v
oid
sensorInfo
(
UniSetTypes
::
SensorMessage
*
sm
);
void
timerInfo
(
UniSetTypes
::
TimerMessage
*
tm
);
void
askSensors
(
UniversalIO
::
UIOCommand
cmd
);
void
initOutput
();
void
waitSMReady
();
virtual
bool
activateObject
();
...
...
@@ -211,13 +182,11 @@ class RTUExchange:
virtual
void
sigterm
(
int
signo
);
void
initMB
(
bool
reopen
=
false
);
void
initIterators
();
v
irtual
v
oid
initIterators
();
bool
initItem
(
UniXML_iterator
&
it
);
bool
readItem
(
UniXML
&
xml
,
UniXML_iterator
&
it
,
xmlNode
*
sec
);
void
initDeviceList
();
void
initOffsetList
();
RTUDevice
*
addDev
(
RTUDeviceMap
&
dmap
,
ModbusRTU
::
ModbusAddr
a
,
UniXML_iterator
&
it
);
RegInfo
*
addReg
(
RegMap
&
rmap
,
ModbusRTU
::
ModbusData
r
,
UniXML_iterator
&
it
,
RTUDevice
*
dev
,
RegInfo
*
rcopy
=
0
);
...
...
@@ -232,38 +201,14 @@ class RTUExchange:
void
rtuQueryOptimization
(
RTUDeviceMap
&
m
);
void
readConfiguration
();
private
:
RTUExchange
();
bool
initPause
;
UniSetTypes
::
uniset_mutex
mutex_start
;
bool
force
;
/*!< флаг означающий, что надо сохранять в SM, даже если значение не менялось */
bool
force_out
;
/*!< флаг означающий, принудительного чтения выходов */
bool
mbregFromID
;
int
polltime
;
/*!< переодичность обновления данных, [мсек] */
timeout_t
sleepPause_usec
;
PassiveTimer
ptHeartBeat
;
UniSetTypes
::
ObjectId
sidHeartBeat
;
int
maxHeartBeat
;
IOController
::
AIOStateList
::
iterator
aitHeartBeat
;
UniSetTypes
::
ObjectId
test_id
;
UniSetTypes
::
uniset_mutex
pollMutex
;
bool
activated
;
int
activateTimeout
;
bool
rs_pre_clean
;
bool
noQueryOptimization
;
bool
allNotRespond
;
Trigger
trAllNotRespond
;
PassiveTimer
ptAllNotRespond
;
std
::
string
prefix
;
};
// -----------------------------------------------------------------------------
#endif // _RS_EXCHANGE_H_
...
...
extensions/include/MBExchange.h
0 → 100644
View file @
089e9ffb
#ifndef _MBExchange_H_
#define _MBExchange_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <map>
#include <vector>
#include "IONotifyController.h"
#include "UniSetObject_LT.h"
#include "PassiveTimer.h"
#include "Trigger.h"
#include "Mutex.h"
#include "Calibration.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "IOBase.h"
#include "VTypes.h"
#include "MTR.h"
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
/*!
\par Базовый класс для реализация обмена по протоколу Modbus [RTU|TCP].
*/
class
MBExchange
:
public
UniSetObject_LT
{
public
:
MBExchange
(
UniSetTypes
::
ObjectId
objId
,
UniSetTypes
::
ObjectId
shmID
,
SharedMemory
*
ic
=
0
,
const
std
::
string
prefix
=
"mb"
);
virtual
~
MBExchange
();
/*! глобальная функция для вывода help-а */
static
void
help_print
(
int
argc
,
const
char
*
const
*
argv
);
static
const
int
NoSafetyState
=-
1
;
/*! Режимы работы процесса обмена */
enum
ExchangeMode
{
emNone
,
/*!< нормальная работа (по умолчанию) */
emWriteOnly
,
/*!< "только посылка данных" (работают только write-функции) */
emReadOnly
,
/*!< "только чтение" (работают только read-функции) */
emSkipSaveToSM
/*!< не писать данные в SM (при этом работают и read и write функции */
};
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
ExchangeMode
&
em
);
enum
DeviceType
{
dtUnknown
,
/*!< неизвестный */
dtRTU
,
/*!< RTU (default) */
dtMTR
,
/*!< MTR (DEIF) */
dtRTU188
/*!< RTU188 (Fastwell) */
};
static
DeviceType
getDeviceType
(
const
std
::
string
dtype
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
DeviceType
&
dt
);
protected
:
virtual
void
step
();
virtual
void
sensorInfo
(
UniSetTypes
::
SensorMessage
*
sm
);
virtual
void
sigterm
(
int
signo
);
virtual
bool
initItem
(
UniXML_iterator
&
it
){
return
false
;
}
virtual
void
initIterators
();
bool
checkUpdateSM
(
bool
wrFunc
);
bool
checkPoll
(
bool
wrFunc
);
bool
checkProcActive
();
void
setProcActive
(
bool
st
);
void
waitSMReady
();
void
readConfiguration
();
bool
readItem
(
UniXML
&
xml
,
UniXML_iterator
&
it
,
xmlNode
*
sec
);
xmlNode
*
cnode
;
std
::
string
s_field
;
std
::
string
s_fvalue
;
SMInterface
*
shm
;
bool
initPause
;
UniSetTypes
::
uniset_mutex
mutex_start
;
bool
force
;
/*!< флаг означающий, что надо сохранять в SM, даже если значение не менялось */
bool
force_out
;
/*!< флаг означающий, принудительного чтения выходов */
bool
mbregFromID
;
int
polltime
;
/*!< переодичность обновления данных, [мсек] */
timeout_t
sleepPause_usec
;
PassiveTimer
ptHeartBeat
;
UniSetTypes
::
ObjectId
sidHeartBeat
;
int
maxHeartBeat
;
IOController
::
AIOStateList
::
iterator
aitHeartBeat
;
UniSetTypes
::
ObjectId
test_id
;
UniSetTypes
::
ObjectId
sidExchangeMode
;
/*!< иденидентификатор для датчика режима работы */
IOController
::
AIOStateList
::
iterator
aitExchangeMode
;
long
exchangeMode
;
/*!< режим работы см. ExchangeMode */
UniSetTypes
::
uniset_mutex
actMutex
;
bool
activated
;
int
activateTimeout
;
bool
noQueryOptimization
;
std
::
string
prefix
;
timeout_t
stat_time
;
/*!< время сбора статистики обмена */
int
poll_count
;
PassiveTimer
ptStatistic
;
/*!< таймер для сбора статистики обмена */
private
:
MBExchange
();
};
// -----------------------------------------------------------------------------
#endif // _MBExchange_H_
// -----------------------------------------------------------------------------
extensions/lib/MBExchange.cc
0 → 100644
View file @
089e9ffb
// -----------------------------------------------------------------------------
#include <cmath>
#include <limits>
#include <sstream>
#include <Exceptions.h>
#include <extensions/Extensions.h>
#include "MBExchange.h"
// -----------------------------------------------------------------------------
using
namespace
std
;
using
namespace
UniSetTypes
;
using
namespace
UniSetExtensions
;
// -----------------------------------------------------------------------------
MBExchange
::
MBExchange
(
UniSetTypes
::
ObjectId
objId
,
UniSetTypes
::
ObjectId
shmId
,
SharedMemory
*
ic
,
const
std
::
string
prefix
)
:
UniSetObject_LT
(
objId
),
shm
(
0
),
initPause
(
0
),
force
(
false
),
force_out
(
false
),
mbregFromID
(
false
),
sidExchangeMode
(
DefaultObjectId
),
activated
(
false
),
noQueryOptimization
(
false
),
prefix
(
prefix
)
{
// cout << "$ $" << endl;
if
(
objId
==
DefaultObjectId
)
throw
UniSetTypes
::
SystemError
(
"(MBExchange): objId=-1?!! Use --"
+
prefix
+
"-name"
);
// xmlNode* cnode = conf->getNode(myname);
string
conf_name
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-confnode"
,
myname
);
cnode
=
conf
->
getNode
(
conf_name
);
if
(
cnode
==
NULL
)
throw
UniSetTypes
::
SystemError
(
"(MBExchange): Not found node <"
+
conf_name
+
" ...> for "
+
myname
);
shm
=
new
SMInterface
(
shmId
,
&
ui
,
objId
,
ic
);
UniXML_iterator
it
(
cnode
);
// определяем фильтр
s_field
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-filter-field"
);
s_fvalue
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-filter-value"
);
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): read fileter-field='"
<<
s_field
<<
"' filter-value='"
<<
s_fvalue
<<
"'"
<<
endl
;
stat_time
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-statistic-sec"
,
it
.
getProp
(
"statistic_sec"
),
0
);
if
(
stat_time
>
0
)
ptStatistic
.
setTiming
(
stat_time
*
1000
);
// recv_timeout = conf->getArgPInt("--" + prefix + "-recv-timeout",it.getProp("recv_timeout"), 500);
//
// int tout = conf->getArgPInt("--" + prefix + "-timeout",it.getProp("timeout"), 5000);
// ptTimeout.setTiming(tout);
noQueryOptimization
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-no-query-optimization"
,
it
.
getProp
(
"no_query_optimization"
));
mbregFromID
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-reg-from-id"
,
it
.
getProp
(
"reg_from_id"
));
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): mbregFromID="
<<
mbregFromID
<<
endl
;
polltime
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-polltime"
,
it
.
getProp
(
"polltime"
),
100
);
initPause
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-initPause"
,
it
.
getProp
(
"initPause"
),
3000
);
sleepPause_usec
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-sleepPause-usec"
,
it
.
getProp
(
"slepePause"
),
100
);
force
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-force"
,
it
.
getProp
(
"force"
));
force_out
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-force-out"
,
it
.
getProp
(
"force_out"
));
// ********** HEARTBEAT *************
string
heart
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-heartbeat-id"
,
it
.
getProp
(
"heartbeat_id"
));
if
(
!
heart
.
empty
()
)
{
sidHeartBeat
=
conf
->
getSensorID
(
heart
);
if
(
sidHeartBeat
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
": ID not found ('HeartBeat') for "
<<
heart
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
int
heartbeatTime
=
getHeartBeatTime
();
if
(
heartbeatTime
)
ptHeartBeat
.
setTiming
(
heartbeatTime
);
else
ptHeartBeat
.
setTiming
(
UniSetTimer
::
WaitUpTime
);
maxHeartBeat
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-heartbeat-max"
,
it
.
getProp
(
"heartbeat_max"
),
10
);
test_id
=
sidHeartBeat
;
}
else
{
test_id
=
conf
->
getSensorID
(
"TestMode_S"
);
if
(
test_id
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
"(init): test_id unknown. 'TestMode_S' not found..."
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
dlog
[
Debug
::
INFO
]
<<
myname
<<
"(init): test_id="
<<
test_id
<<
endl
;
string
emode
=
conf
->
getArgParam
(
"--"
+
prefix
+
"-exchange-mode-id"
,
it
.
getProp
(
"exchangeModeID"
));
if
(
!
emode
.
empty
()
)
{
sidExchangeMode
=
conf
->
getSensorID
(
emode
);
if
(
sidExchangeMode
==
DefaultObjectId
)
{
ostringstream
err
;
err
<<
myname
<<
": ID not found ('ExchangeMode') for "
<<
emode
;
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(init): "
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
activateTimeout
=
conf
->
getArgPInt
(
"--"
+
prefix
+
"-activate-timeout"
,
20000
);
}
// -----------------------------------------------------------------------------
void
MBExchange
::
help_print
(
int
argc
,
const
char
*
const
*
argv
)
{
cout
<<
"--prefix-name name - ObjectId (имя) процесса. По умолчанию: MBTCPMaster1"
<<
endl
;
cout
<<
"--prefix-confnode name - Настроечная секция в конф. файле <name>. "
<<
endl
;
cout
<<
"--prefix-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек."
<<
endl
;
cout
<<
"--prefix-heartbeat-id name - Данный процесс связан с указанным аналоговым heartbeat-дачиком."
<<
endl
;
cout
<<
"--prefix-heartbeat-max val - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10."
<<
endl
;
cout
<<
"--prefix-ready-timeout msec - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')"
<<
endl
;
cout
<<
"--prefix-force 0,1 - Сохранять значения в SM, независимо от, того менялось ли значение"
<<
endl
;
cout
<<
"--prefix-force-out 0,1 - Считывать значения 'выходов' кажый раз SM (а не по изменению)"
<<
endl
;
cout
<<
"--prefix-initPause msec - Задержка перед инициализацией (время на активизация процесса)"
<<
endl
;
cout
<<
"--prefix-no-query-optimization 0,1 - Не оптимизировать запросы (не объединять соседние регистры в один запрос)"
<<
endl
;
cout
<<
"--prefix-reg-from-id 0,1 - Использовать в качестве регистра sensor ID"
<<
endl
;
cout
<<
"--prefix-filter-field name - Считывать список опрашиваемых датчиков, только у которых есть поле field"
<<
endl
;
cout
<<
"--prefix-filter-value val - Считывать список опрашиваемых датчиков, только у которых field=value"
<<
endl
;
cout
<<
"--prefix-statistic-sec sec - Выводить статистику опроса каждые sec секунд"
<<
endl
;
cout
<<
"--prefix-sm-ready-timeout - время на ожидание старта SM"
<<
endl
;
}
// -----------------------------------------------------------------------------
MBExchange
::~
MBExchange
()
{
delete
shm
;
}
// -----------------------------------------------------------------------------
void
MBExchange
::
waitSMReady
()
{
// waiting for SM is ready...
int
ready_timeout
=
conf
->
getArgInt
(
"--"
+
prefix
+
"-sm-ready-timeout"
,
"15000"
);
if
(
ready_timeout
==
0
)
ready_timeout
=
15000
;
else
if
(
ready_timeout
<
0
)
ready_timeout
=
UniSetTimer
::
WaitUpTime
;
if
(
!
shm
->
waitSMready
(
ready_timeout
,
50
)
)
{
ostringstream
err
;
err
<<
myname
<<
"(waitSMReady): failed waiting SharedMemory "
<<
ready_timeout
<<
" msec"
;
dlog
[
Debug
::
CRIT
]
<<
err
.
str
()
<<
endl
;
throw
SystemError
(
err
.
str
());
}
}
// -----------------------------------------------------------------------------
void
MBExchange
::
step
()
{
if
(
!
checkProcActive
()
)
return
;
if
(
sidHeartBeat
!=
DefaultObjectId
&&
ptHeartBeat
.
checkTime
()
)
{
try
{
shm
->
localSaveValue
(
aitHeartBeat
,
sidHeartBeat
,
maxHeartBeat
,
getId
());
ptHeartBeat
.
reset
();
}
catch
(
Exception
&
ex
)
{
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(step): (hb) "
<<
ex
<<
std
::
endl
;
}
}
}
// -----------------------------------------------------------------------------
bool
MBExchange
::
checkProcActive
()
{
uniset_mutex_lock
l
(
actMutex
,
300
);
return
activated
;
}
// -----------------------------------------------------------------------------
void
MBExchange
::
setProcActive
(
bool
st
)
{
uniset_mutex_lock
l
(
actMutex
,
400
);
activated
=
st
;
}
// -----------------------------------------------------------------------------
void
MBExchange
::
sensorInfo
(
UniSetTypes
::
SensorMessage
*
sm
)
{
if
(
force_out
)
return
;
if
(
sm
->
id
==
sidExchangeMode
)
{
exchangeMode
=
sm
->
value
;
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
myname
<<
"(sensorInfo): exchange MODE="
<<
sm
->
value
<<
std
::
endl
;
return
;
}
}
// ------------------------------------------------------------------------------------------
void
MBExchange
::
sigterm
(
int
signo
)
{
dlog
[
Debug
::
WARN
]
<<
myname
<<
": ********* SIGTERM("
<<
signo
<<
") ********"
<<
endl
;
setProcActive
(
false
);
UniSetObject_LT
::
sigterm
(
signo
);
}
// ------------------------------------------------------------------------------------------
void
MBExchange
::
readConfiguration
()
{
// readconf_ok = false;
xmlNode
*
root
=
conf
->
getXMLSensorsSection
();
if
(
!
root
)
{
ostringstream
err
;
err
<<
myname
<<
"(readConfiguration): не нашли корневого раздела <sensors>"
;
throw
SystemError
(
err
.
str
());
}
UniXML_iterator
it
(
root
);
if
(
!
it
.
goChildren
()
)
{
dlog
[
Debug
::
CRIT
]
<<
myname
<<
"(readConfiguration): раздел <sensors> не содержит секций ?!!
\n
"
;
return
;
}
for
(
;
it
.
getCurrent
();
it
.
goNext
()
)
{
if
(
UniSetTypes
::
check_filter
(
it
,
s_field
,
s_fvalue
)
)
initItem
(
it
);
}
// readconf_ok = true;
}
// ------------------------------------------------------------------------------------------
bool
MBExchange
::
readItem
(
UniXML
&
xml
,
UniXML_iterator
&
it
,
xmlNode
*
sec
)
{
if
(
UniSetTypes
::
check_filter
(
it
,
s_field
,
s_fvalue
)
)
initItem
(
it
);
return
true
;
}
// ------------------------------------------------------------------------------------------
MBExchange
::
DeviceType
MBExchange
::
getDeviceType
(
const
std
::
string
dtype
)
{
if
(
dtype
.
empty
()
)
return
dtUnknown
;
if
(
dtype
==
"mtr"
||
dtype
==
"MTR"
)
return
dtMTR
;
if
(
dtype
==
"rtu"
||
dtype
==
"RTU"
)
return
dtRTU
;
return
dtUnknown
;
}
// ------------------------------------------------------------------------------------------
void
MBExchange
::
initIterators
()
{
shm
->
initAIterator
(
aitHeartBeat
);
shm
->
initAIterator
(
aitExchangeMode
);
}
// -----------------------------------------------------------------------------
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
MBExchange
::
DeviceType
&
dt
)
{
switch
(
dt
)
{
case
MBExchange
:
:
dtRTU
:
os
<<
"RTU"
;
break
;
case
MBExchange
:
:
dtMTR
:
os
<<
"MTR"
;
break
;
default
:
os
<<
"Unknown device type ("
<<
(
int
)
dt
<<
")"
;
break
;
}
return
os
;
}
// -----------------------------------------------------------------------------
bool
MBExchange
::
checkUpdateSM
(
bool
wrFunc
)
{
if
(
wrFunc
&&
exchangeMode
==
emReadOnly
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
"(checkUpdateSM):"
<<
" skip... mode='emReadOnly' "
<<
endl
;
return
false
;
}
if
(
!
wrFunc
&&
exchangeMode
==
emWriteOnly
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
"(checkUpdateSM):"
<<
" skip... mode='emWriteOnly' "
<<
endl
;
return
false
;
}
if
(
wrFunc
&&
exchangeMode
==
emSkipSaveToSM
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
"(checkUpdateSM):"
<<
" skip... mode='emSkipSaveToSM' "
<<
endl
;
return
false
;
}
return
true
;
}
// -----------------------------------------------------------------------------
bool
MBExchange
::
checkPoll
(
bool
wrFunc
)
{
if
(
exchangeMode
==
emWriteOnly
&&
!
wrFunc
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
myname
<<
"(checkPoll): skip.. mode='emWriteOnly'"
<<
endl
;
return
false
;
}
if
(
exchangeMode
==
emReadOnly
&&
wrFunc
)
{
if
(
dlog
.
debugging
(
Debug
::
LEVEL3
)
)
dlog
[
Debug
::
LEVEL3
]
<<
myname
<<
"(checkPoll): skip.. poll mode='emReadOnly'"
<<
endl
;
return
false
;
}
return
true
;
}
// -----------------------------------------------------------------------------
extensions/lib/Makefile.am
View file @
089e9ffb
...
...
@@ -6,6 +6,6 @@ libUniSetExtensions_la_LDFLAGS = -version-info $(UEXT_VER)
libUniSetExtensions_la_CPPFLAGS
=
$(SIGC_CFLAGS)
-I
$(top_builddir)
/extensions/include
libUniSetExtensions_la_LIBADD
=
$(SIGC_LIBS)
$(top_builddir)
/lib/libUniSet.la
libUniSetExtensions_la_SOURCES
=
Extensions.cc SMInterface.cc Calibration.cc SingleProcess.cc
\
IOBase.cc DigitalFilter.cc PID.cc MTR.cc VTypes.cc
IOBase.cc DigitalFilter.cc PID.cc MTR.cc VTypes.cc
MBExchange.cc
#UObject_SK.cc
\ No newline at end of file
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