From d13c8ade455d695fd60614e82c59061a2c148590 Mon Sep 17 00:00:00 2001
From: Andreas Strasser <a.strasser@student.tugraz.at>
Date: Sun, 30 Jul 2023 07:32:42 +0200
Subject: [PATCH] implemented power saving

---
 src/driver/nbiot.be | 115 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 103 insertions(+), 12 deletions(-)

diff --git a/src/driver/nbiot.be b/src/driver/nbiot.be
index 1857b2e..a510d3e 100644
--- a/src/driver/nbiot.be
+++ b/src/driver/nbiot.be
@@ -1,15 +1,29 @@
 import string
+import gpio
 
 class NBIoTRequestType
   static var MQTT = 1
   static var COAP = 2
   static var NTP = 3
+  static var PSM = 4
+  static var TEST = 69
 end
 
 class NBIoTRequest
   var type
 end
 
+class NBIoTTestRequest : NBIoTRequest
+  var msg
+  var cmd
+
+  def init(msg, cmd)
+    self.type = NBIoTRequestType.TEST
+    self.msg = msg
+    self.cmd = cmd
+  end
+end
+
 class NBIoTMQTTRequest : NBIoTRequest
   var type
   var host
@@ -32,12 +46,6 @@ class NBIoTMQTTRequest : NBIoTRequest
   end
 end
 
-class NBIoTNTPRequest : NBIoTRequest
-  def init()
-    self.type = NBIoTRequestType.NTP
-  end
-end
-
 class NBIoTCOAPRequest : NBIoTRequest
   var host
   var port
@@ -59,6 +67,26 @@ class NBIoTCOAPRequest : NBIoTRequest
   end
 end
 
+class NBIoTNTPRequest : NBIoTRequest
+  var callback
+
+  def init(callback)
+    self.type = NBIoTRequestType.NTP
+    self.callback = callback
+  end
+end
+
+class NBIoTPSMRequest : NBIoTRequest
+  var value
+  var callback
+
+  def init(value, callback)
+    self.type = NBIoTRequestType.PSM
+    self.value = value
+    self.callback = callback
+  end
+end
+
 class NBIoTMQTTConnection
   var host
   var port
@@ -84,6 +112,7 @@ class NBIoTMQTTConnection
 end
 
 class NBIoTDriverState
+  static var IDLE = 0
   static var RESET = 1
   static var READY = 2
   static var NTP_SYNC = 3
@@ -97,6 +126,11 @@ class NBIoTDriverState
   static var COAP_SEND = 11
   static var COAP_RECEIVE = 12
   static var COAP_CLOSE = 13
+  static var PSM_DISABLE = 14
+  static var PSM_INIT = 15
+  static var PSM_CFG = 16
+  static var PSM_ENABLE = 17
+  static var TEST = 69 
 end
 
 class NBIoTDriver
@@ -110,14 +144,16 @@ class NBIoTDriver
   var request_queue
   var request
   var mqtt_connection
+  var psm_eint
 
-  def init(rx, tx)
-    self.state = NBIoTDriverState.RESET
+  def init(rx, tx, psm_eint)
+    self.state = NBIoTDriverState.PSM_DISABLE
     self.rsp_awaiting = false
     self.retries = self.MAX_RETRIES
     self.request_queue = []
     self.request = nil
     self.mqtt_connection = nil
+    self.psm_eint = psm_eint
 
     self.ser = serial(rx, tx, 115200, serial.SERIAL_8N1)
   end
@@ -184,6 +220,8 @@ class NBIoTDriver
     if self.rsp_awaiting
       var rsp = self.ser.read().asstring()
 
+      print(rsp)
+
       if string.find(rsp, msg) >= 0
         self.rsp_awaiting = false
 
@@ -231,12 +269,22 @@ class NBIoTDriver
   end
 
   def every_second()
+    if self.state == NBIoTDriverState.IDLE
+      return
     # ---- retries exceeded ---- #
-    if self.retries < 1 && self.request != nil
+    elif self.retries < 1 && self.request != nil
       self.request = nil
+      self.mqtt_connection = nil
       self.next_state(NBIoTDriverState.RESET)
 
       tasmota.log('NBT: Maximum number of retries exceeded, skipping request', 2)
