Index: /trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- /trunk/FACT++/src/InterpreterV8.cc	(revision 15042)
+++ /trunk/FACT++/src/InterpreterV8.cc	(revision 15043)
@@ -442,5 +442,5 @@
 
     if (args.Length()==1 && !args[0]->IsString())
-        return ThrowException(String::New("Argument must be an string."));
+        return ThrowException(String::New("Argument must be a string."));
 
     const string server = args.Length()==1 ? *String::AsciiValue(args[0]) : "DIM_CONTROL";
@@ -465,4 +465,109 @@
 
     return handle_scope.Close(list);
+}
+
+Handle<Value> InterpreterV8::FuncGetService(const Arguments& args)
+{
+    if (args.Length()!=1)
+        return ThrowException(String::New("getService must take exactly one argument."));
+
+    if (args.Length()==1 && !args[0]->IsString())
+        return ThrowException(String::New("Argument must be a string."));
+
+    const string service = *String::AsciiValue(args[0]);
+
+    const vector<Description> descriptions = JsGetDescription(service);
+    const set<Service> services = JsGetServices();
+
+    auto is=services.begin();
+    for (; is!=services.end(); is++)
+        if (is->name==service)
+            break;
+
+    HandleScope handle_scope;
+
+    Handle<Array> arr = Array::New();
+    if (arr.IsEmpty())
+        return Undefined();
+
+    auto it=descriptions.begin();
+    arr->Set(String::New("name"), String::New(it->name.c_str()), ReadOnly);
+    if (!it->comment.empty())
+        arr->Set(String::New("description"), String::New(it->comment.c_str()), ReadOnly);
+    if (is!=services.end())
+    {
+        arr->Set(String::New("server"), String::New(is->server.c_str()), ReadOnly);
+        arr->Set(String::New("service"), String::New(is->service.c_str()), ReadOnly);
+        arr->Set(String::New("command"), Boolean::New(is->iscmd), ReadOnly);
+        if (!is->format.empty())
+            arr->Set(String::New("format"), String::New(is->format.c_str()), ReadOnly);
+    }
+
+    uint32_t i=0;
+    for (it++; it!=descriptions.end(); it++)
+    {
+        Handle<Object> obj = Object::New();
+        if (obj.IsEmpty())
+            return Undefined();
+
+        obj->Set(String::New("name"), String::New(it->name.c_str()), ReadOnly);
+        if (!it->comment.empty())
+            obj->Set(String::New("description"), String::New(it->comment.c_str()), ReadOnly);
+        if (!it->unit.empty())
+            obj->Set(String::New("unit"), String::New(it->unit.c_str()), ReadOnly);
+
+        arr->Set(i++, obj);
+    }
+
+    return handle_scope.Close(arr);
+}
+
+Handle<Value> InterpreterV8::FuncGetServices(const Arguments& args)
+{
+    if (args.Length()>2)
+        return ThrowException(String::New("getServices must not take more than two argument."));
+
+    if (args.Length()>=1 && !args[0]->IsString())
+        return ThrowException(String::New("First argument must be a string."));
+
+    if (args.Length()==2 && !args[1]->IsBoolean())
+        return ThrowException(String::New("Second argument must be a boolean."));
+
+    string arg0 = args.Length() ? *String::AsciiValue(args[0]) : "";
+    if (arg0=="*")
+        arg0=="";
+
+    const set<Service> services = JsGetServices();
+
+    HandleScope handle_scope;
+
+    Handle<Array> arr = Array::New();
+    if (arr.IsEmpty())
+        return Undefined();
+
+    uint32_t i=0;
+    for (auto is=services.begin(); is!=services.end(); is++)
+    {
+        if (!arg0.empty() && is->name.find(arg0)!=0)
+            continue;
+
+        if (args.Length()==2 && args[1]->BooleanValue()!=is->iscmd)
+            continue;
+
+        Handle<Object> obj = Object::New();
+        if (obj.IsEmpty())
+            return Undefined();
+
+        obj->Set(String::New("name"), String::New(is->name.c_str()), ReadOnly);
+        obj->Set(String::New("server"), String::New(is->server.c_str()), ReadOnly);
+        obj->Set(String::New("service"), String::New(is->service.c_str()), ReadOnly);
+        obj->Set(String::New("command"), Boolean::New(is->iscmd), ReadOnly);
+        if (!is->format.empty())
+            obj->Set(String::New("format"), String::New(is->format.c_str()), ReadOnly);
+
+        arr->Set(i++, obj);
+    }
+
+    return handle_scope.Close(arr);
 }
 
@@ -2030,4 +2135,6 @@
     dim->Set(String::New("version"),   Integer::New(DIM_VERSION_NUMBER),     ReadOnly);
     dim->Set(String::New("getStates"), FunctionTemplate::New(WrapGetStates), ReadOnly);
+    dim->Set(String::New("getService"), FunctionTemplate::New(WrapGetService), ReadOnly);
+    dim->Set(String::New("getServices"), FunctionTemplate::New(WrapGetServices), ReadOnly);
 
     Handle<ObjectTemplate> dimctrl = ObjectTemplate::New();
Index: /trunk/FACT++/src/InterpreterV8.h
===================================================================
--- /trunk/FACT++/src/InterpreterV8.h	(revision 15042)
+++ /trunk/FACT++/src/InterpreterV8.h	(revision 15043)
@@ -13,4 +13,5 @@
 
 #include "State.h"
+#include "Service.h"
 #include "Description.h"
 #include "EventImp.h"
@@ -78,4 +79,6 @@
     v8::Handle<v8::Value> FuncGetState(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncGetStates(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncGetService(const v8::Arguments& args);
+    v8::Handle<v8::Value> FuncGetServices(const v8::Arguments& args);
     v8::Handle<v8::Value> FuncNewState(const v8::Arguments& args);
     //v8::Handle<v8::Value> FuncOpen(const v8::Arguments& args);
@@ -129,4 +132,6 @@
     static v8::Handle<v8::Value> WrapGetState(const v8::Arguments &args) { if (This) return This->FuncGetState(args); else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapGetStates(const v8::Arguments &args){ if (This) return This->FuncGetStates(args);else return v8::Undefined(); }
+    static v8::Handle<v8::Value> WrapGetService(const v8::Arguments &args){ if (This) return This->FuncGetService(args);else return v8::Undefined(); }
+    static v8::Handle<v8::Value> WrapGetServices(const v8::Arguments &args){ if (This) return This->FuncGetServices(args);else return v8::Undefined(); }
     //static v8::Handle<v8::Value> WrapOpen(const v8::Arguments &args)     { if (This) return This->FuncOpen(args);     else return v8::Undefined(); }
     static v8::Handle<v8::Value> WrapSubscription(const v8::Arguments &args){ if (This) return This->FuncSubscription(args);else return v8::Undefined(); }
@@ -185,4 +190,6 @@
     virtual State JsGetCurrentState() const { return State(); }
     virtual std::vector<State> JsGetStates(const std::string &) { return std::vector<State>(); }
+    virtual std::set<Service> JsGetServices() { return std::set<Service>(); }
+    virtual std::vector<Description> JsGetDescription(const std::string &) { return std::vector<Description>(); }
 
     virtual std::vector<Description> JsDescription(const std::string &) { return std::vector<Description>(); };
