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()