diff --git a/README.md b/README.md
index b53620b6956fcda4fdb6e960c4311be0d87b68fe..71dcaddd9e5e441a383fff6897fd84c004f3ec4d 100644
--- a/README.md
+++ b/README.md
@@ -227,6 +227,17 @@ const clear = usp.on(/NOTIFY.*/, (data, msg) => console.log({ data, msg }));
 
   Options allows extending commands with additional functionality.
 
+  Props:
+  timeout -> timeout after given ms (throws error)
+  preCall -> called before each command, provides command name and arguments
+  postCall -> called after each command, provides command name, arguments and result/error
+
 ```javascript
-await usp.options({ timeout: 1000 }).get("Device.DeviceInfo.SerialNumber");
+await usp
+  .options({
+    timeout: 1000,
+    preCall: (name, args) => console.log(name, args),
+    postCall: (name, args, result) => console.log(name, args, result),
+  })
+  .get("Device.DeviceInfo.SerialNumber");
 ```
diff --git a/src/index.ts b/src/index.ts
index 61216465f43b20a07f70cc5b11f3cb34a2e51fe2..952ad6e6f23bb1816406e888c2e482f3d4e2dc4f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -9,6 +9,7 @@ import {
   Options,
   USP,
   Command,
+  PostCallCallback,
 } from "./types";
 import { makeCallbackRouter, makeRouter } from "./util";
 
@@ -41,8 +42,8 @@ const wait = (ms: number) =>
     }, ms);
   });
 
-const timeoutWrapper = (promise: Promise<any>, ms: number) =>
-  Promise.race([promise, wait(ms)]);
+const timeoutWrapper = (promise: () => Promise<any>, ms?: number) =>
+  ms && ms > 0 ? Promise.race([promise(), wait(ms)]) : promise();
 
 const wrap = <T extends (...args: any[]) => any>(
   opts: Options,
@@ -50,12 +51,20 @@ const wrap = <T extends (...args: any[]) => any>(
   cmd: T
 ): T => {
   return <T>((...args: any[]) => {
-    if (opts.logMessage) opts.logMessage(cmdName, args);
-    if (opts.timeout && opts.timeout > 0) {
-      return timeoutWrapper(cmd(...args), opts.timeout);
-    }
-
-    return cmd(...args);
+    // Promise.resolve added to handle non-promise commands
+    const cmdCall = () => Promise.resolve(cmd(...args));
+    const finalCall = () =>
+      timeoutWrapper(cmdCall, opts.timeout)
+        .then((res) => {
+          opts.postCall && opts.postCall(cmdName, args, res);
+          return res;
+        })
+        .catch((err) => {
+          opts.postCall && opts.postCall(cmdName, args, err);
+          throw err;
+        });
+    if (opts.preCall) opts.preCall(cmdName, args);
+    return finalCall();
   });
 };
 
@@ -67,7 +76,7 @@ const addOptions = (usp: Partial<USP>, opts: Options): USP => {
     }),
     {} as any
   ) as USP;
-  mainUSP.options = wrap(opts, "options", (opts) => addOptions(mainUSP, opts));
+  mainUSP.options = (opts) => addOptions(mainUSP, opts);
   return mainUSP;
 };
 
diff --git a/src/types.ts b/src/types.ts
index e73e478bad25b1a23349457e7cc370c427cdd2d4..0ab49c9a52fc42ea628bf01207ce94aa6ba251c4 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -174,14 +174,17 @@ export type ResolveRecipe = (
   level?: number
 ) => Promise<GetReturn>;
 
-export type LogMessageCallback = (name: string, args: any[]) => void;
+export type PreCallCallback = (name: string, args: any[]) => void;
+export type PostCallCallback = (name: string, args: any[], result: any) => void;
 
 /** Options that allow extending command funcitonality */
 export type Options = {
   /** Timeout command after given number of milliseconds (throws an error for handling with catch) */
   timeout?: number;
-  /** Log outgoing calls to the console */
-  logMessage?: LogMessageCallback;
+  /** Call function before command */
+  preCall?: PreCallCallback;
+  /** Call after before command */
+  postCall?: PostCallCallback;
 };
 
 /** Device API */
diff --git a/tests/integration/config.json b/tests/integration/config.json
index 8f98c81a8b7c0536e0dc7517e38ad7960d11b11f..8926a5dcf23263efde87e75c1d939451b8987d94 100644
--- a/tests/integration/config.json
+++ b/tests/integration/config.json
@@ -10,12 +10,5 @@
     "url": "ws://192.168.1.1:9001",
     "username": "admin",
     "password": "admin"
-  },
-  "bulut": {
-    "url": "wss://bulut.iopsys.eu:443",
-    "fromId": "proto::usp-cloud-controller",
-    "toId": "os::002207-+105318+2031000004",
-    "username": "admin",
-    "password": "admin"
   }
 }
diff --git a/tests/integration/index.test.ts b/tests/integration/index.test.ts
index 07f111c0f5b1cd346d927a825e0bf6e41872521c..f5fa962fff57d023ff7de96ab8cf05ce948aeddd 100644
--- a/tests/integration/index.test.ts
+++ b/tests/integration/index.test.ts
@@ -7,7 +7,7 @@ describe("Test general API", () => {
   let device: any = null;
 
   before(async () => {
-    device = await connect(config.bulut as ConnectionOptions);
+    device = await connect(config.ws as ConnectionOptions);
   });
 
   // GET
@@ -189,7 +189,7 @@ describe("Test general API", () => {
   it("get with double options setup returns without error", async () => {
     await device
       .options({ timeout: -1 })
-      .options({ logMessage: () => null })
+      .options({ preCall: () => null })
       .get("Device.DeviceInfo.SerialNumber")
       .then((msg) => assert.strictEqual(typeof msg, "string"))
       .catch((err) => {
@@ -197,6 +197,15 @@ describe("Test general API", () => {
       });
   });
 
+  it("get with pre and post call executes without error", async () => {
+    await device
+      .options({
+        preCall: (name) => assert.strictEqual(name, "get"),
+        postCall: (name) => assert.strictEqual(name, "get"),
+      })
+      .get("Device.DeviceInfo.SerialNumber");
+  });
+
   after(async () => {
     await device.disconnect();
   });