Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Q
qjs-wrapper
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
qjs-wrapper
Commits
598b5b79
Commit
598b5b79
authored
Sep 08, 2022
by
Léo-Paul Géneau
👾
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sort qjs_wrapper functions
parent
66755185
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
105 additions
and
94 deletions
+105
-94
mavsdk_wrapper.cpp
mavsdk_wrapper.cpp
+0
-1
qjs_wrapper.c
qjs_wrapper.c
+105
-93
No files found.
mavsdk_wrapper.cpp
View file @
598b5b79
...
@@ -314,7 +314,6 @@ static int startAltitudeControl(void) {
...
@@ -314,7 +314,6 @@ static int startAltitudeControl(void) {
static
double
bearing
(
double
lat1
,
double
lon1
,
double
lat2
,
double
lon2
)
{
static
double
bearing
(
double
lat1
,
double
lon1
,
double
lat2
,
double
lon2
)
{
double
lat1_rad
=
toRad
(
lat1
);
double
lat1_rad
=
toRad
(
lat1
);
double
lat2_rad
=
toRad
(
lat2
);
double
lat2_rad
=
toRad
(
lat2
);
double
dL
=
toRad
(
lon2
-
lon1
);
double
dL
=
toRad
(
lon2
-
lon1
);
double
x
=
cos
(
lat2_rad
)
*
sin
(
dL
);
double
x
=
cos
(
lat2_rad
)
*
sin
(
dL
);
double
y
=
cos
(
lat1_rad
)
*
sin
(
lat2_rad
)
-
sin
(
lat1_rad
)
*
cos
(
lat2_rad
)
*
cos
(
dL
);
double
y
=
cos
(
lat1_rad
)
*
sin
(
lat2_rad
)
-
sin
(
lat1_rad
)
*
cos
(
lat2_rad
)
*
cos
(
dL
);
...
...
qjs_wrapper.c
View file @
598b5b79
...
@@ -16,6 +16,8 @@ UA_String currentMessage;
...
@@ -16,6 +16,8 @@ UA_String currentMessage;
pthread_mutex_t
mutex
;
pthread_mutex_t
mutex
;
pthread_cond_t
threadCond
;
pthread_cond_t
threadCond
;
// Drone class functions
static
void
js_drone_finalizer
(
JSRuntime
*
rt
,
JSValue
val
)
static
void
js_drone_finalizer
(
JSRuntime
*
rt
,
JSValue
val
)
{
{
JSDroneData
*
s
=
(
JSDroneData
*
)
JS_GetOpaque
(
val
,
jsDroneClassId
);
JSDroneData
*
s
=
(
JSDroneData
*
)
JS_GetOpaque
(
val
,
jsDroneClassId
);
...
@@ -169,6 +171,8 @@ static const JSCFunctionListEntry js_drone_proto_funcs[] = {
...
@@ -169,6 +171,8 @@ static const JSCFunctionListEntry js_drone_proto_funcs[] = {
JS_CFUNC_DEF
(
"init"
,
1
,
js_drone_init
),
JS_CFUNC_DEF
(
"init"
,
1
,
js_drone_init
),
};
};
// pubsub functions
UA_UInt16
get_drone_id
(
UA_UInt32
nb
)
{
UA_UInt16
get_drone_id
(
UA_UInt32
nb
)
{
JSDroneData
*
s
=
(
JSDroneData
*
)
JS_GetOpaque
(
droneObjectIdList
[
nb
],
jsDroneClassId
);
JSDroneData
*
s
=
(
JSDroneData
*
)
JS_GetOpaque
(
droneObjectIdList
[
nb
],
jsDroneClassId
);
return
s
->
id
;
return
s
->
id
;
...
@@ -384,6 +388,8 @@ static JSValue js_stop_pubsub(JSContext *ctx, JSValueConst thisVal,
...
@@ -384,6 +388,8 @@ static JSValue js_stop_pubsub(JSContext *ctx, JSValueConst thisVal,
return
JS_NewInt32
(
ctx
,
0
);
return
JS_NewInt32
(
ctx
,
0
);
}
}
// Connexion management functions
static
JSValue
js_mavsdk_start
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
static
JSValue
js_mavsdk_start
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
...
@@ -416,28 +422,72 @@ static JSValue js_mavsdk_reboot(JSContext *ctx, JSValueConst thisVal,
...
@@ -416,28 +422,72 @@ static JSValue js_mavsdk_reboot(JSContext *ctx, JSValueConst thisVal,
return
JS_NewInt32
(
ctx
,
mavsdk_reboot
());
return
JS_NewInt32
(
ctx
,
mavsdk_reboot
());
}
}
static
JSValue
js_mavsdk_healthAllOk
(
JSContext
*
ctx
,
JSValueConst
this_val
,
// Flight state management functions
int
argc
,
JSValueConst
*
argv
)
static
JSValue
js_mavsdk_arm
(
JSContext
*
ctx
,
JSValueConst
this_val
,
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_New
Bool
(
ctx
,
mavsdk_healthAllOk
());
return
JS_New
Int32
(
ctx
,
mavsdk_arm
());
}
}
static
JSValue
js_mavsdk_land
ed
(
JSContext
*
ctx
,
JSValueConst
this_v
al
,
static
JSValue
js_mavsdk_land
(
JSContext
*
ctx
,
JSValueConst
thisV
al
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_New
Bool
(
ctx
,
mavsdk_lande
d
());
return
JS_New
Int32
(
ctx
,
mavsdk_lan
d
());
}
}
static
JSValue
js_mavsdk_isInManualMode
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
static
JSValue
js_mavsdk_takeOff
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
return
JS_NewInt32
(
ctx
,
mavsdk_takeOff
());
}
static
JSValue
js_mavsdk_takeOffAndWait
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_New
Bool
(
ctx
,
mavsdk_isInManualMode
());
return
JS_New
Int32
(
ctx
,
mavsdk_takeOffAndWait
());
}
}
static
JSValue
js_mavsdk_
arm
(
JSContext
*
ctx
,
JSValueConst
this_v
al
,
static
JSValue
js_mavsdk_
triggerParachute
(
JSContext
*
ctx
,
JSValueConst
thisV
al
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_NewInt32
(
ctx
,
mavsdk_arm
());
return
JS_NewInt32
(
ctx
,
mavsdk_triggerParachute
());
}
// Flight management functions
static
JSValue
js_mavsdk_loiter
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
double
radius
=
100
;
if
(
argc
>
0
)
{
if
(
JS_ToFloat64
(
ctx
,
&
radius
,
argv
[
0
]))
return
JS_EXCEPTION
;
}
return
JS_NewInt32
(
ctx
,
mavsdk_loiter
((
float
)
radius
));
}
static
JSValue
js_mavsdk_setAirspeed
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
double
altitude
;
if
(
JS_ToFloat64
(
ctx
,
&
altitude
,
argv
[
0
]))
return
JS_EXCEPTION
;
return
JS_NewInt32
(
ctx
,
mavsdk_setAirspeed
((
float
)
altitude
));
}
static
JSValue
js_mavsdk_setAltitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
double
altitude
;
if
(
JS_ToFloat64
(
ctx
,
&
altitude
,
argv
[
0
]))
return
JS_EXCEPTION
;
return
JS_NewInt32
(
ctx
,
mavsdk_setAltitude
((
float
)
altitude
));
}
}
static
JSValue
js_mavsdk_setTargetCoordinates
(
JSContext
*
ctx
,
static
JSValue
js_mavsdk_setTargetCoordinates
(
JSContext
*
ctx
,
...
@@ -467,32 +517,25 @@ static JSValue js_mavsdk_setManualControlInput(JSContext *ctx,
...
@@ -467,32 +517,25 @@ static JSValue js_mavsdk_setManualControlInput(JSContext *ctx,
return
JS_NewInt32
(
ctx
,
mavsdk_setManualControlInput
());
return
JS_NewInt32
(
ctx
,
mavsdk_setManualControlInput
());
}
}
static
JSValue
js_mavsdk_setAltitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
// Information functions
static
JSValue
js_mavsdk_getAltitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
double
altitude
;
return
JS_NewFloat64
(
ctx
,
mavsdk_getAltitude
());
if
(
JS_ToFloat64
(
ctx
,
&
altitude
,
argv
[
0
]))
return
JS_EXCEPTION
;
return
JS_NewInt32
(
ctx
,
mavsdk_setAltitude
((
float
)
altitude
));
}
}
static
JSValue
js_mavsdk_
setAirspeed
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
static
JSValue
js_mavsdk_
getAltitudeRel
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
double
altitude
;
return
JS_NewFloat64
(
ctx
,
mavsdk_getAltitudeRel
());
if
(
JS_ToFloat64
(
ctx
,
&
altitude
,
argv
[
0
]))
return
JS_EXCEPTION
;
return
JS_NewInt32
(
ctx
,
mavsdk_setAirspeed
((
float
)
altitude
));
}
}
static
JSValue
js_mavsdk_getYaw
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
static
JSValue
js_mavsdk_getInitialAltitude
(
JSContext
*
ctx
,
int
argc
,
JSValueConst
*
argv
)
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_NewFloat64
(
ctx
,
mavsdk_get
Yaw
());
return
JS_NewFloat64
(
ctx
,
mavsdk_get
InitialAltitude
());
}
}
static
JSValue
js_mavsdk_getInitialLatitude
(
JSContext
*
ctx
,
static
JSValue
js_mavsdk_getInitialLatitude
(
JSContext
*
ctx
,
...
@@ -502,12 +545,6 @@ static JSValue js_mavsdk_getInitialLatitude(JSContext *ctx,
...
@@ -502,12 +545,6 @@ static JSValue js_mavsdk_getInitialLatitude(JSContext *ctx,
return
JS_NewFloat64
(
ctx
,
mavsdk_getInitialLatitude
());
return
JS_NewFloat64
(
ctx
,
mavsdk_getInitialLatitude
());
}
}
static
JSValue
js_mavsdk_getLatitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
return
JS_NewFloat64
(
ctx
,
mavsdk_getLatitude
());
}
static
JSValue
js_mavsdk_getInitialLongitude
(
JSContext
*
ctx
,
static
JSValue
js_mavsdk_getInitialLongitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
...
@@ -515,6 +552,12 @@ static JSValue js_mavsdk_getInitialLongitude(JSContext *ctx,
...
@@ -515,6 +552,12 @@ static JSValue js_mavsdk_getInitialLongitude(JSContext *ctx,
return
JS_NewFloat64
(
ctx
,
mavsdk_getInitialLongitude
());
return
JS_NewFloat64
(
ctx
,
mavsdk_getInitialLongitude
());
}
}
static
JSValue
js_mavsdk_getLatitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
return
JS_NewFloat64
(
ctx
,
mavsdk_getLatitude
());
}
static
JSValue
js_mavsdk_getLongitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
static
JSValue
js_mavsdk_getLongitude
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
...
@@ -528,91 +571,60 @@ static JSValue js_mavsdk_getTakeOffAltitude(JSContext *ctx,
...
@@ -528,91 +571,60 @@ static JSValue js_mavsdk_getTakeOffAltitude(JSContext *ctx,
return
JS_NewFloat64
(
ctx
,
mavsdk_getTakeOffAltitude
());
return
JS_NewFloat64
(
ctx
,
mavsdk_getTakeOffAltitude
());
}
}
static
JSValue
js_mavsdk_getInitialAltitude
(
JSContext
*
ctx
,
static
JSValue
js_mavsdk_getYaw
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_NewFloat64
(
ctx
,
mavsdk_get
InitialAltitude
());
return
JS_NewFloat64
(
ctx
,
mavsdk_get
Yaw
());
}
}
static
JSValue
js_mavsdk_
getAltitude
(
JSContext
*
ctx
,
JSValueConst
thisV
al
,
static
JSValue
js_mavsdk_
healthAllOk
(
JSContext
*
ctx
,
JSValueConst
this_v
al
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_New
Float64
(
ctx
,
mavsdk_getAltitude
());
return
JS_New
Bool
(
ctx
,
mavsdk_healthAllOk
());
}
}
static
JSValue
js_mavsdk_
getAltitudeRel
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
static
JSValue
js_mavsdk_
isInManualMode
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
return
JS_New
Float64
(
ctx
,
mavsdk_getAltitudeRel
());
return
JS_New
Bool
(
ctx
,
mavsdk_isInManualMode
());
}
}
static
JSValue
js_mavsdk_l
oiter
(
JSContext
*
ctx
,
JSValueConst
thisV
al
,
static
JSValue
js_mavsdk_l
anded
(
JSContext
*
ctx
,
JSValueConst
this_v
al
,
int
argc
,
JSValueConst
*
argv
)
int
argc
,
JSValueConst
*
argv
)
{
{
double
radius
=
100
;
return
JS_NewBool
(
ctx
,
mavsdk_landed
());
if
(
argc
>
0
)
{
if
(
JS_ToFloat64
(
ctx
,
&
radius
,
argv
[
0
]))
return
JS_EXCEPTION
;
}
return
JS_NewInt32
(
ctx
,
mavsdk_loiter
((
float
)
radius
));
}
static
JSValue
js_mavsdk_triggerParachute
(
JSContext
*
ctx
,
JSValueConst
this_val
,
int
argc
,
JSValueConst
*
argv
)
{
return
JS_NewInt32
(
ctx
,
mavsdk_triggerParachute
());
}
static
JSValue
js_mavsdk_takeOff
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
return
JS_NewInt32
(
ctx
,
mavsdk_takeOff
());
}
static
JSValue
js_mavsdk_takeOffAndWait
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
return
JS_NewInt32
(
ctx
,
mavsdk_takeOffAndWait
());
}
static
JSValue
js_mavsdk_land
(
JSContext
*
ctx
,
JSValueConst
thisVal
,
int
argc
,
JSValueConst
*
argv
)
{
return
JS_NewInt32
(
ctx
,
mavsdk_land
());
}
}
static
const
JSCFunctionListEntry
js_mavsdk_funcs
[]
=
{
static
const
JSCFunctionListEntry
js_mavsdk_funcs
[]
=
{
JS_CFUNC_DEF
(
"setMessage"
,
1
,
js_drone_set_message
),
JS_CFUNC_DEF
(
"runPubsub"
,
6
,
js_run_pubsub
),
JS_CFUNC_DEF
(
"stopPubsub"
,
0
,
js_stop_pubsub
),
JS_CFUNC_DEF
(
"start"
,
3
,
js_mavsdk_start
),
JS_CFUNC_DEF
(
"start"
,
3
,
js_mavsdk_start
),
JS_CFUNC_DEF
(
"stop"
,
0
,
js_mavsdk_stop
),
JS_CFUNC_DEF
(
"stop"
,
0
,
js_mavsdk_stop
),
JS_CFUNC_DEF
(
"reboot"
,
0
,
js_mavsdk_reboot
),
JS_CFUNC_DEF
(
"reboot"
,
0
,
js_mavsdk_reboot
),
JS_CFUNC_DEF
(
"healthAllOk"
,
0
,
js_mavsdk_healthAllOk
),
JS_CFUNC_DEF
(
"landed"
,
0
,
js_mavsdk_landed
),
JS_CFUNC_DEF
(
"isInManualMode"
,
0
,
js_mavsdk_isInManualMode
),
JS_CFUNC_DEF
(
"arm"
,
0
,
js_mavsdk_arm
),
JS_CFUNC_DEF
(
"arm"
,
0
,
js_mavsdk_arm
),
JS_CFUNC_DEF
(
"land"
,
0
,
js_mavsdk_land
),
JS_CFUNC_DEF
(
"takeOff"
,
0
,
js_mavsdk_takeOff
),
JS_CFUNC_DEF
(
"takeOffAndWait"
,
0
,
js_mavsdk_takeOffAndWait
),
JS_CFUNC_DEF
(
"triggerParachute"
,
0
,
js_mavsdk_triggerParachute
),
JS_CFUNC_DEF
(
"loiter"
,
0
,
js_mavsdk_loiter
),
JS_CFUNC_DEF
(
"setAirspeed"
,
1
,
js_mavsdk_setAirspeed
),
JS_CFUNC_DEF
(
"setAltitude"
,
1
,
js_mavsdk_setAltitude
),
JS_CFUNC_DEF
(
"setTargetCoordinates"
,
3
,
js_mavsdk_setTargetCoordinates
),
JS_CFUNC_DEF
(
"setTargetCoordinates"
,
3
,
js_mavsdk_setTargetCoordinates
),
JS_CFUNC_DEF
(
"setManualControlInput"
,
0
,
js_mavsdk_setManualControlInput
),
JS_CFUNC_DEF
(
"setManualControlInput"
,
0
,
js_mavsdk_setManualControlInput
),
JS_CFUNC_DEF
(
"setAltitude"
,
1
,
js_mavsdk_setAltitude
),
JS_CFUNC_DEF
(
"getAltitude"
,
0
,
js_mavsdk_getAltitude
),
JS_CFUNC_DEF
(
"setAirspeed"
,
1
,
js_mavsdk_setAirspeed
),
JS_CFUNC_DEF
(
"getAltitudeRel"
,
0
,
js_mavsdk_getAltitudeRel
),
JS_CFUNC_DEF
(
"loiter"
,
0
,
js_mavsdk_loiter
),
JS_CFUNC_DEF
(
"getInitialAltitude"
,
0
,
js_mavsdk_getInitialAltitude
),
JS_CFUNC_DEF
(
"triggerParachute"
,
0
,
js_mavsdk_triggerParachute
),
JS_CFUNC_DEF
(
"getYaw"
,
0
,
js_mavsdk_getYaw
),
JS_CFUNC_DEF
(
"getInitialLatitude"
,
0
,
js_mavsdk_getInitialLatitude
),
JS_CFUNC_DEF
(
"getInitialLatitude"
,
0
,
js_mavsdk_getInitialLatitude
),
JS_CFUNC_DEF
(
"getLatitude"
,
0
,
js_mavsdk_getLatitude
),
JS_CFUNC_DEF
(
"getInitialLongitude"
,
0
,
js_mavsdk_getInitialLongitude
),
JS_CFUNC_DEF
(
"getInitialLongitude"
,
0
,
js_mavsdk_getInitialLongitude
),
JS_CFUNC_DEF
(
"getLatitude"
,
0
,
js_mavsdk_getLatitude
),
JS_CFUNC_DEF
(
"getLongitude"
,
0
,
js_mavsdk_getLongitude
),
JS_CFUNC_DEF
(
"getLongitude"
,
0
,
js_mavsdk_getLongitude
),
JS_CFUNC_DEF
(
"getTakeOffAltitude"
,
0
,
js_mavsdk_getTakeOffAltitude
),
JS_CFUNC_DEF
(
"getTakeOffAltitude"
,
0
,
js_mavsdk_getTakeOffAltitude
),
JS_CFUNC_DEF
(
"getInitialAltitude"
,
0
,
js_mavsdk_getInitialAltitude
),
JS_CFUNC_DEF
(
"getYaw"
,
0
,
js_mavsdk_getYaw
),
JS_CFUNC_DEF
(
"getAltitude"
,
0
,
js_mavsdk_getAltitude
),
JS_CFUNC_DEF
(
"isInManualMode"
,
0
,
js_mavsdk_isInManualMode
),
JS_CFUNC_DEF
(
"getAltitudeRel"
,
0
,
js_mavsdk_getAltitudeRel
),
JS_CFUNC_DEF
(
"healthAllOk"
,
0
,
js_mavsdk_healthAllOk
),
JS_CFUNC_DEF
(
"takeOff"
,
0
,
js_mavsdk_takeOff
),
JS_CFUNC_DEF
(
"landed"
,
0
,
js_mavsdk_landed
),
JS_CFUNC_DEF
(
"takeOffAndWait"
,
0
,
js_mavsdk_takeOffAndWait
),
JS_CFUNC_DEF
(
"land"
,
0
,
js_mavsdk_land
),
JS_CFUNC_DEF
(
"initPubsub"
,
1
,
js_init_pubsub
),
JS_CFUNC_DEF
(
"initPubsub"
,
1
,
js_init_pubsub
),
JS_CFUNC_DEF
(
"runPubsub"
,
6
,
js_run_pubsub
),
JS_CFUNC_DEF
(
"setMessage"
,
1
,
js_drone_set_message
),
JS_CFUNC_DEF
(
"stopPubsub"
,
0
,
js_stop_pubsub
),
};
};
static
int
js_mavsdk_init
(
JSContext
*
ctx
,
JSModuleDef
*
m
)
static
int
js_mavsdk_init
(
JSContext
*
ctx
,
JSModuleDef
*
m
)
...
...
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