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
c17b06c3
Commit
c17b06c3
authored
Mar 01, 2010
by
Pavel Vaynerman
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of git.eter:/projects/uniset
parents
af13ad1e
e77363e6
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
218 additions
and
20 deletions
+218
-20
IOController_i.idl
IDL/Processes/IOController_i.idl
+1
-0
ctl-cpp-cc-alone-ask.xsl
Utilities/codegen/ctl-cpp-cc-alone-ask.xsl
+1
-1
ctl-cpp-cc-alone.xsl
Utilities/codegen/ctl-cpp-cc-alone.xsl
+1
-1
ctl-cpp-cc-ask.xsl
Utilities/codegen/ctl-cpp-cc-ask.xsl
+1
-1
ctl-cpp-cc.xsl
Utilities/codegen/ctl-cpp-cc.xsl
+1
-1
ctl-cpp-common.xsl
Utilities/codegen/ctl-cpp-common.xsl
+28
-8
libuniset.spec
conf/libuniset.spec
+7
-1
Concept.dox
docs/DocPages/Concept.dox
+2
-2
IOBase.cc
extensions/lib/IOBase.cc
+15
-4
Makefile.am
tests/Makefile.am
+5
-1
conftest.cc
tests/conftest.cc
+43
-0
conftest.sh
tests/conftest.sh
+12
-0
passivetimer.cc
tests/passivetimer.cc
+13
-0
testID.xml
tests/testID.xml
+88
-0
No files found.
IDL/Processes/IOController_i.idl
View file @
c17b06c3
...
@@ -291,6 +291,7 @@ interface IONotifyController_i : IOController_i
...
@@ -291,6 +291,7 @@ interface IONotifyController_i : IOController_i
ThresholdState
state
;
ThresholdState
state
;
long
tv_sec
; /*!< , (gettimeofday) */
long
tv_sec
; /*!< , (gettimeofday) */
long
tv_usec
; /*!< , (gettimeofday) */
long
tv_usec
; /*!< , (gettimeofday) */
boolean
inverse
; /*!< */
}
;
}
;
typedef
sequence
<
ThresholdInfo
>
ThresholdInfoSeq
;
typedef
sequence
<
ThresholdInfo
>
ThresholdInfoSeq
;
...
...
Utilities/codegen/ctl-cpp-cc-alone-ask.xsl
View file @
c17b06c3
...
@@ -287,7 +287,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::updateOutputs( bool force )
...
@@ -287,7 +287,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::updateOutputs( bool force )
</xsl:for-each>
</xsl:for-each>
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Info
( UniSetTypes::ObjectId code, bool state )
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Msg
( UniSetTypes::ObjectId code, bool state )
{
{
// (.. )
// (.. )
if( !state )
if( !state )
...
...
Utilities/codegen/ctl-cpp-cc-alone.xsl
View file @
c17b06c3
...
@@ -209,7 +209,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::updateOutputs( bool force )
...
@@ -209,7 +209,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::updateOutputs( bool force )
-->
-->
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Info
( UniSetTypes::ObjectId code, bool state )
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Msg
( UniSetTypes::ObjectId code, bool state )
{
{
// (.. )
// (.. )
if( !state )
if( !state )
...
...
Utilities/codegen/ctl-cpp-cc-ask.xsl
View file @
c17b06c3
...
@@ -262,7 +262,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::askSensors( UniversalIO::UIOCommand
...
@@ -262,7 +262,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::askSensors( UniversalIO::UIOCommand
}
}
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Info
( UniSetTypes::ObjectId code, bool state )
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Msg
( UniSetTypes::ObjectId code, bool state )
{
{
// (.. )
// (.. )
if( !state )
if( !state )
...
...
Utilities/codegen/ctl-cpp-cc.xsl
View file @
c17b06c3
...
@@ -198,7 +198,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::preSensorInfo( UniSetTypes::SensorM
...
@@ -198,7 +198,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::preSensorInfo( UniSetTypes::SensorM
sensorInfo(sm);
sensorInfo(sm);
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Info
( UniSetTypes::ObjectId code, bool state )
void
<xsl:value-of
select=
"$CLASSNAME"
/>
_SK::set
Msg
( UniSetTypes::ObjectId code, bool state )
{
{
// (.. )
// (.. )
if( !state )
if( !state )
...
...
Utilities/codegen/ctl-cpp-common.xsl
View file @
c17b06c3
...
@@ -122,8 +122,18 @@
...
@@ -122,8 +122,18 @@
</xsl:when>
</xsl:when>
<xsl:when
test=
"$GENTYPE='R'"
>
<xsl:when
test=
"$GENTYPE='R'"
>
m_
<xsl:value-of
select=
"../../@name"
/>
= 0;
m_
<xsl:value-of
select=
"../../@name"
/>
= 0;
si.id = mid_
<xsl:value-of
select=
"../../@name"
/>
;
if( mid_
<xsl:value-of
select=
"../../@name"
/>
!= UniSetTypes::DefaultObjectId )
ui.saveState( si,false,UniversalIO::DigitalInput,getId() );
{
try
{
si.id = mid_
<xsl:value-of
select=
"../../@name"
/>
;
ui.saveState( si,false,UniversalIO::DigitalInput,getId() );
}
catch( UniSetTypes::Exception
&
ex )
{
unideb[Debug::LEVEL1]
<<
getName()
<<
ex
<<
endl;
}
}
</xsl:when>
</xsl:when>
</xsl:choose>
</xsl:choose>
</xsl:if>
</xsl:if>
...
@@ -166,7 +176,7 @@
...
@@ -166,7 +176,7 @@
UniSetTypes::ObjectId backid = UniSetTypes::DefaultObjectId );
UniSetTypes::ObjectId backid = UniSetTypes::DefaultObjectId );
void updateValues();
void updateValues();
void set
Info
( UniSetTypes::ObjectId code, bool state );
void set
Msg
( UniSetTypes::ObjectId code, bool state );
</xsl:template>
</xsl:template>
<xsl:template
name=
"COMMON-HEAD-PROTECTED"
>
<xsl:template
name=
"COMMON-HEAD-PROTECTED"
>
...
@@ -550,7 +560,7 @@ activated(false)
...
@@ -550,7 +560,7 @@ activated(false)
sleep_msec = conf->getArgPInt("--sleep-msec","
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
",
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
);
sleep_msec = conf->getArgPInt("--sleep-msec","
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
",
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
);
resetMsgTime = conf->getPIntProp(cnode,"resetMsgTime", 200);
resetMsgTime = conf->getPIntProp(cnode,"resetMsgTime", 200
0
);
ptResetMsg.setTiming(resetMsgTime);
ptResetMsg.setTiming(resetMsgTime);
smReadyTimeout = conf->getArgInt("--sm-ready-timeout","
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'smReadyTimeout'"
/></xsl:call-template>
");
smReadyTimeout = conf->getArgInt("--sm-ready-timeout","
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'smReadyTimeout'"
/></xsl:call-template>
");
...
@@ -657,9 +667,19 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::resetMsg()
...
@@ -657,9 +667,19 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::resetMsg()
// reset messages
// reset messages
<xsl:for-each
select=
"//msgmap/item"
>
<xsl:for-each
select=
"//msgmap/item"
>
m_
<xsl:value-of
select=
"@name"
/>
= 0;
m_
<xsl:value-of
select=
"@name"
/>
= 0;
si.id =
<xsl:value-of
select=
"@name"
/>
;
if(
<xsl:value-of
select=
"@name"
/>
!= UniSetTypes::DefaultObjectId )
si.node = node_
<xsl:value-of
select=
"@name"
/>
;
{
ui.saveState( si,false,UniversalIO::DigitalInput,getId() );
try
{
si.id =
<xsl:value-of
select=
"@name"
/>
;
si.node = node_
<xsl:value-of
select=
"@name"
/>
;
ui.saveState( si,false,UniversalIO::DigitalInput,getId() );
}
catch( UniSetTypes::Exception
&
ex )
{
unideb[Debug::LEVEL1]
<<
getName()
<<
ex
<<
endl;
}
}
</xsl:for-each>
</xsl:for-each>
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
...
@@ -766,7 +786,7 @@ activated(false)
...
@@ -766,7 +786,7 @@ activated(false)
sleep_msec = conf->getArgPInt("--sleep-msec","
<xsl:call-template
name=
"settings-alone"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
",
<xsl:call-template
name=
"settings-alone"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
);
sleep_msec = conf->getArgPInt("--sleep-msec","
<xsl:call-template
name=
"settings-alone"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
",
<xsl:call-template
name=
"settings-alone"
><xsl:with-param
name=
"varname"
select=
"'sleep-msec'"
/></xsl:call-template>
);
resetMsgTime = conf->getPIntProp(cnode,"resetMsgTime", 0);
resetMsgTime = conf->getPIntProp(cnode,"resetMsgTime",
200
0);
ptResetMsg.setTiming(resetMsgTime);
ptResetMsg.setTiming(resetMsgTime);
smReadyTimeout = conf->getArgInt("--sm-ready-timeout","
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'smReadyTimeout'"
/></xsl:call-template>
");
smReadyTimeout = conf->getArgInt("--sm-ready-timeout","
<xsl:call-template
name=
"settings"
><xsl:with-param
name=
"varname"
select=
"'smReadyTimeout'"
/></xsl:call-template>
");
...
...
conf/libuniset.spec
View file @
c17b06c3
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
Name: libuniset
Name: libuniset
Version: 0.97
Version: 0.97
Release: eter5
3
Release: eter5
4
Summary: UniSet - library for building distributed industrial control systems
Summary: UniSet - library for building distributed industrial control systems
License: GPL
License: GPL
Group: Development/C++
Group: Development/C++
...
@@ -183,6 +183,12 @@ rm -f %buildroot%_libdir/*.la
...
@@ -183,6 +183,12 @@ rm -f %buildroot%_libdir/*.la
%exclude %_pkgconfigdir/libUniSet.pc
%exclude %_pkgconfigdir/libUniSet.pc
%changelog
%changelog
* Sat Feb 13 2010 Pavel Vainerman <pv@altlinux.ru> 0.97-eter54
- fixed bug in codegen
* Thu Feb 04 2010 Pavel Vainerman <pv@altlinux.ru> 0.97-eter53
- new build
* Tue Feb 02 2010 Larik Ishkulov <gentro@etersoft.ru> 0.97-eter52
* Tue Feb 02 2010 Larik Ishkulov <gentro@etersoft.ru> 0.97-eter52
- new build
- new build
...
...
docs/DocPages/Concept.dox
View file @
c17b06c3
...
@@ -183,8 +183,8 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
...
@@ -183,8 +183,8 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
- AO - UniversalIO::AnalogOutput -
- AO - UniversalIO::AnalogOutput -
/.
/.
""(D
I,AI
) - , " "
""(D
O,AO
) - , " "
""(D
O,AO
) - " ".
""(D
I,AI
) - " ".
, "" .
, "" .
ң , ,
ң , ,
,
,
...
...
extensions/lib/IOBase.cc
View file @
c17b06c3
...
@@ -369,10 +369,20 @@ void IOBase::processingThreshold( IOBase* it, SMInterface* shm, bool force )
...
@@ -369,10 +369,20 @@ void IOBase::processingThreshold( IOBase* it, SMInterface* shm, bool force )
// cout << "val=" << val << " set=" << set << endl;
// cout << "val=" << val << " set=" << set << endl;
//
//
// lowLimit-
// lowLimit-
if
(
val
<=
(
it
->
ti
.
lowlimit
-
it
->
ti
.
sensibility
)
)
if
(
it
->
ti
.
inverse
)
set
=
false
;
{
else
if
(
val
>=
(
it
->
ti
.
hilimit
+
it
->
ti
.
sensibility
)
)
if
(
val
<=
(
it
->
ti
.
lowlimit
-
it
->
ti
.
sensibility
)
)
set
=
true
;
set
=
true
;
else
if
(
val
>=
(
it
->
ti
.
hilimit
+
it
->
ti
.
sensibility
)
)
set
=
false
;
}
else
{
if
(
val
<=
(
it
->
ti
.
lowlimit
-
it
->
ti
.
sensibility
)
)
set
=
false
;
else
if
(
val
>=
(
it
->
ti
.
hilimit
+
it
->
ti
.
sensibility
)
)
set
=
true
;
}
// cout << "thresh: set=" << set << endl;
// cout << "thresh: set=" << set << endl;
processingAsDI
(
it
,
set
,
shm
,
force
);
processingAsDI
(
it
,
set
,
shm
,
force
);
...
@@ -527,6 +537,7 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
...
@@ -527,6 +537,7 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
b
->
ti
.
lowlimit
=
it
.
getIntProp
(
"lowlimit"
);
b
->
ti
.
lowlimit
=
it
.
getIntProp
(
"lowlimit"
);
b
->
ti
.
hilimit
=
it
.
getIntProp
(
"hilimit"
);
b
->
ti
.
hilimit
=
it
.
getIntProp
(
"hilimit"
);
b
->
ti
.
sensibility
=
it
.
getIntProp
(
"sensibility"
);
b
->
ti
.
sensibility
=
it
.
getIntProp
(
"sensibility"
);
b
->
ti
.
inverse
=
it
.
getIntProp
(
"inverse"
);
}
}
}
}
// else
// else
...
...
tests/Makefile.am
View file @
c17b06c3
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
# This file is part of the UniSet library #
# This file is part of the UniSet library #
############################################################################
############################################################################
noinst_PROGRAMS
=
passivetimer unixml ui umutex
noinst_PROGRAMS
=
passivetimer unixml ui umutex
conftest
passivetimer_SOURCES
=
passivetimer.cc
passivetimer_SOURCES
=
passivetimer.cc
passivetimer_LDADD
=
$(top_builddir)
/lib/libUniSet.la
passivetimer_LDADD
=
$(top_builddir)
/lib/libUniSet.la
...
@@ -20,6 +20,10 @@ umutex_SOURCES = umutex.cc
...
@@ -20,6 +20,10 @@ umutex_SOURCES = umutex.cc
umutex_LDADD
=
$(top_builddir)
/lib/libUniSet.la
umutex_LDADD
=
$(top_builddir)
/lib/libUniSet.la
umutex_CPPFLAGS
=
-I
$(top_builddir)
/include
umutex_CPPFLAGS
=
-I
$(top_builddir)
/include
conftest_SOURCES
=
conftest.cc
conftest_LDADD
=
$(top_builddir)
/lib/libUniSet.la
conftest_CPPFLAGS
=
-I
$(top_builddir)
/include
include
$(top_builddir)/conf/setting.mk
include
$(top_builddir)/conf/setting.mk
tests/conftest.cc
0 → 100644
View file @
c17b06c3
// --------------------------------------------------------------------------
//! \version $Id: smemory.cc,v 1.1 2008/12/14 21:57:50 vpashka Exp $
// --------------------------------------------------------------------------
#include <string>
#include "Debug.h"
#include "Configuration.h"
// --------------------------------------------------------------------------
using
namespace
std
;
using
namespace
UniSetTypes
;
// --------------------------------------------------------------------------
int
main
(
int
argc
,
const
char
**
argv
)
{
if
(
argc
>
1
&&
strcmp
(
argv
[
1
],
"--help"
)
==
0
)
{
cout
<<
"--confile - Configuration file. Default: test.xml"
<<
endl
;
return
0
;
}
try
{
string
confile
=
UniSetTypes
::
getArgParam
(
"--confile"
,
argc
,
argv
,
"test.xml"
);
conf
=
new
Configuration
(
argc
,
argv
,
confile
);
string
t
(
conf
->
oind
->
getTextName
(
1
));
cout
<<
"**** check getTextName: "
<<
(
t
.
empty
()
?
"FAILED"
:
"OK"
)
<<
endl
;
return
0
;
}
catch
(
SystemError
&
err
)
{
cerr
<<
"(conftest): "
<<
err
<<
endl
;
}
catch
(
Exception
&
ex
)
{
cerr
<<
"(conftest): "
<<
ex
<<
endl
;
}
catch
(...)
{
cerr
<<
"(conftest): catch(...)"
<<
endl
;
}
return
1
;
}
tests/conftest.sh
0 → 100755
View file @
c17b06c3
#!/bin/sh
SID
=
$1
[
-z
"
$SID
"
]
&&
SID
=
1
echo
"check auto ID configuration..."
uniset-start.sh
-f
./conftest
--confile
test.xml
echo
"check id from file configuration..."
uniset-start.sh
-f
./conftest
--confile
testID.xml
tests/passivetimer.cc
View file @
c17b06c3
...
@@ -32,6 +32,19 @@ int main()
...
@@ -32,6 +32,19 @@ int main()
}
}
PassiveTimer
pt4
(
350
);
for
(
int
i
=
0
;
i
<
12
;
i
++
)
{
cerr
<<
"pt4: check time = "
<<
pt4
.
checkTime
()
<<
endl
;
if
(
pt4
.
checkTime
()
)
{
cerr
<<
"pt4: reset..."
<<
endl
;
pt4
.
reset
();
}
msleep
(
200
);
}
while
(
1
)
while
(
1
)
{
{
cerr
<<
"timer="
<<
pt
.
checkTime
()
<<
endl
;
cerr
<<
"timer="
<<
pt
.
checkTime
()
<<
endl
;
...
...
tests/testID.xml
0 → 100644
View file @
c17b06c3
<?xml version = '1.0' encoding = 'koi8-r' ?>
<UNISETPLC>
<UserData></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"
/>
<!-- [] -->
<!-- Debug, logs -->
<UniSetDebug
name=
"unideb"
levels=
"crit,warn"
file=
""
/>
<!-- , -->
<ConfDir
name=
""
/>
<DataDir
name=
""
/>
<BinDir
name=
""
/>
<LogDir
name=
""
/>
<DocDir
name=
""
/>
<LockDir
name=
""
/>
<Services>
<LocalTimeService
name=
"TimeService"
MaxCountTimers=
"100"
AskLifeTimeSEC=
"10"
/>
<LocalInfoServer
name=
"InfoServer"
dbrepeat=
"1"
>
<RouteList>
</RouteList>
</LocalInfoServer>
<LocalDBServer
name=
"DBServer"
dbnode=
""
dbname=
"UNISET_PLC"
dbuser=
"dbadmin"
dbpass=
"dbadmin"
pingTime=
"60000"
reconnectTime=
"30000"
/>
<LocalPrintServer
device=
"/dev/lp0"
checkTime=
"5000"
/>
</Services>
</UniSet>
<dlog
name=
"dlog"
levels=
""
file=
""
/>
<ObjectsMap
idfromfile=
"1"
>
<!--
'sensors'
==========================================
node -
iotype -
priority -
textname -
-->
<nodes
port=
"2809"
>
<item
id=
"1000"
name=
"LocalhostNode"
alias=
""
textname=
" "
ip=
"127.0.0.1"
/>
<item
id=
"1001"
name=
"Node2"
alias=
""
textname=
" "
ip=
"127.0.0.1"
/>
</nodes>
<!-- ************************ ********************** -->
<sensors
name=
"Sensors"
>
<item
id=
"1"
name=
"Input1_S"
textname=
" 1"
node=
""
iotype=
"DI"
priority=
"Medium"
default=
"1"
/>
<item
id=
"4"
name=
"Input2_S"
textname=
" 2"
node=
""
iotype=
"DI"
priority=
"Medium"
/>
<item
id=
"140"
name=
"Input3_S"
textname=
" 3"
node=
""
iotype=
"DI"
priority=
"Medium"
/>
</sensors>
<thresholds
name=
"thresholds"
>
</thresholds>
<controllers
name=
"Controllers"
>
<item
id=
"90"
name=
"SharedMemory"
/>
</controllers>
<!-- ******************* ***************** -->
<services
name=
"Services"
>
<item
id=
"99"
name=
"TimeService"
/>
</services>
<!-- ******************* ***************** -->
<objects
name=
"UniObjects"
>
<item
id=
"100"
name=
"TestProc"
/>
</objects>
</ObjectsMap>
<messages
name=
"messages"
idfromfile=
"1"
>
</messages>
</UNISETPLC>
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