diff --git a/src/driver/nbiot.be b/src/driver/nbiot.be
index 085598f1a9492339fe1ac085752dcc7e31369f37..17ba6b928d00e325a4f8b3a5a3039e716f2eac7a 100644
--- a/src/driver/nbiot.be
+++ b/src/driver/nbiot.be
@@ -1,41 +1,156 @@
 import string
 
+class NBIoTRequestType
+  static var MQTT = 1
+  static var COAP = 2
+end
+
+class NBIoTRequest
+  var type
+end
+
+class NBIoTMQTTRequest : NBIoTRequest
+  var type
+  var host
+  var port
+  var username
+  var password
+  var topic
+  var payload
+  var callback
+
+  def init(host, port, username, password, topic, payload, callback)
+    self.type = NBIoTRequestType.MQTT
+    self.host = host
+    self.port = port
+    self.username = username
+    self.password = password
+    self.topic = topic
+    self.payload = payload
+    self.callback = callback
+  end
+end
+
+class NBIoTCOAPRequest : NBIoTRequest
+  var host
+  var port
+  var path
+  var query
+  var topic
+  var payload
+  var callback
+
+  def init(host, port, path, method, query, payload, callback)
+    self.type = NBIoTRequestType.COAP
+    self.host = host
+    self.port = port
+    self.path = path
+    self.method = method
+    self.query = query
+    self.payload = payload
+    self.callback = callback
+  end
+end
+
+class NBIoTMQTTConnection
+  var host
+  var port
+  var username
+  var password
+
+  def init(host, port, username, password)
+    self.host = host
+    self.port = port
+    self.username = username
+    self.password = password
+  end
+
+  def equals(other)
+    var equal = true
+    equal = equal && self.host == other.host
+    equal = equal && self.port == other.port
+    equal = equal && self.username == other.username
+    equal = equal && self.password == other.password
+
+    return equal
+  end
+end
+
 class NBIoTDriverState
   static var RESET = 1
-  static var INIT_COAP = 2
-  static var INIT_MQTT = 3
-  static var READY = 4
-  static var COAP_SET_OPTIONS = 5
-  static var COAP_SEND = 6
-  static var COAP_RECEIVE = 7
+  static var READY = 2
+  static var COAP_OPEN = 3
+  static var COAP_SET_OPTIONS = 4
+  static var COAP_SEND = 5
+  static var COAP_RECEIVE = 6
+  static var COAP_CLOSE = 7
+  static var MQTT_OPEN = 8
+  static var MQTT_CONNECT = 9
+  static var MQTT_PUBLISH = 10
+  static var MQTT_CHECK_CONN = 11
+  static var MQTT_CLOSE = 12
 end
 
 class NBIoTDriver
   var ser
   var state
-  var send_queue
-  var send_request
-  var ok_awaiting
+  var rsp_awaiting
   var payload_awaiting
   var retries
+  var request_queue
+  var request
+  var mqtt_connection
 
   def init(rx, tx)
     self.state = NBIoTDriverState.RESET
-    self.send_queue = []
-    self.send_request = nil
-    self.ok_awaiting = false
+    self.rsp_awaiting = false
+    self.payload_awaiting = false
     self.retries = 0
+    self.request_queue = []
+    self.request = nil
+    self.mqtt_connection = nil
 
     self.ser = serial(rx, tx, 115200, serial.SERIAL_8N1)
   end
 
-  def check_ok()
-    if self.ok_awaiting
-      var msg = self.ser.read().asstring()
-      print(msg)
+  def queue_request(request)
+    self.request_queue.push(request)
+  end
+
+  def finish_request(payload)
+    if self.request.callback != nil
+      self.request.callback(payload)
+    end
+
+    self.request = nil
+  end
+
+  def build_mqtt_open_cmd()
+    var cmd = 'AT+QMTOPEN=0,\"%s\",%s\r\n'
+
+    return string.format(cmd, self.request.host, str(self.request.port))
+  end
 
-      if string.find(msg,'OK') >= 0
-        self.ok_awaiting = false
+  def build_mqtt_conn_cmd()
+    var client_id = 'nb-iot' # todo: change
+    var cmd = 'AT+QMTCONN=0,\"%s\",\"%s\",\"%s\"\r\n'
+
+    return string.format(cmd, client_id, self.request.username, self.request.password)
+  end
+
+  def build_mqtt_pub_cmd()
+    var cmd = 'AT+QMTPUB=0,0,0,0,\"%s\",\"%s\"\r\n'
+
+    return string.format(cmd, self.request.topic, self.request.payload)
+  end
+
+  def rsp_contains_msg(msg)
+    if self.rsp_awaiting
+      var rsp = self.ser.read().asstring()
+      print(rsp)
+
+      if string.find(rsp, msg) >= 0
+        self.rsp_awaiting = false
         
         return true
       else
@@ -50,54 +165,90 @@ class NBIoTDriver
     end
   end
 
-  def check_ok_or_send(cmd)
-    if self.check_ok()
+  def rsp_contains_msg_or_send(msg, cmd)
+    if self.rsp_contains_msg(msg)
       return true
     else
       print('send ' + cmd)
       self.ser.write(bytes().fromstring(cmd))
-      self.ok_awaiting = true
+      self.rsp_awaiting = true
 
       return false
     end
   end
 
