gl-puli-mcu: Add power monitoring for XE3000 (Puli AX) variant
authorJean Thomas <jean.thomas@wifirst.fr>
Wed, 15 Nov 2023 14:59:07 +0000 (15:59 +0100)
committerNuno Goncalves <nunojpg@gmail.com>
Mon, 20 Nov 2023 14:51:52 +0000 (14:51 +0000)
Signed-off-by: Jean Thomas <jean.thomas@wifirst.fr>
utils/gl-puli-mcu/Config.in [new file with mode: 0644]
utils/gl-puli-mcu/Makefile
utils/gl-puli-mcu/src/gl-puli-mcu.c

diff --git a/utils/gl-puli-mcu/Config.in b/utils/gl-puli-mcu/Config.in
new file mode 100644 (file)
index 0000000..315526c
--- /dev/null
@@ -0,0 +1,12 @@
+choice
+    depends on PACKAGE_gl-puli-mcu
+
+    prompt "GL.iNet target"
+    default GL_PULI_MCU_XE300
+
+    config GL_PULI_MCU_XE300
+            bool "GL.iNet XE300 (Puli)"
+
+    config GL_PULI_MCU_XE3000
+            bool "GL.iNet XE3000 (Puli AX)"
+endchoice
index d33e9288f3062dc2360994eac8c2ac136f8b15cd..b1da42c77748ae49943db705e4f3d35db80e9506 100644 (file)
@@ -1,24 +1,40 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=gl-puli-mcu
-PKG_VERSION:=1
+PKG_VERSION:=2
 PKG_RELEASE:=1
 
 PKG_MAINTAINER:=Nuno Goncalves <nunojpg@gmail.com>
 PKG_LICENSE:=GPL-3.0-or-later
 
+PKG_CONFIG_DEPENDS:= \
+  CONFIG_GL_PULI_MCU_XE300 \
+  CONFIG_GL_PULI_MCU_XE3000
+
 include $(INCLUDE_DIR)/package.mk
 include $(INCLUDE_DIR)/cmake.mk
 
+define Package/gl-puli-mcu/config
+  source "$(SOURCE)/Config.in"
+endef
+
 define Package/gl-puli-mcu
   SECTION:=utils
   CATEGORY:=Utilities
-  TITLE:=GL.iNet GL-XE300 (Puli) power monitoring support
-  DEPENDS:=+kmod-usb-serial-ch341 +libubus +libubox
+  TITLE:=GL.iNet power monitoring support
+  DEPENDS:=+CONFIG_GL_PULI_MCU_XE300:kmod-usb-serial-ch341 +libubus +libubox
+  MENU:=1
 endef
 
+ifeq ($(CONFIG_GL_PULI_MCU_XE300),y)
+  TARGET_CFLAGS+=-DGL_TARGET=1
+endif
+ifeq ($(CONFIG_GL_PULI_MCU_XE3000),y)
+  TARGET_CFLAGS+=-DGL_TARGET=2
+endif
+
 define Package/gl-puli-mcu/description
-  Interfaces with GL-XE300 (Puli) power monitoring MCU over
+  Interfaces with GL.iNet Puli family power monitoring MCU over
   a USB to UART adapter present on the device and provides
   battery SOC, temperature, charging state and cycle count at
   ubus battery/info.
index 6cf4f2abde51e745b68fa59f7e61957cb5ec3642..da7d7db8391477cca0cedf71ee4d996b3894465b 100644 (file)
 #include <libubox/uloop.h>
 #include <libubus.h>
 
+#define GL_TARGET_XE300  1
+#define GL_TARGET_XE3000 2
+
+#if GL_TARGET == GL_TARGET_XE300
+#define MCU_PORT "/dev/ttyUSB0"
+#elif GL_TARGET ==  GL_TARGET_XE3000
+#define MCU_PORT "/dev/ttyS1"
+#else
+#error Please define GL_TARGET!
+#endif /* GL_TARGET */
+
 static struct ustream_fd stream;
 static struct ubus_auto_conn conn;
 static struct blob_buf b;
@@ -39,6 +50,9 @@ struct Battery
        bool set;
 } battery;
 
+#if GL_TARGET == GL_TARGET_XE300
+// MCU status returns something like:
+// {OK},100,275,1,0
 static bool
 process(char *read)
 {
@@ -66,6 +80,65 @@ process(char *read)
                return false;
        return true;
 }
+#elif GL_TARGET == GL_TARGET_XE3000
+static bool
+get_int_value(const char *read, const char *key, int *int_value, char **new_end)
+{
+       char *from = NULL;
+
+       from = strstr(read, key);
+       if ((!from) || (from != read))
+       {
+               return false;
+       }
+       from = (char *)read + strlen(key);
+       *int_value = strtol(from, new_end, 10);
+       if (from == *new_end)
+       {
+               return false;
+       }
+
+       return true;
+}
+
+// MCU status returns something like:
+// {"code":0,"capacity":100,"temp":28,"chg_state":1,"charge_cycle":0}
+static bool
+process(char *read)
+{
+       int int_value = 0;
+       char *to = NULL;
+
+       if ((read[0] != '{') ||
+               (!get_int_value(&read[1], "\"code\":", &int_value, &to)) ||
+               (int_value != 0))
+       {
+               return false;
+       }
+       if (!get_int_value(to + 1, "\"capacity\":", &int_value, &to))
+       {
+               return false;
+       }
+       battery.soc = int_value;
+       if (!get_int_value(to + 1, "\"temp\":", &int_value, &to))
+       {
+               return false;
+       }
+       battery.temperature = (float) int_value;
+       if (!get_int_value(to + 1, "\"chg_state\":", &int_value, &to))
+       {
+               return false;
+       }
+       battery.charging = (bool) int_value;
+       if (!get_int_value(to + 1, "\"charge_cycle\":", &int_value, &to))
+       {
+               return false;
+       }
+       battery.cycles = (uint16_t) int_value;
+
+       return true;
+}
+#endif /* GL_TARGET */
 
 static int
 consume(struct ustream *s, char **a)
@@ -202,7 +275,7 @@ main(int argc, char **argv)
        conn.cb = ubus_connect_handler;
        ubus_auto_connect(&conn);
 
-       if (serial_open("/dev/ttyUSB0") < 0)
+       if (serial_open(MCU_PORT) < 0)
                return -1;
 
        serial_query_timer.cb = serial_query_handler;