Commit 1ee14014 authored by Pavel Vainerman's avatar Pavel Vainerman

(IOBase): запретил переопределять id и name. Разрешил переопределять

различные параметры (mbreg,mbfunc) и т.п. для ModbusSlave,ModusMaster.
parent b58e2dd0
...@@ -860,7 +860,7 @@ bool MBExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it ) ...@@ -860,7 +860,7 @@ bool MBExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
for( unsigned int i=0; i<ret.bcnt; i++ ) for( unsigned int i=0; i<ret.bcnt; i++ )
{ {
ModbusRTU::DataBits b(ret.data[i]); ModbusRTU::DataBits b(ret.data[i]);
for( int k=0;k<ModbusRTU::BitsPerByte && m<p->q_count; k++,it++,m++ ) for( unsigned int k=0;k<ModbusRTU::BitsPerByte && m<p->q_count; k++,it++,m++ )
it->second->mbval = b[k]; it->second->mbval = b[k];
} }
it--; it--;
...@@ -1882,7 +1882,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it ) ...@@ -1882,7 +1882,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
return true; return true;
} }
if( it.getIntProp(prop_prefix + "rawdata") ) if( IOBase::initIntProp(it,"rawdata",prefix,false) )
{ {
p.cal.minRaw = 0; p.cal.minRaw = 0;
p.cal.maxRaw = 0; p.cal.maxRaw = 0;
...@@ -1892,7 +1892,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it ) ...@@ -1892,7 +1892,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
p.cdiagram = 0; p.cdiagram = 0;
} }
string sbit(it.getProp(prop_prefix + "nbit")); string sbit(IOBase::initProp(it,"nbit",prefix,false));
if( !sbit.empty() ) if( !sbit.empty() )
{ {
p.nbit = UniSetTypes::uni_atoi(sbit.c_str()); p.nbit = UniSetTypes::uni_atoi(sbit.c_str());
...@@ -1912,7 +1912,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it ) ...@@ -1912,7 +1912,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
<< " but iotype=" << p.stype << " for " << it.getProp("name") << endl; << " but iotype=" << p.stype << " for " << it.getProp("name") << endl;
} }
string sbyte(it.getProp(prop_prefix + "nbyte")); string sbyte(IOBase::initProp(it,"nbyte",prefix,false) );
if( !sbyte.empty() ) if( !sbyte.empty() )
{ {
p.nbyte = UniSetTypes::uni_atoi(sbyte.c_str()); p.nbyte = UniSetTypes::uni_atoi(sbyte.c_str());
...@@ -1924,7 +1924,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it ) ...@@ -1924,7 +1924,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
} }
} }
string vt(it.getProp(prop_prefix + "vtype")); string vt( IOBase::initProp(it,"vtype",prefix,false) );
if( vt.empty() ) if( vt.empty() )
{ {
p.rnum = VTypes::wsize(VTypes::vtUnknown); p.rnum = VTypes::wsize(VTypes::vtUnknown);
...@@ -1952,7 +1952,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it ) ...@@ -1952,7 +1952,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUDevice* dev ) bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUDevice* dev )
{ {
r->dev = dev; r->dev = dev;
r->mbval = it.getIntProp("default"); r->mbval = IOBase::initIntProp(it,"default",prefix,false);
if( dev->dtype == MBExchange::dtRTU ) if( dev->dtype == MBExchange::dtRTU )
{ {
...@@ -1970,7 +1970,7 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD ...@@ -1970,7 +1970,7 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD
if( !initRTU188item(it,r) ) if( !initRTU188item(it,r) )
return false; return false;
UniversalIO::IOType t = UniSetTypes::getIOType(it.getProp("iotype")); UniversalIO::IOType t = UniSetTypes::getIOType(IOBase::initProp(it,"iotype",prefix,false));
r->mbreg = RTUStorage::getRegister(r->rtuJack,r->rtuChan,t); r->mbreg = RTUStorage::getRegister(r->rtuJack,r->rtuChan,t);
r->mbfunc = RTUStorage::getFunction(r->rtuJack,r->rtuChan,t); r->mbfunc = RTUStorage::getFunction(r->rtuJack,r->rtuChan,t);
...@@ -1995,7 +1995,7 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD ...@@ -1995,7 +1995,7 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD
} }
else else
{ {
string sr = it.getProp(prop_prefix + "mbreg"); string sr( IOBase::initProp(it,"mbreg",prefix,false) );
if( sr.empty() ) if( sr.empty() )
{ {
dcrit << myname << "(initItem): Unknown 'mbreg' for " << it.getProp("name") << endl; dcrit << myname << "(initItem): Unknown 'mbreg' for " << it.getProp("name") << endl;
...@@ -2005,7 +2005,7 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD ...@@ -2005,7 +2005,7 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD
} }
r->mbfunc = ModbusRTU::fnUnknown; r->mbfunc = ModbusRTU::fnUnknown;
string f = it.getProp(prop_prefix + "mbfunc"); string f( IOBase::initProp(it,"mbfunc",prefix,false) );
if( !f.empty() ) if( !f.empty() )
{ {
r->mbfunc = (ModbusRTU::SlaveFunctionCode)UniSetTypes::uni_atoi(f.c_str()); r->mbfunc = (ModbusRTU::SlaveFunctionCode)UniSetTypes::uni_atoi(f.c_str());
...@@ -2022,17 +2022,18 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD ...@@ -2022,17 +2022,18 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
bool MBExchange::initRTUDevice( RTUDevice* d, UniXML_iterator& it ) bool MBExchange::initRTUDevice( RTUDevice* d, UniXML_iterator& it )
{ {
d->dtype = getDeviceType(it.getProp(prop_prefix + "mbtype")); string mbtype(IOBase::initProp(it,"mbtype",prefix,false));
d->dtype = getDeviceType(mbtype);
if( d->dtype == dtUnknown ) if( d->dtype == dtUnknown )
{ {
dcrit << myname << "(initRTUDevice): Unknown tcp_mbtype=" << it.getProp(prop_prefix + "mbtype") dcrit << myname << "(initRTUDevice): Unknown tcp_mbtype='" << mbtype << "'"
<< ". Use: rtu " << ". Use: rtu "
<< " for " << it.getProp("name") << endl; << " for " << it.getProp("name") << endl;
return false; return false;
} }
string addr = it.getProp(prop_prefix + "mbaddr"); string addr( IOBase::initProp(it,"mbaddr",prefix,false) );
if( addr.empty() ) if( addr.empty() )
{ {
dcrit << myname << "(initRTUDevice): Unknown mbaddr for " << it.getProp("name") << endl; dcrit << myname << "(initRTUDevice): Unknown mbaddr for " << it.getProp("name") << endl;
...@@ -2056,10 +2057,10 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2056,10 +2057,10 @@ bool MBExchange::initItem( UniXML_iterator& it )
if( !initRSProperty(p,it) ) if( !initRSProperty(p,it) )
return false; return false;
string addr(it.getProp(prop_prefix + "mbaddr")); string addr( IOBase::initProp(it,"mbaddr",prefix,false) );
if( addr.empty() ) if( addr.empty() )
{ {
dcrit << myname << "(initItem): Unknown mbaddr(" << prop_prefix << "mbaddr)='" << addr << "' for " << it.getProp("name") << endl; dcrit << myname << "(initItem): Unknown mbaddr(" << IOBase::initProp(it,"mbaddr",prefix,false) << ")='" << addr << "' for " << it.getProp("name") << endl;
return false; return false;
} }
...@@ -2073,7 +2074,7 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2073,7 +2074,7 @@ bool MBExchange::initItem( UniXML_iterator& it )
} }
ModbusRTU::ModbusData mbreg = 0; ModbusRTU::ModbusData mbreg = 0;
int fn = it.getIntProp(prop_prefix + "mbfunc"); int fn = IOBase::initIntProp(it,"mbfunc",prefix,false);
if( dev->dtype == dtRTU188 ) if( dev->dtype == dtRTU188 )
{ {
...@@ -2093,7 +2094,7 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2093,7 +2094,7 @@ bool MBExchange::initItem( UniXML_iterator& it )
mbreg = p.si.id; // conf->getSensorID(it.getProp("name")); mbreg = p.si.id; // conf->getSensorID(it.getProp("name"));
else else
{ {
string reg = it.getProp(prop_prefix + "mbreg"); string reg( IOBase::initProp(it,"mbreg",prefix,false) );
if( reg.empty() ) if( reg.empty() )
{ {
dcrit << myname << "(initItem): unknown mbreg(" << prop_prefix << ") for " << it.getProp("name") << endl; dcrit << myname << "(initItem): unknown mbreg(" << prop_prefix << ") for " << it.getProp("name") << endl;
...@@ -2173,7 +2174,7 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2173,7 +2174,7 @@ bool MBExchange::initItem( UniXML_iterator& it )
// Раз это регистр для записи, то как минимум надо сперва // Раз это регистр для записи, то как минимум надо сперва
// инициализировать значением из SM // инициализировать значением из SM
ri->sm_initOK = it.getIntProp(prop_prefix + "sm_initOK"); ri->sm_initOK = IOBase::initIntProp(it,"sm_initOK",prefix,false);
ri->mb_initOK = true; // может быть переопределён если будет указан tcp_preinit="1" (см. ниже) ri->mb_initOK = true; // может быть переопределён если будет указан tcp_preinit="1" (см. ниже)
} }
else else
...@@ -2225,7 +2226,7 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2225,7 +2226,7 @@ bool MBExchange::initItem( UniXML_iterator& it )
} }
// Фомируем список инициализации // Фомируем список инициализации
bool need_init = it.getIntProp(prop_prefix + "preinit"); bool need_init = IOBase::initIntProp(it,"preinit",prefix,false);
if( need_init && ModbusRTU::isWriteFunction(ri->mbfunc) ) if( need_init && ModbusRTU::isWriteFunction(ri->mbfunc) )
{ {
InitRegInfo ii; InitRegInfo ii;
...@@ -2233,7 +2234,7 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2233,7 +2234,7 @@ bool MBExchange::initItem( UniXML_iterator& it )
ii.dev = dev; ii.dev = dev;
ii.ri = ri; ii.ri = ri;
string s_reg(it.getProp(prop_prefix + "init_mbreg")); string s_reg(IOBase::initProp(it,"init_mbreg",prefix,false));
if( !s_reg.empty() ) if( !s_reg.empty() )
ii.mbreg = ModbusRTU::str2mbData(s_reg); ii.mbreg = ModbusRTU::str2mbData(s_reg);
else else
...@@ -2301,8 +2302,8 @@ bool MBExchange::initMTRitem( UniXML_iterator& it, RegInfo* p ) ...@@ -2301,8 +2302,8 @@ bool MBExchange::initMTRitem( UniXML_iterator& it, RegInfo* p )
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
bool MBExchange::initRTU188item( UniXML_iterator& it, RegInfo* p ) bool MBExchange::initRTU188item( UniXML_iterator& it, RegInfo* p )
{ {
string jack(it.getProp(prop_prefix + "jack")); string jack(IOBase::initProp(it,"jakc",prefix,false));
string chan(it.getProp(prop_prefix + "channel")); string chan(IOBase::initProp(it,"channel",prefix,false));
if( jack.empty() ) if( jack.empty() )
{ {
......
...@@ -129,8 +129,8 @@ class MBExchange: ...@@ -129,8 +129,8 @@ class MBExchange:
MTR::MTRType mtrType; /*!< тип регистра (согласно спецификации на MTR) */ MTR::MTRType mtrType; /*!< тип регистра (согласно спецификации на MTR) */
// optimization // optimization
int q_num; /*!< number in query */ unsigned int q_num; /*!< number in query */
int q_count; /*!< count registers for query */ unsigned int q_count; /*!< count registers for query */
RegMap::iterator rit; RegMap::iterator rit;
......
...@@ -812,7 +812,7 @@ bool MBSlave::initItem( UniXML_iterator& it ) ...@@ -812,7 +812,7 @@ bool MBSlave::initItem( UniXML_iterator& it )
if( !IOBase::initItem( static_cast<IOBase*>(&p),it,shm,prop_prefix,false,&dlog,myname) ) if( !IOBase::initItem( static_cast<IOBase*>(&p),it,shm,prop_prefix,false,&dlog,myname) )
return false; return false;
if( it.getIntProp(prop_prefix + "rawdata") ) if( IOBase::initIntProp(it,"rawdata",prefix,false) )
{ {
p.cal.minRaw = 0; p.cal.minRaw = 0;
p.cal.maxRaw = 0; p.cal.maxRaw = 0;
...@@ -829,7 +829,7 @@ bool MBSlave::initItem( UniXML_iterator& it ) ...@@ -829,7 +829,7 @@ bool MBSlave::initItem( UniXML_iterator& it )
string r = IOBase::initProp(it,"mbreg",prop_prefix,false); string r = IOBase::initProp(it,"mbreg",prop_prefix,false);
if( r.empty() ) if( r.empty() )
{ {
dcrit << myname << "(initItem): Unknown 'mbreg' for " << IOBase::initProp(it,"name",prop_prefix,false) << endl; dcrit << myname << "(initItem): Unknown 'mbreg' for " << it.getProp("name") << endl;
return false; return false;
} }
......
...@@ -124,7 +124,7 @@ namespace MTR ...@@ -124,7 +124,7 @@ namespace MTR
~T1(){} ~T1(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return 1; } static unsigned int wsize(){ return 1; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT1; } static MTRType type(){ return mtT1; }
// ------------------------------------------ // ------------------------------------------
...@@ -141,7 +141,7 @@ namespace MTR ...@@ -141,7 +141,7 @@ namespace MTR
~T2(){} ~T2(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return 1; } static unsigned int wsize(){ return 1; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT2; } static MTRType type(){ return mtT2; }
// ------------------------------------------ // ------------------------------------------
...@@ -184,7 +184,7 @@ namespace MTR ...@@ -184,7 +184,7 @@ namespace MTR
~T3(){} ~T3(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT3; } static MTRType type(){ return mtT3; }
// ------------------------------------------ // ------------------------------------------
...@@ -219,7 +219,7 @@ namespace MTR ...@@ -219,7 +219,7 @@ namespace MTR
~T4(){} ~T4(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return 1; } static unsigned int wsize(){ return 1; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT4; } static MTRType type(){ return mtT4; }
// ------------------------------------------ // ------------------------------------------
...@@ -272,7 +272,7 @@ namespace MTR ...@@ -272,7 +272,7 @@ namespace MTR
~T5(){} ~T5(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT5; } static MTRType type(){ return mtT5; }
// ------------------------------------------ // ------------------------------------------
...@@ -325,7 +325,7 @@ namespace MTR ...@@ -325,7 +325,7 @@ namespace MTR
~T6(){} ~T6(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT6; } static MTRType type(){ return mtT6; }
// ------------------------------------------ // ------------------------------------------
...@@ -378,7 +378,7 @@ namespace MTR ...@@ -378,7 +378,7 @@ namespace MTR
~T7(){} ~T7(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT7; } static MTRType type(){ return mtT7; }
// ------------------------------------------ // ------------------------------------------
...@@ -430,7 +430,7 @@ namespace MTR ...@@ -430,7 +430,7 @@ namespace MTR
~T8(){} ~T8(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT8; } static MTRType type(){ return mtT8; }
// ------------------------------------------ // ------------------------------------------
...@@ -481,7 +481,7 @@ namespace MTR ...@@ -481,7 +481,7 @@ namespace MTR
~T9(){} ~T9(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT9; } static MTRType type(){ return mtT9; }
// ------------------------------------------ // ------------------------------------------
...@@ -530,7 +530,7 @@ namespace MTR ...@@ -530,7 +530,7 @@ namespace MTR
~T10(){} ~T10(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT10; } static MTRType type(){ return mtT10; }
// ------------------------------------------ // ------------------------------------------
...@@ -559,7 +559,7 @@ namespace MTR ...@@ -559,7 +559,7 @@ namespace MTR
~T16(){} ~T16(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return 1; } static unsigned int wsize(){ return 1; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT16; } static MTRType type(){ return mtT16; }
// ------------------------------------------ // ------------------------------------------
...@@ -595,7 +595,7 @@ namespace MTR ...@@ -595,7 +595,7 @@ namespace MTR
~T17(){} ~T17(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return 1; } static unsigned int wsize(){ return 1; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT17; } static MTRType type(){ return mtT17; }
// ------------------------------------------ // ------------------------------------------
...@@ -644,7 +644,7 @@ namespace MTR ...@@ -644,7 +644,7 @@ namespace MTR
~F1(){} ~F1(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return u2size; } static unsigned int wsize(){ return u2size; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtF1; } static MTRType type(){ return mtF1; }
// ------------------------------------------ // ------------------------------------------
...@@ -676,7 +676,7 @@ namespace MTR ...@@ -676,7 +676,7 @@ namespace MTR
~T_Str16(){} ~T_Str16(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return 8; } static unsigned int wsize(){ return 8; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT_Str16; } static MTRType type(){ return mtT_Str16; }
// ------------------------------------------ // ------------------------------------------
...@@ -705,7 +705,7 @@ namespace MTR ...@@ -705,7 +705,7 @@ namespace MTR
~T_Str8(){} ~T_Str8(){}
// ------------------------------------------ // ------------------------------------------
/*! размер в словах */ /*! размер в словах */
static int wsize(){ return 4; } static unsigned int wsize(){ return 4; }
/*! тип значения */ /*! тип значения */
static MTRType type(){ return mtT_Str8; } static MTRType type(){ return mtT_Str8; }
// ------------------------------------------ // ------------------------------------------
......
...@@ -408,20 +408,19 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm, const s ...@@ -408,20 +408,19 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm, const s
int def_filtersize, float def_filterT, float def_lsparam, int def_filtersize, float def_filterT, float def_lsparam,
float def_iir_coeff_prev, float def_iir_coeff_new ) float def_iir_coeff_prev, float def_iir_coeff_new )
{ {
string sname( initProp(it,"name",prefix,init_prefix_only) ); // Переопределять ID и name - нельзя..s
string sname( it.getProp("name") );
ObjectId sid = DefaultObjectId; ObjectId sid = DefaultObjectId;
if( initProp(it,"id",prefix,init_prefix_only).empty() ) if( it.getProp("id").empty() )
sid = conf->getSensorID(sname); sid = conf->getSensorID(sname);
else else
{ sid = it.getPIntProp("id",DefaultObjectId);
sid = initIntProp(it,"id",prefix,init_prefix_only,DefaultObjectId);
}
if( sid == DefaultObjectId ) if( sid == DefaultObjectId )
{ {
if( dlog && dlog->is_crit() ) if( dlog && dlog->is_crit() )
dlog->crit() << myname << "(readItem): (-1) Не удалось получить ID для датчика: " dlog->crit() << myname << "(readItem): (" << DefaultObjectId << ") Не удалось получить ID для датчика: "
<< sname << endl; << sname << endl;
return false; return false;
} }
......
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