Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
new-socketemulator
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李远洪
new-socketemulator
Commits
adbf5cc3
Commit
adbf5cc3
authored
Apr 30, 2020
by
liyuanhong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
M500 模拟器更新了单向跑完,点击熄火失败的bug
parent
c9fa1e49
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
276 additions
and
46 deletions
+276
-46
lib/socket/service/MessageSimulaterService.py
lib/socket/service/MessageSimulaterService.py
+1
-0
lib/socket/service/ProtocolSimulaterDataService.py
lib/socket/service/ProtocolSimulaterDataService.py
+55
-4
lib/socket/service/ProtocolSimulaterService.py
lib/socket/service/ProtocolSimulaterService.py
+24
-1
templates/protocolTools/report/M_carSimulater_page.html
templates/protocolTools/report/M_carSimulater_page.html
+58
-38
templates/protocolTools/report/event_protocol_page.html
templates/protocolTools/report/event_protocol_page.html
+1
-0
views/protocolTools/M_carSimulater_process.py
views/protocolTools/M_carSimulater_process.py
+137
-3
No files found.
lib/socket/service/MessageSimulaterService.py
View file @
adbf5cc3
...
...
@@ -281,6 +281,7 @@ class MessageSimulaterService():
self
.
gpsLineIndex
=
self
.
gpsLineIndex
-
1
# 反向行驶
elif
self
.
gpsLineIndex
==
len
(
self
.
gpsLine
)
or
self
.
gpsLineIndex
==
-
1
:
#如果反向行驶和反向行驶刚好跑完
if
int
(
self
.
data
[
"travelData"
][
"travelLoop"
])
==
0
:
#没有设置循环行驶
self
.
gpsLineIndex
=
self
.
gpsLineIndex
-
1
self
.
stopTravel
()
self
.
websocket
.
sendMsgToClient
(
"gps轨迹跑完,自动停止行驶!"
,
self
.
websocketId
)
else
:
#设置了循环行驶
...
...
lib/socket/service/ProtocolSimulaterDataService.py
View file @
adbf5cc3
...
...
@@ -19,7 +19,7 @@ class ProtocolSimulaterDataService():
def
setFileName
(
self
,
data
):
self
.
fileName
=
data
def
setData
(
self
,
data
):
self
.
data
=
data
self
.
data
=
self
.
fixDataTemplate
(
data
)
####################################################
# 生成一个默认数据模板
...
...
@@ -40,12 +40,31 @@ class ProtocolSimulaterDataService():
data
[
"curDayTravel"
][
"theOil"
]
=
0
#本次行驶总油耗
data
[
"curDayTravel"
][
"theTime"
]
=
0
#本次行驶总时间
data
[
"travelData"
]
=
{}
#定义所有行驶数据
data
[
"travelData"
][
"totalMilleage"
]
=
0
#行驶总里程
data
[
"travelData"
][
"totalMilleage"
]
=
0
#行驶总里程
data
[
"travelData"
][
"totalOil"
]
=
0
#行驶总油耗
data
[
"travelData"
][
"totalTime"
]
=
0
#行驶总时间
data
[
"event"
]
=
{}
data
[
"event"
][
"threeRapid"
]
=
{}
#急加速,急减速,急转弯基本数据
data
[
"event"
][
"threeRapid"
][
"totalRapidlyAccelerate"
]
=
0
#急加速总次数
data
[
"event"
][
"threeRapid"
][
"totalSharpSlowdown"
]
=
0
#急减速总次数
data
[
"event"
][
"threeRapid"
][
"totalSharpTurn"
]
=
0
#急转弯总次数
return
data
####################################################
# 修复默认数据模板
# 用于在升级模拟器的时候,对增加的字段进行初始化
####################################################
def
fixDataTemplate
(
self
,
data
):
if
not
"event"
in
data
:
data
[
"event"
]
=
{}
data
[
"event"
][
"threeRapid"
]
=
{}
data
[
"event"
][
"threeRapid"
][
"totalRapidlyAccelerate"
]
=
0
# 急加速总次数
data
[
"event"
][
"threeRapid"
][
"totalSharpSlowdown"
]
=
0
# 急减速总次数
data
[
"event"
][
"threeRapid"
][
"totalSharpTurn"
]
=
0
# 急转弯总次数
if
not
"threeRapid"
in
data
[
"event"
]:
data
[
"event"
][
"threeRapid"
]
=
{}
data
[
"event"
][
"threeRapid"
][
"totalRapidlyAccelerate"
]
=
0
#急加速总次数
data
[
"event"
][
"threeRapid"
][
"totalSharpSlowdown"
]
=
0
#急减速总次数
data
[
"event"
][
"threeRapid"
][
"totalSharpTurn"
]
=
0
#急转弯总次数
return
data
#设今日行驶总里程,同时写入文件
...
...
@@ -87,6 +106,31 @@ class ProtocolSimulaterDataService():
self
.
data
[
"travelData"
][
"totalTime"
]
=
data
self
.
writeToFile
(
self
.
path
+
self
.
fileName
,
self
.
data
)
#设置急加速总次数,同时写入文件
def
setTotalRapidlyAccelerateCount
(
self
,
data
):
if
not
"event"
in
data
:
data
[
"event"
]
=
{}
if
not
"threeRapid"
in
data
[
"event"
]:
data
[
"event"
][
"threeRapid"
]
=
{}
data
[
"event"
][
"threeRapid"
][
"totalRapidlyAccelerate"
]
=
data
self
.
writeToFile
(
self
.
path
+
self
.
fileName
,
self
.
data
)
# 设置急减速总次数,同时写入文件
def
setTotalSharpSlowdown
(
self
,
data
):
if
not
"event"
in
data
:
data
[
"event"
]
=
{}
if
not
"threeRapid"
in
data
[
"event"
]:
data
[
"event"
][
"threeRapid"
]
=
{}
data
[
"event"
][
"threeRapid"
][
"totalSharpSlowdown"
]
=
data
self
.
writeToFile
(
self
.
path
+
self
.
fileName
,
self
.
data
)
# 设置急转弯总次数,同时写入文件
def
setTotalSharpTurn
(
self
,
data
):
if
not
"event"
in
data
:
data
[
"event"
]
=
{}
if
not
"threeRapid"
in
data
[
"event"
]:
data
[
"event"
][
"threeRapid"
]
=
{}
data
[
"event"
][
"threeRapid"
][
"totalSharpTurn"
]
=
data
self
.
writeToFile
(
self
.
path
+
self
.
fileName
,
self
.
data
)
#设今日日期时间
def
setDateTime2file
(
self
,
data
):
self
.
data
[
"time"
][
"dateTime"
]
=
data
...
...
@@ -100,6 +144,12 @@ class ProtocolSimulaterDataService():
self
.
data
[
"time"
][
"time"
]
=
data
self
.
writeToFile
(
self
.
path
+
self
.
fileName
,
self
.
data
)
####################################################
# 将数据持久化到已经设定好的文件
####################################################
def
setData2file
(
self
):
self
.
writeToFile
(
self
.
path
+
self
.
fileName
,
self
.
data
)
####################################################
# 将数据写入文件
...
...
@@ -136,6 +186,7 @@ class ProtocolSimulaterDataService():
self
.
setDateTime2file
(
dateTimeM
)
self
.
setData2file
(
dateM
)
self
.
setTime2file
(
timeM
)
conJson
=
self
.
fixDataTemplate
(
conJson
)
#每次读取,都会对数据进行修复
self
.
data
=
conJson
...
...
lib/socket/service/ProtocolSimulaterService.py
View file @
adbf5cc3
...
...
@@ -60,6 +60,10 @@ class ProtocolSimulaterService():
self
.
websocketId
=
self
.
websocket
.
getCurrentClientId
()
def
setWebsocket
(
self
,
data
):
self
.
websocket
=
data
def
setSn
(
self
,
data
):
self
.
sn
=
data
def
setCarData
(
self
,
data
):
self
.
carData
=
data
def
getWebsocket
(
self
):
...
...
@@ -70,6 +74,10 @@ class ProtocolSimulaterService():
return
self
.
gpsLine
def
getTravelStatus
(
self
):
return
self
.
travelStatus
def
getSn
(
self
):
return
self
.
sn
def
getCarData
(
self
):
return
self
.
carData
def
sendMsg
(
self
,
msg
):
...
...
@@ -106,6 +114,7 @@ class ProtocolSimulaterService():
self
.
OBDdata
[
"totalRunTime"
]
=
self
.
OBDdata
[
"totalRunTime"
]
+
self
.
sendDur
latitude
=
self
.
gpsLine
[
self
.
gpsLineIndex
][
"lat"
]
longitude
=
self
.
gpsLine
[
self
.
gpsLineIndex
][
"lng"
]
# print("经度:" + str(longitude) + " 维度:" + str(latitude))
gpsMsg
=
self
.
genGPSMsg
(
latitude
,
longitude
)
if
self
.
travelDirection
==
0
:
self
.
gpsLineIndex
=
self
.
gpsLineIndex
+
1
#正向行驶
...
...
@@ -113,6 +122,7 @@ class ProtocolSimulaterService():
self
.
gpsLineIndex
=
self
.
gpsLineIndex
-
1
#反向行驶
elif
self
.
gpsLineIndex
==
len
(
self
.
gpsLine
)
or
self
.
gpsLineIndex
==
-
1
:
#如果反向行驶和反向行驶刚好跑完
if
int
(
self
.
data
[
"travelData"
][
"travelLoop"
])
==
0
:
#没有设置循环行驶
self
.
gpsLineIndex
=
self
.
gpsLineIndex
-
1
self
.
stopTravel
()
self
.
websocket
.
sendMsgToClient
(
"gps轨迹跑完,自动停止行驶!"
,
self
.
websocketId
)
else
:
#设置了循环行驶
...
...
@@ -316,7 +326,7 @@ class ProtocolSimulaterService():
self
.
OBDdataOri
[
"totalOilExpen"
]
=
conJson
[
"travelData"
][
"totalOil"
]
self
.
OBDdata
[
"totalRunTime"
]
=
conJson
[
"travelData"
][
"totalTime"
]
self
.
OBDdataOri
[
"totalRunTime"
]
=
conJson
[
"travelData"
][
"totalTime"
]
self
.
carData
=
conJson
self
.
carData
=
self
.
carDataObj
.
fixDataTemplate
(
conJson
)
fireOnEventObj
=
EventReport_protocol
(
DEV_ID
=
self
.
carId
,
WATER_CODE
=
self
.
sn
)
gpsData
=
self
.
genGPSData
(
self
.
gpsLine
[
0
][
"lat"
],
self
.
gpsLine
[
0
][
"lng"
])
fireOnEventObj
.
setGPSPkg
(
gpsData
)
...
...
@@ -387,6 +397,19 @@ class ProtocolSimulaterService():
gpsObj
.
setGPSTimestamp
(
timeS
)
data
=
gpsObj
.
generateGpsData
()
return
data
#根据当前所在GPS点,生成GPS消息体,不包含消息头
def
genGPSData2
(
self
):
gpsObj
=
GPSReport_protocol
(
DEV_ID
=
self
.
carId
,
WATER_CODE
=
self
.
sn
)
gpsObj
.
setLatitude
(
self
.
gpsLine
[
self
.
gpsLineIndex
][
"lat"
])
gpsObj
.
setLongitude
(
self
.
gpsLine
[
self
.
gpsLineIndex
][
"lng"
])
gpsObj
.
setDirectionAngle
(
self
.
getDirAngle
())
timeS
=
int
(
time
.
time
())
-
8
*
3600
timeArray
=
time
.
localtime
(
timeS
)
UTCTime
=
time
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
,
timeArray
)
gpsObj
.
setUTCTime
(
UTCTime
)
gpsObj
.
setGPSTimestamp
(
timeS
)
data
=
gpsObj
.
generateGpsData
()
return
data
# 根据特定参数,生成OBD CAN消息
def
genOBDMsg
(
self
,
fireStatus
=
1
,
ACCStatus
=
0
,
engineSpeed
=
300
,
speed
=
0
,
meterMileage
=
6000
,
\
...
...
templates/protocolTools/report/M_carSimulater_page.html
View file @
adbf5cc3
...
...
@@ -115,43 +115,44 @@
<span
style=
"margin-left:20px;"
><label>
当前状态:
</label><input
id=
"curStatus"
value=
"断网"
disabled=
"disabled"
class=
"form-control"
style=
"font-weight: bold;width:85px;color:red;border-width: 1px; border-style: solid; border-color: darkgray; border-radius: 10px;"
></span>
<span
style=
"width:80px;padding-left:10px;"
><label
style=
"width:70px"
><input
type=
"checkbox"
id=
"ignition"
onclick=
"isLogShow(this)"
/>
隐藏日志
</label>
</span>
</div>
<!-- <div style="display: block; width: 100%; border-width: 1px; border-style: solid; border-color: darkgray; border-radius: 10px; padding: 2px; margin-top: 5px;">-->
<!-- <h5><b>事件发送:</b>-->
<!-- <span style="border-width:1px;border-style:solid;border-color:darkgray;border-radius:10px;padding:1px 10px;">-->
<!-- <label><input name="eventshow" type="radio" value="0" checked="checked" onclick="isShowEventArea(this)"/>隐藏</label>-->
<!-- <label style="margin-left:10px;"><input name="eventshow" type="radio" value="1" onclick="isShowEventArea(this)"/>显示</label>-->
<!-- </span>-->
<!-- </h5>-->
<!-- <div id="event_area" style="display:none;">-->
<!-- <div style="margin-top:10px;width:100%;border-width:1px;border-style:solid;border-color:darkgray;border-radius:10px;padding:2px;background:skyblue;">-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="rapidlyAccelerateEvent_check" onclick="eventSelect(this)"/>急加速 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="bbb" onclick="eventSelect(this)"/>急减速 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="ccc" onclick="eventSelect(this)"/>急转弯 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="0003" onclick="eventSelect(this)"/>汽车电瓶低电压报警 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="0004" onclick="eventSelect(this)"/>终端主电断电报警 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="0012" onclick="eventSelect(this)"/>设防 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="0013" onclick="eventSelect(this)"/>撤防 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="0036" onclick="eventSelect(this)"/>低档高速报警 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="0037" onclick="eventSelect(this)"/>高档低速报警 </label>-->
<!-- <label style="padding: 0px 10px;"><input type="checkbox" id="004A" onclick="eventSelect(this)"/>剩余油量异常告警 </label>-->
<!-- </div>-->
<!-- <div style="padding:10px;">-->
<!-- <span id="rapidlyAccelerateEvent_button" style="display:none;"><button id="a" type="button" class="btn btn-primary" onclick="sendRapidlyAccelerateEvent(this)">急加速</button></label></span>-->
<!-- <span><label>在线人数:</label><input disabled=disabled type="text" id="b" class="form-control" style="display:inline;width:80px;" value="1"/></span>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div style="display: block; width: 100%; border-width: 1px; border-style: solid; border-color: darkgray; border-radius: 10px; padding: 2px; margin-top: 5px;">-->
<!-- <h5><b>实时控制:</b>-->
<!-- <span style="border-width:1px;border-style:solid;border-color:darkgray;border-radius:10px;padding:1px 10px;">-->
<!-- <label><input name="realtime" type="radio" value="0" checked="checked" onclick="isShowRealTimeCtrArea(this)"/>隐藏</label>-->
<!-- <label style="margin-left:10px;"><input name="realtime" type="radio" value="1" onclick="isShowRealTimeCtrArea(this)"/>显示</label>-->
<!-- </span>-->
<!-- </h5>-->
<!-- <div id="realTimeCtl_area" style="display:none;">-->
<!-- 实时控制-->
<!-- </div>-->
<!-- </div>-->
<div
style=
"display: block; width: 100%; border-width: 1px; border-style: solid; border-color: darkgray; border-radius: 10px; padding: 2px; margin-top: 5px;"
>
<h5><b>
事件发送:
</b>
<span
style=
"border-width:1px;border-style:solid;border-color:darkgray;border-radius:10px;padding:1px 10px;"
>
<label><input
name=
"eventshow"
type=
"radio"
value=
"0"
checked=
"checked"
onclick=
"isShowEventArea(this)"
/>
隐藏
</label>
<label
style=
"margin-left:10px;"
><input
name=
"eventshow"
type=
"radio"
value=
"1"
onclick=
"isShowEventArea(this)"
/>
显示
</label>
</span>
</h5>
<div
id=
"event_area"
style=
"display:none;"
>
<div
style=
"margin-top:10px;width:100%;border-width:1px;border-style:solid;border-color:darkgray;border-radius:10px;padding:2px;background:skyblue;"
>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"rapidlyAccelerateEvent_check"
onclick=
"eventSelect(this)"
/>
急加速
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"sharpSlowdownEvent_check"
onclick=
"eventSelect(this)"
/>
急减速
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"sharpTurnEvent_check"
onclick=
"eventSelect(this)"
/>
急转弯
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"0003"
onclick=
"eventSelect(this)"
/>
汽车电瓶低电压报警
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"0004"
onclick=
"eventSelect(this)"
/>
终端主电断电报警
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"0012"
onclick=
"eventSelect(this)"
/>
设防
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"0013"
onclick=
"eventSelect(this)"
/>
撤防
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"0036"
onclick=
"eventSelect(this)"
/>
低档高速报警
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"0037"
onclick=
"eventSelect(this)"
/>
高档低速报警
</label>
<label
style=
"padding: 0px 10px;"
><input
type=
"checkbox"
id=
"004A"
onclick=
"eventSelect(this)"
/>
剩余油量异常告警
</label>
</div>
<div
style=
"padding:10px;"
>
<span
id=
"rapidlyAccelerateEvent_button"
style=
"display:none;"
><button
type=
"button"
class=
"btn btn-primary"
onclick=
"sendRapidlyAccelerateEvent(this)"
>
急加速
</button></label></span>
<span
id=
"sharpSlowdownEvent_button"
style=
"display:none;"
><button
type=
"button"
class=
"btn btn-primary"
onclick=
"sendSharpSlowdownEvent(this)"
>
急减速
</button></label></span>
<span
id=
"sharpTurnEvent_button"
style=
"display:none;"
><button
type=
"button"
class=
"btn btn-primary"
onclick=
"sendSharpTurnEvent(this)"
>
急转弯
</button></label></span>
</div>
</div>
</div>
<div
style=
"display: block; width: 100%; border-width: 1px; border-style: solid; border-color: darkgray; border-radius: 10px; padding: 2px; margin-top: 5px;"
>
<h5><b>
实时控制:
</b>
<span
style=
"border-width:1px;border-style:solid;border-color:darkgray;border-radius:10px;padding:1px 10px;"
>
<label><input
name=
"realtime"
type=
"radio"
value=
"0"
checked=
"checked"
onclick=
"isShowRealTimeCtrArea(this)"
/>
隐藏
</label>
<label
style=
"margin-left:10px;"
><input
name=
"realtime"
type=
"radio"
value=
"1"
onclick=
"isShowRealTimeCtrArea(this)"
/>
显示
</label>
</span>
</h5>
<div
id=
"realTimeCtl_area"
style=
"display:none;"
>
实时控制
</div>
</div>
<div
style=
"width:100%;padding-bottom:60px;border-bottom: 1px solid #eee;"
>
<h3>
日志:
</h3>
<textarea
id=
"showFeedback"
style=
"width:100%;padding:5px;padding-bottom:60px;"
rows=
"10"
></textarea>
...
...
@@ -633,10 +634,18 @@ function eventSelect(e){
if
(
$
(
e
).
is
(
'
:checked
'
)){
if
(
$
(
e
).
attr
(
"
id
"
)
==
"
rapidlyAccelerateEvent_check
"
){
$
(
"
#rapidlyAccelerateEvent_button
"
).
css
(
"
display
"
,
"
inline
"
)
}
else
if
(
$
(
e
).
attr
(
"
id
"
)
==
"
sharpSlowdownEvent_check
"
){
$
(
"
#sharpSlowdownEvent_button
"
).
css
(
"
display
"
,
"
inline
"
)
}
else
if
(
$
(
e
).
attr
(
"
id
"
)
==
"
sharpTurnEvent_check
"
){
$
(
"
#sharpTurnEvent_button
"
).
css
(
"
display
"
,
"
inline
"
)
}
}
else
{
if
(
$
(
e
).
attr
(
"
id
"
)
==
"
rapidlyAccelerateEvent_check
"
){
$
(
"
#rapidlyAccelerateEvent_button
"
).
css
(
"
display
"
,
"
none
"
)
}
else
if
(
$
(
e
).
attr
(
"
id
"
)
==
"
sharpSlowdownEvent_check
"
){
$
(
"
#sharpSlowdownEvent_button
"
).
css
(
"
display
"
,
"
none
"
)
}
else
if
(
$
(
e
).
attr
(
"
id
"
)
==
"
sharpTurnEvent_check
"
){
$
(
"
#sharpTurnEvent_button
"
).
css
(
"
display
"
,
"
none
"
)
}
}
}
...
...
@@ -646,7 +655,18 @@ function sendRapidlyAccelerateEvent(){
url
=
"
/protocolTools/M_carSimulater_process/sendRapidlyAccelerateEvent
"
;
sendjson
(
data
,
url
);
}
//发送急减速事件消息
function
sendSharpSlowdownEvent
(){
var
data
=
getPageData
()
url
=
"
/protocolTools/M_carSimulater_process/sendSharpSlowdownEvent
"
;
sendjson
(
data
,
url
);
}
//发送急转弯事件消息
function
sendSharpTurnEvent
(){
var
data
=
getPageData
()
url
=
"
/protocolTools/M_carSimulater_process/sendSharpTurnEvent
"
;
sendjson
(
data
,
url
);
}
</script>
{% endblock %}
...
...
templates/protocolTools/report/event_protocol_page.html
View file @
adbf5cc3
...
...
@@ -399,6 +399,7 @@
//发送电瓶采样数据包
$
(
"
#sendMsgBtn
"
).
click
(
function
(){
var
data
=
getData
();
//console.log(JSON.stringify(data))
var
host
=
window
.
location
.
host
;
$
(
"
#showFeedback
"
).
val
(
""
);
$
.
ajax
({
...
...
views/protocolTools/M_carSimulater_process.py
View file @
adbf5cc3
This diff is collapsed.
Click to expand it.
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