+    # ---- disable power saving mode ---- #
+    elif self.state == NBIoTDriverState.PSM_DISABLE
+      gpio.digital_write(self.psm_eint, 1)
+
+      if self.rsp_contains_msg_or_send('OK', 'AT+QSCLK=0\r\n')
+        self.next_state(NBIoTDriverState.RESET)
+      end
     # ---- reset module ---- #
     elif self.state == NBIoTDriverState.RESET
       if self.rsp_contains_msg_or_send('RDY', 'AT+QRST=1\r\n')
@@ -265,10 +313,22 @@ class NBIoTDriver
             self.mqtt_connection = mqtt_connection
             self.next_state(NBIoTDriverState.MQTT_OPEN)
           end
+        elif self.request.type == NBIoTRequestType.TEST
+          self.next_state(NBIoTDriverState.TEST)
+        elif self.request.type == NBIoTRequestType.PSM
+          if self.request.value
+            self.next_state(NBIoTDriverState.PSM_INIT)
+          else
+            self.next_state(NBIoTDriverState.PSM_DISABLE)
+          end
         else
           self.finish_request()
         end
       end
+    elif self.state == NBIoTDriverState.TEST
+      if self.rsp_contains_msg_or_send(self.request.msg, self.request.cmd + '\r\n')
+        self.next_state(NBIoTDriverState.READY)
+      end
     # ---- fetch time from ntp server ---- #
     elif self.state == NBIoTDriverState.NTP_SYNC
       var rsp = self.fetch_rsp_if_contains_msg_or_send('+QNTP: 0', 'AT+QNTP=1,\"0.at.pool.ntp.org\"\r\n')
@@ -277,6 +337,10 @@ class NBIoTDriver
         self.set_system_time(rsp)
         self.next_state(NBIoTDriverState.READY)
       end
+    elif self.state == NBIoTDriverState.TEST
+      if self.rsp_contains_msg_or_send(self.request.msg, self.request.cmd + '\r\n')
+        self.next_state(NBIoTDriverState.READY)
+      end
     # ---- punlish mqtt message ---- #
     elif self.state == NBIoTDriverState.MQTT_CHECK_CONN
       if self.retries == 1
@@ -320,6 +384,21 @@ class NBIoTDriver
     elif self.state == NBIoTDriverState.COAP_RECEIVE
       var msg = self.ser.read().asstring()
       print(msg)
+    # ---- enable power saving mode ---- #
+    elif self.state == NBIoTDriverState.PSM_INIT
+      if self.rsp_contains_msg_or_send('OK', 'AT+CEREG=5\r\n')
+        self.next_state(NBIoTDriverState.PSM_CFG)
+      end
+    elif self.state == NBIoTDriverState.PSM_CFG
+      if self.rsp_contains_msg_or_send('OK', 'AT+CPSMS=1,,,\"11100010\",\"00000001\"\r\n')
+        self.next_state(NBIoTDriverState.PSM_ENABLE)
+      end
+    elif self.state == NBIoTDriverState.PSM_ENABLE
+      gpio.digital_write(self.psm_eint, 0)
+
+      if self.rsp_contains_msg_or_send('OK', 'AT+QSCLK=1\r\n')
+        self.next_state(NBIoTDriverState.IDLE)
+      end
     else
       tasmota.log('NBT: Invalid driver state, stopping driver', 2)
       tasmota.remove_driver(self)
@@ -334,13 +413,19 @@ nbiot.init = def (m)
     var _driver
 
     def init()
-      self._driver = NBIoTDriver(19, 23)
+      self._driver = NBIoTDriver(18, 23, 16)
 
       tasmota.add_driver(self._driver)
     end
 
-    def sync_time()
-      var request = NBIoTNTPRequest()
+    def set_power_save_mode(value, callback)
+      var request = NBIoTPSMRequest(value, callback)
+
+      self._driver.queue_request(request)
+    end
+
+    def sync_time(callback)
+      var request = NBIoTNTPRequest(callback)
 
       self._driver.queue_request(request)
     end
@@ -380,6 +465,12 @@ nbiot.init = def (m)
         return true
       end
     end
+
+    def test(msg, cmd)
+      var request = NBIoTTestRequest(msg, cmd)
+
+      self._driver.queue_request(request)
+    end
   end
 
   return nbiot()
-- 
GitLab