-  def check_ready()
-    var msg = self.ser.read().asstring()
-    print(msg)
-
-    return string.find(msg,'RDY') >= 0
-  end
-
-  def reset()
-    self.ser.write(bytes().fromstring('AT+QRST=1\r\n'))
-    print('write AT+QRST')
-  end
-
   def every_second()
+    # ---- RESET ---- #
     if self.state == NBIoTDriverState.RESET
-      if !self.check_ready()
-        self.reset()
-      else
-        self.state = NBIoTDriverState.INIT_COAP
+      if self.rsp_contains_msg_or_send('RDY', 'AT+QRST=1\r\n')
+        self.state = NBIoTDriverState.READY
       end
-    elif self.state == NBIoTDriverState.INIT_COAP
-      if self.check_ok_or_send('AT+QCOAPCREATE=1,0\r\n')
-        self.state = NBIoTDriverState.COAP_SET_OPTIONS
+    # ---- READY ---- #
+    elif self.state == NBIoTDriverState.READY
+      if self.request_queue.size() > 0
+        self.request = self.request_queue[0]
+        self.request_queue.remove(0)
+
+        if self.request.type == NBIoTRequestType.MQTT
+          var mqtt_connection = NBIoTMQTTConnection(self.request.host, 
+                                                    self.request.port, 
+                                                    self.request.username, 
+                                                    self.request.password)
+
+          if self.mqtt_connection != nil && self.mqtt_connection.equals(mqtt_connection)
+            self.state = NBIoTDriverState.MQTT_CHECK_CONN
+          elif self.mqtt_connection != nil
+            self.mqtt_connection = mqtt_connection
+            self.state = NBIoTDriverState.MQTT_CLOSE
+          else
+            self.mqtt_connection = mqtt_connection
+            self.state = NBIoTDriverState.MQTT_OPEN
+          end
+        else
+          self.finish_request()
+        end
       end
+    # ---- COAP ---- #
     elif self.state == NBIoTDriverState.COAP_SET_OPTIONS
-      if self.check_ok_or_send('AT+QCOAPOPTION=1,11,\"test\"\r\n')
+      if self.rsp_contains_msg_or_send('OK', 'AT+QCOAPOPTION=1,11,\"test\"\r\n')
         self.state = NBIoTDriverState.COAP_SEND
       end
     elif self.state == NBIoTDriverState.COAP_SEND
-      if self.check_ok_or_send('AT+QCOAPSEND=1,0,\"37.120.174.40\",5683,0\r\n')
+      if self.rsp_contains_msg_or_send('OK', 'AT+QCOAPSEND=1,0,\"37.120.174.40\",5683,0\r\n')
         self.state = NBIoTDriverState.COAP_RECEIVE
       end
     elif self.state == NBIoTDriverState.COAP_RECEIVE
       var msg = self.ser.read().asstring()
       print(msg)
+    # ---- MQTT ---- #
+    elif self.state == NBIoTDriverState.MQTT_CHECK_CONN
+      if self.rsp_contains_msg_or_send('+QMTCONN: 0,3', 'AT+QMTCONN?\r\n')
+        self.state = NBIoTDriverState.MQTT_PUBLISH
+      end
+    elif self.state == NBIoTDriverState.MQTT_OPEN
+      if self.rsp_contains_msg_or_send('+QMTOPEN: 0,0', self.build_mqtt_open_cmd())
+        self.state = NBIoTDriverState.MQTT_CONNECT
+      end
+    elif self.state == NBIoTDriverState.MQTT_CONNECT
+      if self.rsp_contains_msg_or_send('+QMTCONN: 0,0,0', self.build_mqtt_conn_cmd())
+        self.state = NBIoTDriverState.MQTT_PUBLISH
+      end
+    elif self.state == NBIoTDriverState.MQTT_PUBLISH
+      if self.rsp_contains_msg_or_send('+QMTPUB: 0,0,0', self.build_mqtt_pub_cmd())
+        self.finish_request()
+
+        self.state = NBIoTDriverState.READY
+      end
+    elif self.state == NBIoTDriverState.MQTT_CLOSE
+      if self.rsp_contains_msg_or_send('+QMTDISC: 0,0', 'AT+QMTDISC=0\r\n')
+        if self.request != nil
+          self.state = NBIoTDriverState.MQTT_OPEN
+        else
+          self.state = NBIoTDriverState.READY
+        end
+      end
     else
-      print('duuude')
+      tasmota.remove_driver(self)
     end
   end
 end
@@ -114,6 +265,42 @@ nbiot.init = def (m)
 
       tasmota.add_driver(self._driver)
     end
+
+    def mqtt_publish(host, port, username, password, topic, payload, callback)
+      if type(payload) == type('')
+        var request = NBIoTMQTTRequest(host, port, username, password, topic, payload, callback)
+
+        self._driver.queue_request(request)
+        
+        return true
+      else 
+        return false
+      end
+    end
+
+    def coap_get(host, port, path, query, callback)
+      if type(path) != type([]) || type(query) != type([])
+        return false
+      else
+        var request = NBIoTCOAPRequest(host, port, path, 'GET', query, nil, callback)
+
+        self._driver.queue_request(request)
+
+        return true
+      end
+    end
+
+    def coap_post(host, port, path, payload, callback)
+      if type(path) != type([])
+        return false
+      else
+        var request = NBIoTCOAPRequest(host, port, path, 'POST', [], payload, callback)
+
+        self._driver.queue_request(request)
+
+        return true
+      end
+    end
   end
 
   return nbiot()