Hello Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/3277

to look at the new patch set (#4).

lc15: port lc15bts-mgr changes

That's mostly changes related to lc15bts-mgr from
https://gitlab.com/nrw_noa/osmo-bts branch nrw/litecell15 based on
eb5b7f80510b603579f7af6d7d5ead296c2fa260 commit.

I wanted to incorporate vty and hardcoded paths changes so we can use it
from this point without major backward-incompatible changes as a base
for future ports.

Change-Id: Iabbaedc84aaaa594150a4e5445c16dd1f6f89858
Related: SYS#3679
---
M doc/examples/litecell15/lc15bts-mgr.cfg
M include/osmo-bts/phy_link.h
M src/common/Makefile.am
M src/osmo-bts-litecell15/Makefile.am
M src/osmo-bts-litecell15/hw_misc.c
A src/osmo-bts-litecell15/misc/lc15bts_bts.c
A src/osmo-bts-litecell15/misc/lc15bts_bts.h
M src/osmo-bts-litecell15/misc/lc15bts_clock.c
A src/osmo-bts-litecell15/misc/lc15bts_led.c
A src/osmo-bts-litecell15/misc/lc15bts_led.h
M src/osmo-bts-litecell15/misc/lc15bts_mgr.c
M src/osmo-bts-litecell15/misc/lc15bts_mgr.h
M src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c
M src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c
M src/osmo-bts-litecell15/misc/lc15bts_misc.c
M src/osmo-bts-litecell15/misc/lc15bts_misc.h
M src/osmo-bts-litecell15/misc/lc15bts_par.c
M src/osmo-bts-litecell15/misc/lc15bts_par.h
M src/osmo-bts-litecell15/misc/lc15bts_power.c
M src/osmo-bts-litecell15/misc/lc15bts_power.h
M src/osmo-bts-litecell15/misc/lc15bts_temp.c
M src/osmo-bts-litecell15/misc/lc15bts_temp.h
22 files changed, 2,014 insertions(+), 411 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/77/3277/4

diff --git a/doc/examples/litecell15/lc15bts-mgr.cfg 
b/doc/examples/litecell15/lc15bts-mgr.cfg
index 750dc36..c7d0a79 100644
--- a/doc/examples/litecell15/lc15bts-mgr.cfg
+++ b/doc/examples/litecell15/lc15bts-mgr.cfg
@@ -25,39 +25,19 @@
  no login
 !
 lc15bts-mgr
- limits supply
-   threshold warning 60
-   threshold critical 78
- limits soc
-   threshold warning 60
-   threshold critical 78
- limits fpga
-   threshold warning 60
-   threshold critical 78
- limits logrf
-   threshold warning 60
-   threshold critical 78
- limits tx0
-   threshold warning 60
-   threshold critical 78
- limits tx1
-   threshold warning 60
-   threshold critical 78
- limits pa0
-   threshold warning 60
-   threshold critical 78
- limits pa1
-   threshold warning 60
-   threshold critical 78
- actions normal
-  pa0-on
-  pa1-on
-  bts-service-on
- actions warn
-  no pa0-off
-  no pa1-off
-  no bts-service-off
- actions critical
-  pa0-off
-  pa1-off
-  no bts-service-off
+ limits supply_volt
+   threshold warning min 17500
+   threshold critical min 19000
+ limits tx0_vswr
+   threshold warning max 3
+ limits tx1_vswr
+   threshold warning max 3
+ limits supply_pwr
+   threshold warning max 110
+   threshold critical max 120
+ limits pa0_pwr
+   threshold warning max 50
+   threshold critical max 60
+ limits pa1_pwr
+   threshold warning max 50
+   threshold critical max 60
diff --git a/include/osmo-bts/phy_link.h b/include/osmo-bts/phy_link.h
index d8d3c6b..3d4bf91 100644
--- a/include/osmo-bts/phy_link.h
+++ b/include/osmo-bts/phy_link.h
@@ -124,6 +124,12 @@
                        int minTxPower;
                        int maxTxPower;
                        struct lc15l1_hdl *hdl;
+                       uint8_t max_cell_size;          /* 0:166 qbits*/
+                       uint8_t diversity_mode;         /* 0: SISO A, 1: SISO 
B, 2: MRC */
+                       uint8_t pedestal_mode;          /* 0: unused TS is OFF, 
1: unused TS is in minimum Tx power */
+                       uint8_t dsp_alive_period;       /* DSP alive timer 
period  */
+                       uint8_t tx_pwr_adj_mode;        /* 0: no auto adjust 
power, 1: auto adjust power using RMS detector */
+                       uint8_t tx_pwr_red_8psk;        /* 8-PSK maximum Tx 
power reduction level in dB */
                } lc15;
        } u;
 };
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index dd368d0..d104c48 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -2,6 +2,10 @@
 AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOTRAU_CFLAGS) 
$(LIBOSMOCODEC_CFLAGS)
 LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOCODEC_LIBS)
 
+if ENABLE_LC15BTS
+AM_CFLAGS += -DENABLE_LC15BTS
+endif
+
 noinst_LIBRARIES = libbts.a libl1sched.a
 libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
                   rsl.c vty.c paging.c measurement.c amr.c lchan.c \
diff --git a/src/osmo-bts-litecell15/Makefile.am 
b/src/osmo-bts-litecell15/Makefile.am
index 3026e96..90e6c46 100644
--- a/src/osmo-bts-litecell15/Makefile.am
+++ b/src/osmo-bts-litecell15/Makefile.am
@@ -4,9 +4,11 @@
 AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) 
$(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) 
$(LIBOSMOABIS_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) 
$(LIBGPS_CFLAGS) $(ORTP_CFLAGS)
 COMMON_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) 
$(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOCTRL_LIBS) 
$(ORTP_LIBS)
 
-EXTRA_DIST = misc/lc15bts_mgr.h misc/lc15bts_misc.h misc/lc15bts_par.h \
+AM_CFLAGS += -DENABLE_LC15BTS
+
+EXTRA_DIST = misc/lc15bts_mgr.h misc/lc15bts_misc.h misc/lc15bts_par.h 
misc/lc15bts_led.h \
        misc/lc15bts_temp.h misc/lc15bts_power.h misc/lc15bts_clock.h \
-       misc/lc15bts_bid.h misc/lc15bts_nl.h \
+       misc/lc15bts_bid.h misc/lc15bts_nl.h misc/lc15bts_bts.h \
        hw_misc.h l1_if.h l1_transp.h lc15bts.h oml_router.h utils.h
 
 bin_PROGRAMS = osmo-bts-lc15 lc15bts-mgr lc15bts-util
@@ -25,9 +27,11 @@
                misc/lc15bts_mgr_vty.c \
                misc/lc15bts_mgr_nl.c \
                misc/lc15bts_mgr_temp.c \
-               misc/lc15bts_mgr_calib.c 
+               misc/lc15bts_mgr_calib.c \
+               misc/lc15bts_led.c \
+               misc/lc15bts_bts.c
 
-lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) 
$(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) 
$(LIBOSMOCTRL_LIBS)
+lc15bts_mgr_LDADD = $(top_builddir)/src/common/libbts.a $(LIBGPS_LIBS) 
$(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOABIS_LIBS) $(LIBOSMOGSM_LIBS) 
$(LIBOSMOCTRL_LIBS) $(COMMON_LDADD)
 
 lc15bts_util_SOURCES = misc/lc15bts_util.c misc/lc15bts_par.c
 lc15bts_util_LDADD = $(LIBOSMOCORE_LIBS)
diff --git a/src/osmo-bts-litecell15/hw_misc.c 
b/src/osmo-bts-litecell15/hw_misc.c
index 49232b2..9f070bb 100644
--- a/src/osmo-bts-litecell15/hw_misc.c
+++ b/src/osmo-bts-litecell15/hw_misc.c
@@ -69,6 +69,7 @@
 
        rc = write(fd, cmd[0] ? "1" : "0", 2);
        if (rc != 2) {
+               close(fd);
                return -1;
        }
        close(fd);
@@ -79,6 +80,7 @@
 
        rc = write(fd, cmd[1] ? "1" : "0", 2);
        if (rc != 2) {
+               close(fd);
                return -1;
        }
        close(fd);
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_bts.c 
b/src/osmo-bts-litecell15/misc/lc15bts_bts.c
new file mode 100644
index 0000000..0343e93
--- /dev/null
+++ b/src/osmo-bts-litecell15/misc/lc15bts_bts.c
@@ -0,0 +1,131 @@
+/* Copyright (C) 2016 by NuRAN Wireless <supp...@nuranwireless.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include "lc15bts_mgr.h"
+#include "lc15bts_bts.h"
+
+static int check_eth_status(char *dev_name)
+{
+       int fd, rc;
+       struct ifreq ifr;
+
+       fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+       if (fd < 0)
+               return fd;
+
+       memset(&ifr, 0, sizeof(ifr));
+       memcpy(&ifr.ifr_name, dev_name, sizeof(ifr.ifr_name));
+       rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
+       close(fd);
+
+       if (rc < 0)
+               return rc;
+
+       if ((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING))
+               return 0;
+
+       return 1;
+}
+
+void check_bts_led_pattern(uint8_t *led)
+{
+       FILE *fp;
+       char str[64] =  "\0";
+       int rc;
+
+       /* check for existing of BTS state file */
+       if ((fp = fopen("/var/run/osmo-bts/state", "r")) == NULL) {
+               led[BLINK_PATTERN_INIT] = 1;
+               return;
+       }
+
+       /* check Ethernet interface status */
+       rc = check_eth_status("eth0");
+       if (rc > 0) {
+               LOGP(DTEMP, LOGL_DEBUG,"External link is DOWN\n");
+               led[BLINK_PATTERN_EXT_LINK_MALFUNC] = 1;
+               fclose(fp);
+               return;
+       }
+
+       /* check for BTS is still alive */
+       if (system("pidof osmo-bts-lc15 > /dev/null")) {
+               LOGP(DTEMP, LOGL_DEBUG,"BTS process has stopped\n");
+               led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1;
+               fclose(fp);
+               return;
+       }
+
+       /* check for BTS state */
+       while (fgets(str, 64, fp) != NULL) {
+               LOGP(DTEMP, LOGL_DEBUG,"BTS state is %s\n", (strstr(str, "ABIS 
DOWN") != NULL) ? "DOWN" : "UP");
+               if (strstr(str, "ABIS DOWN") != NULL)
+                       led[BLINK_PATTERN_INT_PROC_MALFUNC] = 1;
+       }
+       fclose(fp);
+
+       return;
+}
+
+int check_sensor_led_pattern( struct lc15bts_mgr_instance *mgr, uint8_t *led)
+{
+       if(mgr->alarms.temp_high == 1)
+               led[BLINK_PATTERN_TEMP_HIGH] = 1;
+
+       if(mgr->alarms.temp_max == 1)
+               led[BLINK_PATTERN_TEMP_MAX] = 1;
+
+       if(mgr->alarms.supply_low == 1)
+               led[BLINK_PATTERN_SUPPLY_VOLT_LOW] = 1;
+
+       if(mgr->alarms.supply_min == 1)
+               led[BLINK_PATTERN_SUPPLY_VOLT_MIN] = 1;
+
+       if(mgr->alarms.vswr_high == 1)
+               led[BLINK_PATTERN_VSWR_HIGH] = 1;
+
+       if(mgr->alarms.vswr_max == 1)
+               led[BLINK_PATTERN_VSWR_MAX] = 1;
+
+       if(mgr->alarms.supply_pwr_high == 1)
+               led[BLINK_PATTERN_SUPPLY_PWR_HIGH] = 1;
+
+       if(mgr->alarms.supply_pwr_max == 1)
+               led[BLINK_PATTERN_SUPPLY_PWR_MAX] = 1;
+
+       if(mgr->alarms.supply_pwr_max2 == 1)
+               led[BLINK_PATTERN_SUPPLY_PWR_MAX2] = 1;
+
+       if(mgr->alarms.pa_pwr_high == 1)
+               led[BLINK_PATTERN_PA_PWR_HIGH] = 1;
+
+       if(mgr->alarms.pa_pwr_max == 1)
+               led[BLINK_PATTERN_PA_PWR_MAX] = 1;
+
+       if(mgr->alarms.gps_fix_lost == 1)
+               led[BLINK_PATTERN_GPS_FIX_LOST] = 1;
+
+       return 0;
+}
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_bts.h 
b/src/osmo-bts-litecell15/misc/lc15bts_bts.h
new file mode 100644
index 0000000..3918b87
--- /dev/null
+++ b/src/osmo-bts-litecell15/misc/lc15bts_bts.h
@@ -0,0 +1,21 @@
+#ifndef _LC15BTS_BTS_H_
+#define _LC15BTS_BTS_H_
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <osmo-bts/logging.h>
+
+/* public function prototypes */
+void check_bts_led_pattern(uint8_t *led);
+int check_sensor_led_pattern( struct lc15bts_mgr_instance *mgr, uint8_t *led);
+
+#endif
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_clock.c 
b/src/osmo-bts-litecell15/misc/lc15bts_clock.c
index f4df5d3..7170149 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_clock.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_clock.c
@@ -100,9 +100,6 @@
 
 int lc15bts_clock_err_open(void)
 {
-       int rc;
-       int fault;
-
        if (clkerr_fd_err < 0) {
                clkerr_fd_err = open(CLKERR_ERR_SYSFS, O_RDONLY);
                if (clkerr_fd_err < 0) {
@@ -149,26 +146,6 @@
                        lc15bts_clock_err_close();
                        return clkerr_fd_reset; 
                }
-       }
-
-       rc = sysfs_write_str(clkerr_fd_refresh, "once");
-       if (rc < 0) {
-               lc15bts_clock_err_close();
-               return rc;      
-       }
-
-       rc = sysfs_read_val(clkerr_fd_fault, &fault);
-       if (rc < 0) {
-               lc15bts_clock_err_close();
-               return rc;      
-       }
-
-       if (fault) { 
-               rc = sysfs_write_val(clkerr_fd_reset, 1);
-               if (rc < 0) {
-                       lc15bts_clock_err_close();
-                       return rc;
-               }
        }
        return 0;
 }
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_led.c 
b/src/osmo-bts-litecell15/misc/lc15bts_led.c
new file mode 100644
index 0000000..603e0fb
--- /dev/null
+++ b/src/osmo-bts-litecell15/misc/lc15bts_led.c
@@ -0,0 +1,333 @@
+/* Copyright (C) 2016 by NuRAN Wireless <supp...@nuranwireless.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "lc15bts_led.h"
+#include "lc15bts_bts.h"
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/linuxlist.h>
+
+static struct lc15bts_led led_entries[] = {
+       {
+               .name = "led0",
+               .fullname = "led red",
+               .path = "/var/lc15/leds/led0/brightness"
+       },
+       {
+               .name = "led1",
+               .fullname = "led green",
+               .path = "/var/lc15/leds/led1/brightness"
+       }
+};
+
+static const struct value_string lc15bts_led_strs[] = {
+       { LC15BTS_LED_RED, "LED red" },
+       { LC15BTS_LED_GREEN, "LED green" },
+       { LC15BTS_LED_ORANGE, "LED orange" },
+       { LC15BTS_LED_OFF, "LED off" },
+       { 0, NULL }
+};
+
+static uint8_t led_priority[] = {
+       BLINK_PATTERN_INIT,
+       BLINK_PATTERN_INT_PROC_MALFUNC,
+       BLINK_PATTERN_SUPPLY_PWR_MAX,
+       BLINK_PATTERN_PA_PWR_MAX,
+       BLINK_PATTERN_VSWR_MAX,
+       BLINK_PATTERN_SUPPLY_VOLT_MIN,
+       BLINK_PATTERN_TEMP_MAX,
+       BLINK_PATTERN_SUPPLY_PWR_MAX2,
+       BLINK_PATTERN_EXT_LINK_MALFUNC,
+       BLINK_PATTERN_SUPPLY_VOLT_LOW,
+       BLINK_PATTERN_TEMP_HIGH,
+       BLINK_PATTERN_VSWR_HIGH,
+       BLINK_PATTERN_SUPPLY_PWR_HIGH,
+       BLINK_PATTERN_PA_PWR_HIGH,
+       BLINK_PATTERN_GPS_FIX_LOST,
+       BLINK_PATTERN_NORMAL
+};
+
+
+char *blink_pattern_command[] = BLINK_PATTERN_COMMAND;
+
+static int lc15bts_led_write(char *path, char *str)
+{
+       int fd;
+
+       if ((fd = open(path, O_WRONLY)) == -1)
+       {
+               return 0;
+       }
+
+       write(fd, str, strlen(str)+1);
+       close(fd);
+       return 1;
+}
+
+static void led_set_red()
+{
+       lc15bts_led_write(led_entries[0].path, "1");
+       lc15bts_led_write(led_entries[1].path, "0");
+}
+
+static void led_set_green()
+{
+       lc15bts_led_write(led_entries[0].path, "0");
+       lc15bts_led_write(led_entries[1].path, "1");
+}
+
+static void led_set_orange()
+{
+       lc15bts_led_write(led_entries[0].path, "1");
+       lc15bts_led_write(led_entries[1].path, "1");
+}
+
+static void led_set_off()
+{
+       lc15bts_led_write(led_entries[0].path, "0");
+       lc15bts_led_write(led_entries[1].path, "0");
+}
+
+static void led_sleep( struct lc15bts_mgr_instance *mgr, struct 
lc15bts_led_timer *led_timer, void (*led_timer_cb)(void *_data)) {
+       /* Cancel any pending timer */
+       osmo_timer_del(&led_timer->timer);
+       /* Start LED timer */
+       led_timer->timer.cb = led_timer_cb;
+       led_timer->timer.data = mgr;
+       mgr->lc15bts_leds.active_timer = led_timer->idx;
+       osmo_timer_schedule(&led_timer->timer, led_timer->param.sleep_sec, 
led_timer->param.sleep_usec);
+       LOGP(DTEMP, LOGL_DEBUG,"%s timer scheduled for %d sec + %d usec\n",
+                       get_value_string(lc15bts_led_strs, led_timer->idx),
+                       led_timer->param.sleep_sec,
+                       led_timer->param.sleep_usec);
+
+       switch (led_timer->idx) {
+       case LC15BTS_LED_RED:
+               led_set_red();
+               break;
+       case LC15BTS_LED_GREEN:
+               led_set_green();
+               break;
+       case LC15BTS_LED_ORANGE:
+               led_set_orange();
+               break;
+       case LC15BTS_LED_OFF:
+               led_set_off();
+               break;
+       default:
+               led_set_off();
+       }
+}
+
+static void led_sleep_cb(void *_data) {
+       struct lc15bts_mgr_instance *mgr = _data;
+       struct lc15bts_led_timer_list *led_list;
+
+       /* make sure the timer list is not empty */
+       if (llist_empty(&mgr->lc15bts_leds.list))
+               return;
+
+       llist_for_each_entry(led_list, &mgr->lc15bts_leds.list, list) {
+               if (led_list->led_timer.idx == mgr->lc15bts_leds.active_timer) {
+                       LOGP(DTEMP, LOGL_DEBUG,"Delete expired %s timer %d sec 
+ %d usec\n",
+                               get_value_string(lc15bts_led_strs, 
led_list->led_timer.idx),
+                               led_list->led_timer.param.sleep_sec,
+                               led_list->led_timer.param.sleep_usec);
+
+                       /* Delete current timer */
+                       osmo_timer_del(&led_list->led_timer.timer);
+                       /* Rotate the timer list */
+                        llist_move_tail(led_list, &mgr->lc15bts_leds.list);
+                       break;
+               }
+       }
+
+       /* Execute next timer */
+       led_list = llist_first_entry(&mgr->lc15bts_leds.list, struct 
lc15bts_led_timer_list, list);
+       if (led_list) {
+               LOGP(DTEMP, LOGL_DEBUG,"Execute %s timer %d sec + %d usec, 
total entries=%d\n",
+                       get_value_string(lc15bts_led_strs, 
led_list->led_timer.idx),
+                       led_list->led_timer.param.sleep_sec,
+                       led_list->led_timer.param.sleep_usec,
+                       llist_count(&mgr->lc15bts_leds.list));
+
+               led_sleep(mgr, &led_list->led_timer, led_sleep_cb);
+       }
+
+}
+
+static void delete_led_timer_entries(struct lc15bts_mgr_instance *mgr)
+{
+       struct lc15bts_led_timer_list *led_list, *led_list2;
+
+       if (llist_empty(&mgr->lc15bts_leds.list))
+               return;
+
+       llist_for_each_entry_safe(led_list, led_list2, &mgr->lc15bts_leds.list, 
list) {
+               /* Delete the timer in list */
+               if (led_list) {
+                       LOGP(DTEMP, LOGL_DEBUG,"Delete %s timer entry from 
list, %d sec + %d usec\n",
+                               get_value_string(lc15bts_led_strs, 
led_list->led_timer.idx),
+                               led_list->led_timer.param.sleep_sec,
+                               led_list->led_timer.param.sleep_usec);
+
+                       /* Delete current timer */
+                       osmo_timer_del(&led_list->led_timer.timer);
+                       llist_del(&led_list->list);
+                       talloc_free(led_list);
+               }
+       }
+       return;
+}
+
+static int add_led_timer_entry(struct lc15bts_mgr_instance *mgr, char *cmdstr)
+{
+       double sec, int_sec, frac_sec;
+       struct lc15bts_sleep_time led_param;
+
+       led_param.sleep_sec = 0;
+       led_param.sleep_usec = 0;
+
+       if (strstr(cmdstr, "set red") != NULL)
+               mgr->lc15bts_leds.led_idx = LC15BTS_LED_RED;
+       else if (strstr(cmdstr, "set green") != NULL)
+               mgr->lc15bts_leds.led_idx = LC15BTS_LED_GREEN;
+       else if (strstr(cmdstr, "set orange") != NULL)
+               mgr->lc15bts_leds.led_idx = LC15BTS_LED_ORANGE;
+       else if (strstr(cmdstr, "set off") != NULL)
+               mgr->lc15bts_leds.led_idx = LC15BTS_LED_OFF;
+       else if (strstr(cmdstr, "sleep") != NULL) {
+               sec = atof(cmdstr + 6);
+               /* split time into integer and fractional of seconds */
+               frac_sec = modf(sec, &int_sec) * 1000000.0;
+               led_param.sleep_sec = (int)int_sec;
+               led_param.sleep_usec = (int)frac_sec;
+
+               if ((mgr->lc15bts_leds.led_idx >= LC15BTS_LED_RED) && 
(mgr->lc15bts_leds.led_idx < _LC15BTS_LED_MAX)) {
+                       struct lc15bts_led_timer_list *led_list;
+
+                       /* allocate timer entry */
+                       led_list = talloc_zero(tall_mgr_ctx, struct 
lc15bts_led_timer_list);
+                       if (led_list) {
+                               led_list->led_timer.idx = 
mgr->lc15bts_leds.led_idx;
+                               led_list->led_timer.param.sleep_sec = 
led_param.sleep_sec;
+                               led_list->led_timer.param.sleep_usec = 
led_param.sleep_usec;
+                               llist_add_tail(&led_list->list, 
&mgr->lc15bts_leds.list);
+
+                               LOGP(DTEMP, LOGL_DEBUG,"Add %s timer to list, 
%d sec + %d usec, total entries=%d\n",
+                                       get_value_string(lc15bts_led_strs, 
mgr->lc15bts_leds.led_idx),
+                                       led_list->led_timer.param.sleep_sec,
+                                       led_list->led_timer.param.sleep_usec,
+                                       llist_count(&mgr->lc15bts_leds.list));
+                       }
+               }
+       } else
+               return -1;
+
+       return 0;
+}
+
+static int parse_led_pattern(char *pattern, struct lc15bts_mgr_instance *mgr)
+{
+       char str[1024];
+       char *pstr;
+       char *sep;
+       int rc = 0;
+
+       strcpy(str, pattern);
+       pstr = str;
+       while ((sep = strsep(&pstr, ";")) != NULL) {
+               rc = add_led_timer_entry(mgr, sep);
+               if (rc < 0) {
+                       break;
+               }
+
+       }
+       return rc;
+}
+
+/*** led interface ***/
+
+void led_set(struct lc15bts_mgr_instance *mgr, int pattern_id)
+{
+       int rc;
+       struct lc15bts_led_timer_list *led_list;
+
+       if (pattern_id > BLINK_PATTERN_MAX_ITEM - 1) {
+               LOGP(DTEMP, LOGL_ERROR, "Invalid LED pattern : %d. LED pattern 
must be between %d..%d\n",
+                               pattern_id,
+                               BLINK_PATTERN_POWER_ON,
+                               BLINK_PATTERN_MAX_ITEM - 1);
+               return;
+       }
+       if (pattern_id == mgr->lc15bts_leds.last_pattern_id)
+               return;
+
+       mgr->lc15bts_leds.last_pattern_id = pattern_id;
+
+       LOGP(DTEMP, LOGL_NOTICE, "blink pattern command : %d\n", pattern_id);
+       LOGP(DTEMP, LOGL_NOTICE, "%s\n", blink_pattern_command[pattern_id]);
+
+       /* Empty existing LED timer in the list */
+       delete_led_timer_entries(mgr);
+
+       /* parse LED pattern */
+       rc = parse_led_pattern(blink_pattern_command[pattern_id], mgr);
+       if (rc < 0) {
+               LOGP(DTEMP, LOGL_ERROR,"LED pattern not found or invalid LED 
pattern\n");
+               return;
+       }
+
+       /* make sure the timer list is not empty */
+       if (llist_empty(&mgr->lc15bts_leds.list))
+               return;
+
+       /* Start the first LED timer in the list */
+       led_list = llist_first_entry(&mgr->lc15bts_leds.list, struct 
lc15bts_led_timer_list, list);
+       if (led_list) {
+               LOGP(DTEMP, LOGL_DEBUG,"Execute timer %s for %d sec + %d 
usec\n",
+                       get_value_string(lc15bts_led_strs, 
led_list->led_timer.idx),
+                       led_list->led_timer.param.sleep_sec,
+                       led_list->led_timer.param.sleep_usec);
+
+               led_sleep(mgr, &led_list->led_timer, led_sleep_cb);
+       }
+
+}
+
+void select_led_pattern(struct lc15bts_mgr_instance *mgr)
+{
+       int i;
+       uint8_t led[BLINK_PATTERN_MAX_ITEM] = {0};
+
+       /* set normal LED pattern at first */
+       led[BLINK_PATTERN_NORMAL] = 1;
+
+       /* check on-board sensors for new LED pattern */
+       check_sensor_led_pattern(mgr, led);
+
+       /* check BTS status for new LED pattern */
+       check_bts_led_pattern(led);
+
+       /* check by priority */
+       for (i = 0; i < sizeof(led_priority)/sizeof(uint8_t); i++) {
+               if(led[led_priority[i]] == 1) {
+                       led_set(mgr, led_priority[i]);
+                       break;
+               }
+       }
+}
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_led.h 
b/src/osmo-bts-litecell15/misc/lc15bts_led.h
new file mode 100644
index 0000000..b6d9d28
--- /dev/null
+++ b/src/osmo-bts-litecell15/misc/lc15bts_led.h
@@ -0,0 +1,22 @@
+#ifndef _LC15BTS_LED_H
+#define _LC15BTS_LED_H
+
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/stat.h>
+
+#include <osmo-bts/logging.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/utils.h>
+
+#include "lc15bts_mgr.h"
+
+/* public function prototypes */
+void led_set(struct lc15bts_mgr_instance *mgr, int pattern_id);
+
+void select_led_pattern(struct lc15bts_mgr_instance *mgr);
+
+#endif
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr.c 
b/src/osmo-bts-litecell15/misc/lc15bts_mgr.c
index 3a7d3a1..51a05f9 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_mgr.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_mgr.c
@@ -46,13 +46,14 @@
 #include "misc/lc15bts_par.h"
 #include "misc/lc15bts_bid.h"
 #include "misc/lc15bts_power.h"
+#include "lc15bts_led.h"
 
 static int no_rom_write = 0;
 static int daemonize = 0;
 void *tall_mgr_ctx;
 
 /* every 6 hours means 365*4 = 1460 rom writes per year (max) */
-#define TEMP_TIMER_SECS                (6 * 3600)
+#define SENSOR_TIMER_SECS              (6 * 3600)
 
 /* every 1 hours means 365*24 = 8760 rom writes per year (max) */
 #define HOURS_TIMER_SECS       (1 * 3600)
@@ -62,54 +63,106 @@
 static struct lc15bts_mgr_instance manager = {
        .config_file    = "lc15bts-mgr.cfg",
        .temp = {
-               .supply_limit   = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .supply_temp_limit      = {
+                       .thresh_warn_max        = 80,
+                       .thresh_crit_max        = 85,
+                       .thresh_warn_min        = -40,
                },
-               .soc_limit      = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .soc_temp_limit = {
+                       .thresh_warn_max        = 95,
+                       .thresh_crit_max        = 100,
+                       .thresh_warn_min        = -40,
                },
-               .fpga_limit     = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .fpga_temp_limit        = {
+                       .thresh_warn_max        = 95,
+                       .thresh_crit_max        = 100,
+                       .thresh_warn_min        = -40,
                },
-               .logrf_limit    = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .rmsdet_temp_limit      = {
+                       .thresh_warn_max        = 80,
+                       .thresh_crit_max        = 85,
+                       .thresh_warn_min        = -40,
                },
-               .ocxo_limit     = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .ocxo_temp_limit        = {
+                       .thresh_warn_max        = 80,
+                       .thresh_crit_max        = 85,
+                       .thresh_warn_min        = -40,
                },
-               .tx0_limit      = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .tx0_temp_limit = {
+                       .thresh_warn_max        = 80,
+                       .thresh_crit_max        = 85,
+                       .thresh_warn_min        = -20,
                },
-               .tx1_limit      = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .tx1_temp_limit = {
+                       .thresh_warn_max        = 80,
+                       .thresh_crit_max        = 85,
+                       .thresh_warn_min        = -20,
                },
-               .pa0_limit      = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .pa0_temp_limit = {
+                       .thresh_warn_max        = 80,
+                       .thresh_crit_max        = 85,
+                       .thresh_warn_min        = -40,
                },
-               .pa1_limit      = {
-                       .thresh_warn    = 60,
-                       .thresh_crit    = 78,
+               .pa1_temp_limit = {
+                       .thresh_warn_max        = 80,
+                       .thresh_crit_max        = 85,
+                       .thresh_warn_min        = -40,
+               }
+       },
+       .volt = {
+               .supply_volt_limit = {
+                       .thresh_warn_max        = 30000,
+                       .thresh_crit_max        = 30500,
+                       .thresh_warn_min        = 19000,
+                       .thresh_crit_min        = 17500,
+               }
+       },
+       .pwr = {
+               .supply_pwr_limit = {
+                       .thresh_warn_max        = 110,
+                       .thresh_crit_max        = 120,
                },
+               .pa0_pwr_limit = {
+                       .thresh_warn_max        = 50,
+                       .thresh_crit_max        = 60,
+               },
+               .pa1_pwr_limit = {
+                       .thresh_warn_max        = 50,
+                       .thresh_crit_max        = 60,
+               }
+       },
+       .vswr = {
+               .tx0_vswr_limit = {
+                       .thresh_warn_max        = 3000,
+                       .thresh_crit_max        = 5000,
+               },
+               .tx1_vswr_limit = {
+                       .thresh_warn_max        = 3000,
+                       .thresh_crit_max        = 5000,
+               }
+       },
+       .gps = {
+               .gps_fix_limit = {
+                       .thresh_warn_max        = 7,
+               }
+       },
+       .state = {
+               .action_norm            = SENSOR_ACT_NORM_PA0_ON | 
SENSOR_ACT_NORM_PA1_ON,
                .action_warn            = 0,
-               .action_crit            = TEMP_ACT_PA0_OFF | TEMP_ACT_PA1_OFF,
+               .action_crit            = 0,
+               .action_comb            = 0,
                .state                  = STATE_NORMAL,
        }
 };
 
-static struct osmo_timer_list temp_timer;
-static void check_temp_timer_cb(void *unused)
+static struct osmo_timer_list sensor_timer;
+static void check_sensor_timer_cb(void *unused)
 {
        lc15bts_check_temp(no_rom_write);
-
-       osmo_timer_schedule(&temp_timer, TEMP_TIMER_SECS, 0);
+       lc15bts_check_power(no_rom_write);
+       lc15bts_check_vswr(no_rom_write);
+       osmo_timer_schedule(&sensor_timer, SENSOR_TIMER_SECS, 0);
+       /* TODO checks if 
lc15bts_check_temp/lc15bts_check_power/lc15bts_check_vswr went ok */
 }
 
 static struct osmo_timer_list hours_timer;
@@ -118,6 +171,7 @@
        lc15bts_update_hours(no_rom_write);
 
        osmo_timer_schedule(&hours_timer, HOURS_TIMER_SECS, 0);
+       /* TODO: validates if lc15bts_update_hours went correctly */
 }
 
 static void print_help(void)
@@ -169,6 +223,8 @@
        switch (signal) {
        case SIGINT:
                lc15bts_check_temp(no_rom_write);
+               lc15bts_check_power(no_rom_write);
+               lc15bts_check_vswr(no_rom_write);
                lc15bts_update_hours(no_rom_write);
                exit(0);
                break;
@@ -207,6 +263,12 @@
                .color = "\033[1;37m",
                .enabled = 1, .loglevel = LOGL_INFO,
        },
+       [DSWD] = {
+               .name = "DSWD",
+               .description = "Software Watchdog",
+               .color = "\033[1;37m",
+               .enabled = 1, .loglevel = LOGL_INFO,
+       },
 };
 
 static const struct log_info mgr_log_info = {
@@ -223,7 +285,6 @@
 int main(int argc, char **argv)
 {
        int rc;
-
 
        tall_mgr_ctx = talloc_named_const(NULL, 1, "bts manager");
        msgb_talloc_ctx_init(tall_mgr_ctx, 0);
@@ -253,9 +314,12 @@
                exit(1);
        }
 
+       INIT_LLIST_HEAD(&manager.lc15bts_leds.list);
+       INIT_LLIST_HEAD(&manager.alarms.list);
+
        /* start temperature check timer */
-       temp_timer.cb = check_temp_timer_cb;
-       check_temp_timer_cb(NULL);
+       sensor_timer.cb = check_sensor_timer_cb;
+       check_sensor_timer_cb(NULL);
 
        /* start operational hours timer */
        hours_timer.cb = hours_timer_cb;
@@ -271,14 +335,13 @@
        if (rc < 0) {
                exit(3);
        }
-       
 
        /* handle broadcast messages for ipaccess-find */
        if (lc15bts_mgr_nl_init() != 0)
                exit(3);
 
-       /* Initialize the temperature control */
-       lc15bts_mgr_temp_init(&manager);
+       /* Initialize the sensor control */
+       lc15bts_mgr_sensor_init(&manager);
 
        if (lc15bts_mgr_calib_init(&manager) != 0)
                exit(3);
@@ -290,7 +353,6 @@
                        exit(1);
                }
        }
-
 
        while (1) {
                log_reset_context();
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr.h 
b/src/osmo-bts-litecell15/misc/lc15bts_mgr.h
index 98bd701..4bfbdbc 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_mgr.h
+++ b/src/osmo-bts-litecell15/misc/lc15bts_mgr.h
@@ -9,38 +9,100 @@
 
 #include <stdint.h>
 
+#define LC15BTS_SENSOR_TIMER_DURATION                  60
+#define LC15BTS_PREVENT_TIMER_DURATION                 15 * 60
+#define LC15BTS_PREVENT_TIMER_SHORT_DURATION           5 * 60
+#define LC15BTS_PREVENT_TIMER_NONE                     0
+#define LC15BTS_PREVENT_RETRY                          INT_MAX - 1
+
+enum BLINK_PATTERN {
+       BLINK_PATTERN_POWER_ON = 0,     //hardware set
+       BLINK_PATTERN_INIT,
+       BLINK_PATTERN_NORMAL,
+       BLINK_PATTERN_EXT_LINK_MALFUNC,
+       BLINK_PATTERN_INT_PROC_MALFUNC,
+       BLINK_PATTERN_SUPPLY_VOLT_LOW,
+       BLINK_PATTERN_SUPPLY_VOLT_MIN,
+       BLINK_PATTERN_VSWR_HIGH,
+       BLINK_PATTERN_VSWR_MAX,
+       BLINK_PATTERN_TEMP_HIGH,
+       BLINK_PATTERN_TEMP_MAX,
+       BLINK_PATTERN_SUPPLY_PWR_HIGH,
+       BLINK_PATTERN_SUPPLY_PWR_MAX,
+       BLINK_PATTERN_SUPPLY_PWR_MAX2,
+       BLINK_PATTERN_PA_PWR_HIGH,
+       BLINK_PATTERN_PA_PWR_MAX,
+       BLINK_PATTERN_GPS_FIX_LOST,
+       BLINK_PATTERN_MAX_ITEM
+};
+
+#define BLINK_PATTERN_COMMAND {\
+       "set red; sleep 5.0",\
+       "set orange; sleep 5.0",\
+       "set green; sleep 2.5; set off; sleep 2.5",\
+       "set red; sleep 0.5; set off; sleep 0.5",\
+       "set red; sleep 2.5; set off; sleep 2.5",\
+       "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; 
sleep 0.5; set green; sleep 0.5; set off; sleep 0.5",\
+       "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; 
sleep 0.5; set green; sleep 0.5; set off; sleep 0.5 ",\
+       "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set 
off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\
+       "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set 
off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\
+       "set orange; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set 
off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5 ",\
+       "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; 
sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\
+       "set green; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set 
off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\
+       "set red; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set 
off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\
+       "set orange; sleep 2.5; set off; sleep 0.5; set orange; sleep 0.5; set 
off; sleep 0.5; set red; sleep 0.5; set off; sleep 0.5",\
+       "set green; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; 
sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\
+       "set red; sleep 2.5; set off; sleep 0.5; set red; sleep 0.5; set off; 
sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\
+       "set green; sleep 2.5; set off; sleep 0.5; set green; sleep 0.5; set 
off; sleep 0.5; set orange; sleep 0.5; set off; sleep 0.5",\
+}
+
 enum {
        DTEMP,
        DFW,
        DFIND,
        DCALIB,
+       DSWD,
 };
 
 // TODO NTQD: Define new actions like reducing output power, limit ARM core 
speed, shutdown second TRX/PA, ... 
 enum {
 #if 0
-       TEMP_ACT_PWR_CONTRL     =       0x1,
+       SENSOR_ACT_PWR_CONTRL   =       0x1,
 #endif
-       TEMP_ACT_PA0_OFF        =       0x2,
-       TEMP_ACT_PA1_OFF        =       0x4,
-       TEMP_ACT_BTS_SRV_OFF    =       0x10,
+       SENSOR_ACT_PA0_OFF      =       0x2,
+       SENSOR_ACT_PA1_OFF      =       0x4,
+       SENSOR_ACT_BTS_SRV_OFF  =       0x10,
 };
 
 /* actions only for normal state */
 enum {
 #if 0
-       TEMP_ACT_NORM_PW_CONTRL =       0x1,
+       SENSOR_ACT_NORM_PW_CONTRL       =       0x1,
 #endif
-       TEMP_ACT_NORM_PA0_ON    =       0x2,
-       TEMP_ACT_NORM_PA1_ON    =       0x4,
-       TEMP_ACT_NORM_BTS_SRV_ON=       0x10,
+       SENSOR_ACT_NORM_PA0_ON  =       0x2,
+       SENSOR_ACT_NORM_PA1_ON  =       0x4,
+       SENSOR_ACT_NORM_BTS_SRV_ON=     0x10,
 };
 
-enum lc15bts_temp_state {
+enum lc15bts_sensor_state {
        STATE_NORMAL,           /* Everything is fine */
        STATE_WARNING_HYST,     /* Go back to normal next? */
        STATE_WARNING,          /* We are above the warning threshold */
        STATE_CRITICAL,         /* We have an issue. Wait for below warning */
+};
+
+enum lc15bts_leds_name {
+       LC15BTS_LED_RED = 0,
+       LC15BTS_LED_GREEN,
+       LC15BTS_LED_ORANGE,
+       LC15BTS_LED_OFF,
+       _LC15BTS_LED_MAX
+};
+
+struct lc15bts_led{
+       char *name;
+       char *fullname;
+       char *path;
 };
 
 /**
@@ -49,8 +111,52 @@
  * severe that an action will be taken.
  */
 struct lc15bts_temp_limit {
-       int thresh_warn;
-       int thresh_crit;
+       int thresh_warn_max;
+       int thresh_crit_max;
+       int thresh_warn_min;
+};
+
+struct lc15bts_volt_limit {
+       int thresh_warn_max;
+       int thresh_crit_max;
+       int thresh_warn_min;
+       int thresh_crit_min;
+};
+
+struct lc15bts_pwr_limit {
+       int thresh_warn_max;
+       int thresh_crit_max;
+};
+
+struct lc15bts_vswr_limit {
+       int thresh_warn_max;
+       int thresh_crit_max;
+};
+
+struct lc15bts_gps_fix_limit {
+       int thresh_warn_max;
+};
+
+struct lc15bts_sleep_time {
+       int sleep_sec;
+       int sleep_usec;
+};
+
+struct lc15bts_led_timer {
+       uint8_t idx;
+       struct osmo_timer_list timer;
+       struct lc15bts_sleep_time param;
+};
+
+struct lc15bts_led_timer_list {
+       struct llist_head list;
+       struct lc15bts_led_timer led_timer;
+};
+
+struct lc15bts_preventive_list {
+       struct llist_head list;
+       struct lc15bts_sleep_time param;
+       int action_flag;
 };
 
 enum mgr_vty_node {
@@ -59,55 +165,258 @@
        ACT_NORM_NODE,
        ACT_WARN_NODE,
        ACT_CRIT_NODE,
-       LIMIT_SUPPLY_NODE,
+       LIMIT_SUPPLY_TEMP_NODE,
        LIMIT_SOC_NODE,
        LIMIT_FPGA_NODE,
-       LIMIT_LOGRF_NODE,
+       LIMIT_RMSDET_NODE,
        LIMIT_OCXO_NODE,
-       LIMIT_TX0_NODE,
-       LIMIT_TX1_NODE,
-       LIMIT_PA0_NODE,
-       LIMIT_PA1_NODE,
+       LIMIT_TX0_TEMP_NODE,
+       LIMIT_TX1_TEMP_NODE,
+       LIMIT_PA0_TEMP_NODE,
+       LIMIT_PA1_TEMP_NODE,
+       LIMIT_SUPPLY_VOLT_NODE,
+       LIMIT_TX0_VSWR_NODE,
+       LIMIT_TX1_VSWR_NODE,
+       LIMIT_SUPPLY_PWR_NODE,
+       LIMIT_PA0_PWR_NODE,
+       LIMIT_PA1_PWR_NODE,
+       LIMIT_GPS_FIX_NODE,
+};
+
+enum mgr_vty_limit_type {
+       MGR_LIMIT_TYPE_TEMP = 0,
+       MGR_LIMIT_TYPE_VOLT,
+       MGR_LIMIT_TYPE_VSWR,
+       MGR_LIMIT_TYPE_PWR,
+       _MGR_LIMIT_TYPE_MAX,
 };
 
 struct lc15bts_mgr_instance {
        const char *config_file;
 
        struct {
+               struct lc15bts_temp_limit supply_temp_limit;
+               struct lc15bts_temp_limit soc_temp_limit;
+               struct lc15bts_temp_limit fpga_temp_limit;
+               struct lc15bts_temp_limit rmsdet_temp_limit;
+               struct lc15bts_temp_limit ocxo_temp_limit;
+               struct lc15bts_temp_limit tx0_temp_limit;
+               struct lc15bts_temp_limit tx1_temp_limit;
+               struct lc15bts_temp_limit pa0_temp_limit;
+               struct lc15bts_temp_limit pa1_temp_limit;
+       } temp;
+
+       struct {
+               struct lc15bts_volt_limit supply_volt_limit;
+       } volt;
+
+       struct {
+               struct lc15bts_pwr_limit supply_pwr_limit;
+               struct lc15bts_pwr_limit pa0_pwr_limit;
+               struct lc15bts_pwr_limit pa1_pwr_limit;
+       } pwr;
+
+       struct {
+               struct lc15bts_vswr_limit tx0_vswr_limit;
+               struct lc15bts_vswr_limit tx1_vswr_limit;
+               int tx0_last_vswr;
+               int tx1_last_vswr;
+       } vswr;
+
+       struct {
+               struct lc15bts_gps_fix_limit gps_fix_limit;
+               time_t last_update;
+       } gps;
+
+       struct {
                int action_norm;
                int action_warn;
                int action_crit;
+               int action_comb;
 
-               enum lc15bts_temp_state state;
-
-               struct lc15bts_temp_limit supply_limit;
-               struct lc15bts_temp_limit soc_limit;
-               struct lc15bts_temp_limit fpga_limit;
-               struct lc15bts_temp_limit logrf_limit;
-               struct lc15bts_temp_limit ocxo_limit;
-               struct lc15bts_temp_limit tx0_limit;
-               struct lc15bts_temp_limit tx1_limit;
-               struct lc15bts_temp_limit pa0_limit;
-               struct lc15bts_temp_limit pa1_limit;
-       } temp;
+               enum lc15bts_sensor_state state;
+       } state;
 
        struct {
                int state;
                int calib_from_loop;
                struct osmo_timer_list calib_timeout;
        } calib;
+
+       struct {
+               int state;
+               int swd_from_loop;
+               unsigned long long int swd_events;
+               unsigned long long int swd_events_cache;
+               unsigned long long int swd_eventmasks;
+               int num_events;
+               struct osmo_timer_list swd_timeout;
+       } swd;
+
+       struct {
+               uint8_t led_idx;
+               uint8_t last_pattern_id;
+               uint8_t active_timer;
+               struct llist_head list;
+       } lc15bts_leds;
+
+       struct {
+               int is_up;
+               uint32_t last_seqno;
+               struct osmo_timer_list recon_timer;
+               struct ipa_client_conn *bts_conn;
+               uint32_t crit_flags;
+               uint32_t warn_flags;
+       } lc15bts_ctrl;
+
+       struct lc15bts_alarms {
+               int temp_high;
+               int temp_max;
+               int supply_low;
+               int supply_min;
+               int vswr_high;
+               int vswr_max;
+               int supply_pwr_high;
+               int supply_pwr_max;
+               int supply_pwr_max2;
+               int pa_pwr_high;
+               int pa_pwr_max;
+               int gps_fix_lost;
+               struct llist_head list;
+               struct osmo_timer_list preventive_timer;
+               int preventive_duration;
+               int preventive_retry;
+       } alarms;
+
+};
+
+enum lc15bts_mgr_fail_evt_rep_crit_sig {
+       /* Critical alarms */
+       S_MGR_TEMP_SUPPLY_CRIT_MAX_ALARM                        = (1 << 0),
+       S_MGR_TEMP_SOC_CRIT_MAX_ALARM                           = (1 << 1),
+       S_MGR_TEMP_FPGA_CRIT_MAX_ALARM                          = (1 << 2),
+       S_MGR_TEMP_RMS_DET_CRIT_MAX_ALARM                       = (1 << 3),
+       S_MGR_TEMP_OCXO_CRIT_MAX_ALARM                          = (1 << 4),
+       S_MGR_TEMP_TRX0_CRIT_MAX_ALARM                          = (1 << 5),
+       S_MGR_TEMP_TRX1_CRIT_MAX_ALARM                          = (1 << 6),
+       S_MGR_TEMP_PA0_CRIT_MAX_ALARM                           = (1 << 7),
+       S_MGR_TEMP_PA1_CRIT_MAX_ALARM                           = (1 << 8),
+       S_MGR_SUPPLY_CRIT_MAX_ALARM                             = (1 << 9),
+       S_MGR_SUPPLY_CRIT_MIN_ALARM                             = (1 << 10),
+       S_MGR_VSWR0_CRIT_MAX_ALARM                              = (1 << 11),
+       S_MGR_VSWR1_CRIT_MAX_ALARM                              = (1 << 12),
+       S_MGR_PWR_SUPPLY_CRIT_MAX_ALARM                         = (1 << 13),
+       S_MGR_PWR_PA0_CRIT_MAX_ALARM                            = (1 << 14),
+       S_MGR_PWR_PA1_CRIT_MAX_ALARM                            = (1 << 15),
+       _S_MGR_CRIT_ALARM_MAX,
+};
+
+enum lc15bts_mgr_fail_evt_rep_warn_sig {
+       /* Warning alarms */
+       S_MGR_TEMP_SUPPLY_WARN_MIN_ALARM                        = (1 << 0),
+       S_MGR_TEMP_SUPPLY_WARN_MAX_ALARM                        = (1 << 2),
+       S_MGR_TEMP_SOC_WARN_MIN_ALARM                           = (1 << 3),
+       S_MGR_TEMP_SOC_WARN_MAX_ALARM                           = (1 << 4),
+       S_MGR_TEMP_FPGA_WARN_MIN_ALARM                          = (1 << 5),
+       S_MGR_TEMP_FPGA_WARN_MAX_ALARM                          = (1 << 6),
+       S_MGR_TEMP_RMS_DET_WARN_MIN_ALARM                       = (1 << 7),
+       S_MGR_TEMP_RMS_DET_WARN_MAX_ALARM                       = (1 << 8),
+       S_MGR_TEMP_OCXO_WARN_MIN_ALARM                          = (1 << 9),
+       S_MGR_TEMP_OCXO_WARN_MAX_ALARM                          = (1 << 10),
+       S_MGR_TEMP_TRX0_WARN_MIN_ALARM                          = (1 << 11),
+       S_MGR_TEMP_TRX0_WARN_MAX_ALARM                          = (1 << 12),
+       S_MGR_TEMP_TRX1_WARN_MIN_ALARM                          = (1 << 13),
+       S_MGR_TEMP_TRX1_WARN_MAX_ALARM                          = (1 << 14),
+       S_MGR_TEMP_PA0_WARN_MIN_ALARM                           = (1 << 15),
+       S_MGR_TEMP_PA0_WARN_MAX_ALARM                           = (1 << 16),
+       S_MGR_TEMP_PA1_WARN_MIN_ALARM                           = (1 << 17),
+       S_MGR_TEMP_PA1_WARN_MAX_ALARM                           = (1 << 18),
+       S_MGR_SUPPLY_WARN_MIN_ALARM                             = (1 << 19),
+       S_MGR_SUPPLY_WARN_MAX_ALARM                             = (1 << 20),
+       S_MGR_VSWR0_WARN_MAX_ALARM                              = (1 << 21),
+       S_MGR_VSWR1_WARN_MAX_ALARM                              = (1 << 22),
+       S_MGR_PWR_SUPPLY_WARN_MAX_ALARM                         = (1 << 23),
+       S_MGR_PWR_PA0_WARN_MAX_ALARM                            = (1 << 24),
+       S_MGR_PWR_PA1_WARN_MAX_ALARM                            = (1 << 25),
+       S_MGR_GPS_FIX_WARN_ALARM                                = (1 << 26),
+       _S_MGR_WARN_ALARM_MAX,
+};
+
+enum lc15bts_mgr_failure_event_causes {
+       /* Critical causes */
+       NM_EVT_CAUSE_CRIT_TEMP_SUPPLY_MAX_FAIL  = 0x4100,
+       NM_EVT_CAUSE_CRIT_TEMP_FPGA_MAX_FAIL    = 0x4101,
+       NM_EVT_CAUSE_CRIT_TEMP_SOC_MAX_FAIL     = 0x4102,
+       NM_EVT_CAUSE_CRIT_TEMP_RMS_DET_MAX_FAIL = 0x4103,
+       NM_EVT_CAUSE_CRIT_TEMP_OCXO_MAX_FAIL    = 0x4104,
+       NM_EVT_CAUSE_CRIT_TEMP_TRX0_MAX_FAIL    = 0x4105,
+       NM_EVT_CAUSE_CRIT_TEMP_TRX1_MAX_FAIL    = 0x4106,
+       NM_EVT_CAUSE_CRIT_TEMP_PA0_MAX_FAIL     = 0x4107,
+       NM_EVT_CAUSE_CRIT_TEMP_PA1_MAX_FAIL     = 0x4108,
+       NM_EVT_CAUSE_CRIT_SUPPLY_MAX_FAIL       = 0x4109,
+       NM_EVT_CAUSE_CRIT_SUPPLY_MIN_FAIL       = 0x410A,
+       NM_EVT_CAUSE_CRIT_VSWR0_MAX_FAIL        = 0x410B,
+       NM_EVT_CAUSE_CRIT_VSWR1_MAX_FAIL        = 0x410C,
+       NM_EVT_CAUSE_CRIT_PWR_SUPPLY_MAX_FAIL   = 0x410D,
+       NM_EVT_CAUSE_CRIT_PWR_PA0_MAX_FAIL      = 0x410E,
+       NM_EVT_CAUSE_CRIT_PWR_PA1_MAX_FAIL      = 0x410F,
+       /* Warning causes */
+       NM_EVT_CAUSE_WARN_TEMP_SUPPLY_LOW_FAIL  = 0x4400,
+       NM_EVT_CAUSE_WARN_TEMP_SUPPLY_HIGH_FAIL = 0x4401,
+       NM_EVT_CAUSE_WARN_TEMP_FPGA_LOW_FAIL    = 0x4402,
+       NM_EVT_CAUSE_WARN_TEMP_FPGA_HIGH_FAIL   = 0x4403,
+       NM_EVT_CAUSE_WARN_TEMP_SOC_LOW_FAIL     = 0x4404,
+       NM_EVT_CAUSE_WARN_TEMP_SOC_HIGH_FAIL    = 0x4405,
+       NM_EVT_CAUSE_WARN_TEMP_RMS_DET_LOW_FAIL = 0x4406,
+       NM_EVT_CAUSE_WARN_TEMP_RMS_DET_HIGH_FAIL= 0x4407,
+       NM_EVT_CAUSE_WARN_TEMP_OCXO_LOW_FAIL    = 0x4408,
+       NM_EVT_CAUSE_WARN_TEMP_OCXO_HIGH_FAIL   = 0x4409,
+       NM_EVT_CAUSE_WARN_TEMP_TRX0_LOW_FAIL    = 0x440A,
+       NM_EVT_CAUSE_WARN_TEMP_TRX0_HIGH_FAIL   = 0x440B,
+       NM_EVT_CAUSE_WARN_TEMP_TRX1_LOW_FAIL    = 0x440C,
+       NM_EVT_CAUSE_WARN_TEMP_TRX1_HIGH_FAIL   = 0x440D,
+       NM_EVT_CAUSE_WARN_TEMP_PA0_LOW_FAIL     = 0x440E,
+       NM_EVT_CAUSE_WARN_TEMP_PA0_HIGH_FAIL    = 0x440F,
+       NM_EVT_CAUSE_WARN_TEMP_PA1_LOW_FAIL     = 0x4410,
+       NM_EVT_CAUSE_WARN_TEMP_PA1_HIGH_FAIL    = 0x4411,
+       NM_EVT_CAUSE_WARN_SUPPLY_LOW_FAIL       = 0x4412,
+       NM_EVT_CAUSE_WARN_SUPPLY_HIGH_FAIL      = 0x4413,
+       NM_EVT_CAUSE_WARN_VSWR0_HIGH_FAIL       = 0x4414,
+       NM_EVT_CAUSE_WANR_VSWR1_HIGH_FAIL       = 0x4415,
+       NM_EVT_CAUSE_WARN_PWR_SUPPLY_HIGH_FAIL  = 0x4416,
+       NM_EVT_CAUSE_WARN_PWR_PA0_HIGH_FAIL     = 0x4417,
+       NM_EVT_CAUSE_WARN_PWR_PA1_HIGH_FAIL     = 0x4418,
+       NM_EVT_CAUSE_WARN_GPS_FIX_FAIL          = 0x4419,
+};
+
+/* This defines the list of notification events for systemd service watchdog.
+   all these events must be notified in a certain service defined timeslot
+   or the service (this app) would be restarted (only if related systemd 
service
+   unit file has WatchdogSec!=0).
+   WARNING: swd events must begin with event 0. Last events must be
+   SWD_LAST (max 64 events in this list).
+*/
+enum mgr_swd_events {
+       SWD_MAINLOOP = 0,
+       SWD_CHECK_SENSOR,
+       SWD_UPDATE_HOURS,
+       SWD_CHECK_TEMP_SENSOR,
+       SWD_CHECK_LED_CTRL,
+       SWD_CHECK_CALIB,
+       SWD_CHECK_BTS_CONNECTION,
+       SWD_LAST
 };
 
 int lc15bts_mgr_vty_init(void);
 int lc15bts_mgr_parse_config(struct lc15bts_mgr_instance *mgr);
 int lc15bts_mgr_nl_init(void);
-int lc15bts_mgr_temp_init(struct lc15bts_mgr_instance *mgr);
-const char *lc15bts_mgr_temp_get_state(enum lc15bts_temp_state state);
-
+int lc15bts_mgr_sensor_init(struct lc15bts_mgr_instance *mgr);
+const char *lc15bts_mgr_sensor_get_state(enum lc15bts_sensor_state state);
 
 int lc15bts_mgr_calib_init(struct lc15bts_mgr_instance *mgr);
+int lc15bts_mgr_control_init(struct lc15bts_mgr_instance *mgr);
 int lc15bts_mgr_calib_run(struct lc15bts_mgr_instance *mgr);
-
+void lc15bts_mgr_dispatch_alarm(struct lc15bts_mgr_instance *mgr, const int 
cause, const char *key, const char *text);
 extern void *tall_mgr_ctx;
 
 #endif
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c 
b/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c
index 042fc87..9d2dfec 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_mgr_temp.c
@@ -22,19 +22,22 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-
+#include <inttypes.h>
 #include "misc/lc15bts_mgr.h"
 #include "misc/lc15bts_misc.h"
 #include "misc/lc15bts_temp.h"
 #include "misc/lc15bts_power.h"
+#include "misc/lc15bts_led.h"
+#include "limits.h"
 
 #include <osmo-bts/logging.h>
 
 #include <osmocom/core/timer.h>
 #include <osmocom/core/utils.h>
+#include <osmocom/core/linuxlist.h>
 
-static struct lc15bts_mgr_instance *s_mgr;
-static struct osmo_timer_list temp_ctrl_timer;
+struct lc15bts_mgr_instance *s_mgr;
+static struct osmo_timer_list sensor_ctrl_timer;
 
 static const struct value_string state_names[] = {
        { STATE_NORMAL,                 "NORMAL" },
@@ -44,12 +47,12 @@
        { 0, NULL }
 };
 
-const char *lc15bts_mgr_temp_get_state(enum lc15bts_temp_state state)
+const char *lc15bts_mgr_sensor_get_state(enum lc15bts_sensor_state state)
 {
        return get_value_string(state_names, state);
 }
 
-static int next_state(enum lc15bts_temp_state current_state, int critical, int 
warning)
+static int next_state(enum lc15bts_sensor_state current_state, int critical, 
int warning)
 {
        int next_state = -1;
        switch (current_state) {
@@ -85,7 +88,7 @@
 static void handle_normal_actions(int actions)
 {
        /* switch on the PA */
-       if (actions & TEMP_ACT_NORM_PA0_ON) {
+       if (actions & SENSOR_ACT_NORM_PA0_ON) {
                if (lc15bts_power_set(LC15BTS_POWER_PA0, 1) != 0) {
                        LOGP(DTEMP, LOGL_ERROR,
                                "Failed to switch on the PA #0\n");
@@ -95,7 +98,7 @@
                }
        }
 
-       if (actions & TEMP_ACT_NORM_PA1_ON) {
+       if (actions & SENSOR_ACT_NORM_PA1_ON) {
                if (lc15bts_power_set(LC15BTS_POWER_PA1, 1) != 0) {
                        LOGP(DTEMP, LOGL_ERROR,
                                "Failed to switch on the PA #1\n");
@@ -105,7 +108,7 @@
                }
        }
 
-       if (actions & TEMP_ACT_NORM_BTS_SRV_ON) {
+       if (actions & SENSOR_ACT_NORM_BTS_SRV_ON) {
                LOGP(DTEMP, LOGL_NOTICE,
                "Going to switch on the BTS service\n");
                /*
@@ -120,7 +123,7 @@
 static void handle_actions(int actions)
 {
        /* switch off the PA */
-       if (actions & TEMP_ACT_PA1_OFF) {
+       if (actions & SENSOR_ACT_PA1_OFF) {
                if (lc15bts_power_set(LC15BTS_POWER_PA1, 0) != 0) {
                        LOGP(DTEMP, LOGL_ERROR,
                                "Failed to switch off the PA #1. Stop BTS?\n");
@@ -130,7 +133,7 @@
                }
        }
 
-       if (actions & TEMP_ACT_PA0_OFF) {
+       if (actions & SENSOR_ACT_PA0_OFF) {
                if (lc15bts_power_set(LC15BTS_POWER_PA0, 0) != 0) {
                        LOGP(DTEMP, LOGL_ERROR,
                                "Failed to switch off the PA #0. Stop BTS?\n");
@@ -140,7 +143,7 @@
                }
        }
 
-       if (actions & TEMP_ACT_BTS_SRV_OFF) {
+       if (actions & SENSOR_ACT_BTS_SRV_OFF) {
                LOGP(DTEMP, LOGL_NOTICE,
                        "Going to switch off the BTS service\n");
                /*
@@ -161,36 +164,36 @@
  */
 static void execute_normal_act(struct lc15bts_mgr_instance *manager)
 {
-       LOGP(DTEMP, LOGL_NOTICE, "System is back to normal temperature.\n");
-       handle_normal_actions(manager->temp.action_norm);
+       LOGP(DTEMP, LOGL_NOTICE, "System is back to normal state.\n");
+       handle_normal_actions(manager->state.action_norm);
 }
 
 static void execute_warning_act(struct lc15bts_mgr_instance *manager)
 {
-       LOGP(DTEMP, LOGL_NOTICE, "System has reached temperature warning.\n");
-       handle_actions(manager->temp.action_warn);
+       LOGP(DTEMP, LOGL_NOTICE, "System has reached warning state.\n");
+       handle_actions(manager->state.action_warn);
 }
 
 static void execute_critical_act(struct lc15bts_mgr_instance *manager)
 {
        LOGP(DTEMP, LOGL_NOTICE, "System has reached critical warning.\n");
-       handle_actions(manager->temp.action_crit);
+       handle_actions(manager->state.action_crit);
 }
 
-static void lc15bts_mgr_temp_handle(struct lc15bts_mgr_instance *manager,
+static void lc15bts_mgr_sensor_handle(struct lc15bts_mgr_instance *manager,
                        int critical, int warning)
 {
-       int new_state = next_state(manager->temp.state, critical, warning);
+       int new_state = next_state(manager->state.state, critical, warning);
 
        /* Nothing changed */
        if (new_state < 0)
                return;
 
        LOGP(DTEMP, LOGL_NOTICE, "Moving from state %s to %s.\n",
-               get_value_string(state_names, manager->temp.state),
+               get_value_string(state_names, manager->state.state),
                get_value_string(state_names, new_state));
-       manager->temp.state = new_state;
-       switch (manager->temp.state) {
+       manager->state.state = new_state;
+       switch (manager->state.state) {
        case STATE_NORMAL:
                execute_normal_act(manager);
                break;
@@ -206,163 +209,168 @@
        };
 } 
 
-static void temp_ctrl_check()
+static void sensor_ctrl_check(struct lc15bts_mgr_instance *mgr)
 {
        int rc;
+       int temp = 0;
        int warn_thresh_passed = 0;
        int crit_thresh_passed = 0;
 
        LOGP(DTEMP, LOGL_DEBUG, "Going to check the temperature.\n");
 
        /* Read the current supply temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_SUPPLY);
+       rc = lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the supply temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.supply_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.supply_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.supply_limit.thresh_crit)
+               if (temp > mgr->temp.supply_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "Supply temperature is: %d\n", temp);
        }
 
        /* Read the current SoC temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_SOC);
+       rc = lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the SoC temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.soc_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.soc_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.soc_limit.thresh_crit)
+               if (temp > mgr->temp.soc_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "SoC temperature is: %d\n", temp);
        }
 
        /* Read the current fpga temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_FPGA);
+       rc = lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the fpga temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.fpga_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.fpga_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.fpga_limit.thresh_crit)
+               if (temp > mgr->temp.fpga_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "FPGA temperature is: %d\n", temp);
        }
 
-       /* Read the current RF log detector temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_LOGRF);
+       /* Read the current RMS detector temperature */
+       rc = lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
-                       "Failed to read the RF log detector temperature. 
rc=%d\n", rc);
+                       "Failed to read the RMS detector temperature. rc=%d\n", 
rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.logrf_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.rmsdet_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.logrf_limit.thresh_crit)
+               if (temp > mgr->temp.rmsdet_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
-               LOGP(DTEMP, LOGL_DEBUG, "RF log detector temperature is: %d\n", 
temp);
+               LOGP(DTEMP, LOGL_DEBUG, "RMS detector temperature is: %d\n", 
temp);
        }
 
        /* Read the current OCXO temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_OCXO);
+       rc = lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the OCXO temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.ocxo_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.ocxo_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.ocxo_limit.thresh_crit)
+               if (temp > mgr->temp.ocxo_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "OCXO temperature is: %d\n", temp);
        }
 
-       /* Read the current TX #1 temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_TX0);
+       /* Read the current TX #0 temperature */
+       rc = lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the TX #0 temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.tx0_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.tx0_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.tx0_limit.thresh_crit)
+               if (temp > mgr->temp.tx0_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "TX #0 temperature is: %d\n", temp);
        }
 
-       /* Read the current TX #2 temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_TX1);
+       /* Read the current TX #1 temperature */
+       rc = lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the TX #1 temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.tx1_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.tx1_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.tx1_limit.thresh_crit)
+               if (temp > mgr->temp.tx1_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "TX #1 temperature is: %d\n", temp);
        }
 
-       /* Read the current PA #1 temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_PA0);
+       /* Read the current PA #0 temperature */
+       rc = lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the PA #0 temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.pa0_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.pa0_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.pa0_limit.thresh_crit)
+               if (temp > mgr->temp.pa0_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "PA #0 temperature is: %d\n", temp);
        }
 
-       /* Read the current PA #2 temperature */
-       rc = lc15bts_temp_get(LC15BTS_TEMP_PA1);
+       /* Read the current PA #1 temperature */
+       rc = lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp);
        if (rc < 0) {
                LOGP(DTEMP, LOGL_ERROR,
                        "Failed to read the PA #1 temperature. rc=%d\n", rc);
                warn_thresh_passed = crit_thresh_passed = 1;
        } else {
-               int temp = rc / 1000;
-               if (temp > s_mgr->temp.pa1_limit.thresh_warn)
+               temp = temp / 1000;
+               if (temp > mgr->temp.pa1_temp_limit.thresh_warn_max)
                        warn_thresh_passed = 1;
-               if (temp > s_mgr->temp.pa1_limit.thresh_crit)
+               if (temp > mgr->temp.pa1_temp_limit.thresh_crit_max)
                        crit_thresh_passed = 1;
                LOGP(DTEMP, LOGL_DEBUG, "PA #1 temperature is: %d\n", temp);
        }
 
-       lc15bts_mgr_temp_handle(s_mgr, crit_thresh_passed, warn_thresh_passed); 
+       lc15bts_mgr_sensor_handle(mgr, crit_thresh_passed, warn_thresh_passed);
 }
 
-static void temp_ctrl_check_cb(void *unused)
+static void sensor_ctrl_check_cb(void *_data)
 {
-       temp_ctrl_check();
-       /* Check every two minutes? XXX make it configurable! */
-       osmo_timer_schedule(&temp_ctrl_timer, 2 * 60, 0);
+       struct lc15bts_mgr_instance *mgr = _data;
+       sensor_ctrl_check(mgr);
+       /* Check every minute? XXX make it configurable! */
+       osmo_timer_schedule(&sensor_ctrl_timer, LC15BTS_SENSOR_TIMER_DURATION, 
0);
+       LOGP(DTEMP, LOGL_DEBUG,"Check sensors timer expired\n");
+       /* TODO: do we want to notify if some sensors could not be read? */
 }
 
-int lc15bts_mgr_temp_init(struct lc15bts_mgr_instance *mgr)
+int lc15bts_mgr_sensor_init(struct lc15bts_mgr_instance *mgr)
 {
        s_mgr = mgr;
-       temp_ctrl_timer.cb = temp_ctrl_check_cb;
-       temp_ctrl_check_cb(NULL);
+       sensor_ctrl_timer.cb = sensor_ctrl_check_cb;
+       sensor_ctrl_timer.data = s_mgr;
+       sensor_ctrl_check_cb(s_mgr);
        return 0;
 }
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c 
b/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c
index 280c9c7..b96349e 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_mgr_vty.c
@@ -32,6 +32,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <inttypes.h>
 
 #include <osmocom/vty/vty.h>
 #include <osmocom/vty/command.h>
@@ -43,6 +44,7 @@
 #include "lc15bts_mgr.h"
 #include "lc15bts_temp.h"
 #include "lc15bts_power.h"
+#include "lc15bts_led.h"
 #include "btsconfig.h"
 
 static struct lc15bts_mgr_instance *s_mgr;
@@ -64,15 +66,21 @@
        case ACT_NORM_NODE:
        case ACT_WARN_NODE:
        case ACT_CRIT_NODE:
-       case LIMIT_SUPPLY_NODE:
+       case LIMIT_SUPPLY_TEMP_NODE:
        case LIMIT_SOC_NODE:
        case LIMIT_FPGA_NODE:
-       case LIMIT_LOGRF_NODE:
+       case LIMIT_RMSDET_NODE:
        case LIMIT_OCXO_NODE:
-       case LIMIT_TX0_NODE:
-       case LIMIT_TX1_NODE:
-       case LIMIT_PA0_NODE:
-       case LIMIT_PA1_NODE:
+       case LIMIT_TX0_TEMP_NODE:
+       case LIMIT_TX1_TEMP_NODE:
+       case LIMIT_PA0_TEMP_NODE:
+       case LIMIT_PA1_TEMP_NODE:
+       case LIMIT_SUPPLY_VOLT_NODE:
+       case LIMIT_TX0_VSWR_NODE:
+       case LIMIT_TX1_VSWR_NODE:
+       case LIMIT_SUPPLY_PWR_NODE:
+       case LIMIT_PA0_PWR_NODE:
+       case LIMIT_PA1_PWR_NODE:
                vty->node = MGR_NODE;
                break;
        default:
@@ -88,15 +96,21 @@
        case ACT_NORM_NODE:
        case ACT_WARN_NODE:
        case ACT_CRIT_NODE:
-       case LIMIT_SUPPLY_NODE:
+       case LIMIT_SUPPLY_TEMP_NODE:
        case LIMIT_SOC_NODE:
        case LIMIT_FPGA_NODE:
-       case LIMIT_LOGRF_NODE:
+       case LIMIT_RMSDET_NODE:
        case LIMIT_OCXO_NODE:
-       case LIMIT_TX0_NODE:
-       case LIMIT_TX1_NODE:
-       case LIMIT_PA0_NODE:
-       case LIMIT_PA1_NODE:
+       case LIMIT_TX0_TEMP_NODE:
+       case LIMIT_TX1_TEMP_NODE:
+       case LIMIT_PA0_TEMP_NODE:
+       case LIMIT_PA1_TEMP_NODE:
+       case LIMIT_SUPPLY_VOLT_NODE:
+       case LIMIT_TX0_VSWR_NODE:
+       case LIMIT_TX1_VSWR_NODE:
+       case LIMIT_SUPPLY_PWR_NODE:
+       case LIMIT_PA0_PWR_NODE:
+       case LIMIT_PA1_PWR_NODE:
                return 1;
        default:
                return 0;
@@ -122,25 +136,25 @@
 
 static struct cmd_node act_norm_node = {
        ACT_NORM_NODE,
-       "%s(action-normal)# ",
+       "%s(actions-normal)# ",
        1,
 };
 
 static struct cmd_node act_warn_node = {
        ACT_WARN_NODE,
-       "%s(action-warn)# ",
+       "%s(actions-warn)# ",
        1,
 };
 
 static struct cmd_node act_crit_node = {
        ACT_CRIT_NODE,
-       "%s(action-critical)# ",
+       "%s(actions-critical)# ",
        1,
 };
 
-static struct cmd_node limit_supply_node = {
-       LIMIT_SUPPLY_NODE,
-       "%s(limit-supply)# ",
+static struct cmd_node limit_supply_temp_node = {
+       LIMIT_SUPPLY_TEMP_NODE,
+       "%s(limit-supply-temp)# ",
        1,
 };
 
@@ -156,9 +170,9 @@
        1,
 };
 
-static struct cmd_node limit_logrf_node = {
-       LIMIT_LOGRF_NODE,
-       "%s(limit-logrf)# ",
+static struct cmd_node limit_rmsdet_node = {
+       LIMIT_RMSDET_NODE,
+       "%s(limit-rmsdet)# ",
        1,
 };
 
@@ -168,24 +182,60 @@
        1,
 };
 
-static struct cmd_node limit_tx0_node = {
-       LIMIT_TX0_NODE,
-       "%s(limit-tx0)# ",
+static struct cmd_node limit_tx0_temp_node = {
+       LIMIT_TX0_TEMP_NODE,
+       "%s(limit-tx0-temp)# ",
        1,
 };
-static struct cmd_node limit_tx1_node = {
-       LIMIT_TX1_NODE,
-       "%s(limit-tx1)# ",
+static struct cmd_node limit_tx1_temp_node = {
+       LIMIT_TX1_TEMP_NODE,
+       "%s(limit-tx1-temp)# ",
        1,
 };
-static struct cmd_node limit_pa0_node = {
-       LIMIT_PA0_NODE,
-       "%s(limit-pa0)# ",
+static struct cmd_node limit_pa0_temp_node = {
+       LIMIT_PA0_TEMP_NODE,
+       "%s(limit-pa0-temp)# ",
        1,
 };
-static struct cmd_node limit_pa1_node = {
-       LIMIT_PA1_NODE,
-       "%s(limit-pa1)# ",
+static struct cmd_node limit_pa1_temp_node = {
+       LIMIT_PA1_TEMP_NODE,
+       "%s(limit-pa1-temp)# ",
+       1,
+};
+static struct cmd_node limit_supply_volt_node = {
+       LIMIT_SUPPLY_VOLT_NODE,
+       "%s(limit-supply-volt)# ",
+       1,
+};
+static struct cmd_node limit_tx0_vswr_node = {
+       LIMIT_TX0_VSWR_NODE,
+       "%s(limit-tx0-vswr)# ",
+       1,
+};
+static struct cmd_node limit_tx1_vswr_node = {
+       LIMIT_TX1_VSWR_NODE,
+       "%s(limit-tx1-vswr)# ",
+       1,
+};
+static struct cmd_node limit_supply_pwr_node = {
+       LIMIT_SUPPLY_PWR_NODE,
+       "%s(limit-supply-pwr)# ",
+       1,
+};
+static struct cmd_node limit_pa0_pwr_node = {
+       LIMIT_PA0_PWR_NODE,
+       "%s(limit-pa0-pwr)# ",
+       1,
+};
+static struct cmd_node limit_pa1_pwr_node = {
+       LIMIT_PA1_PWR_NODE,
+       "%s(limit-pa1-pwr)# ",
+       1,
+};
+
+static struct cmd_node limit_gps_fix_node = {
+       LIMIT_GPS_FIX_NODE,
+       "%s(limit-gps-fix)# ",
        1,
 };
 
@@ -197,55 +247,68 @@
        return CMD_SUCCESS;
 }
 
-static void write_temp_limit(struct vty *vty, const char *name,
-                               struct lc15bts_temp_limit *limit)
+static void write_volt_limit(struct vty *vty, const char *name,
+                               struct lc15bts_volt_limit *limit)
 {
        vty_out(vty, " %s%s", name, VTY_NEWLINE);
-       vty_out(vty, "   threshold warning %d%s",
-               limit->thresh_warn, VTY_NEWLINE);
-       vty_out(vty, "   threshold critical %d%s",
-               limit->thresh_crit, VTY_NEWLINE);
+       vty_out(vty, "   threshold warning min %d%s",
+               limit->thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "   threshold critical min %d%s",
+               limit->thresh_crit_min, VTY_NEWLINE);
+}
+
+static void write_vswr_limit(struct vty *vty, const char *name,
+                               struct lc15bts_vswr_limit *limit)
+{
+       vty_out(vty, " %s%s", name, VTY_NEWLINE);
+       vty_out(vty, "   threshold warning max %d%s",
+               limit->thresh_warn_max, VTY_NEWLINE);
+}
+
+static void write_pwr_limit(struct vty *vty, const char *name,
+                               struct lc15bts_pwr_limit *limit)
+{
+       vty_out(vty, " %s%s", name, VTY_NEWLINE);
+       vty_out(vty, "   threshold warning max %d%s",
+               limit->thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "   threshold critical max %d%s",
+               limit->thresh_crit_max, VTY_NEWLINE);
 }
 
 static void write_norm_action(struct vty *vty, const char *name, int actions)
 {
        vty_out(vty, " %s%s", name, VTY_NEWLINE);
        vty_out(vty, "  %spa0-on%s",
-               (actions & TEMP_ACT_NORM_PA0_ON) ? "" : "no ", VTY_NEWLINE);
+               (actions & SENSOR_ACT_NORM_PA0_ON) ? "" : "no ", VTY_NEWLINE);
        vty_out(vty, "  %spa1-on%s",
-               (actions & TEMP_ACT_NORM_PA1_ON) ? "" : "no ", VTY_NEWLINE);
+               (actions & SENSOR_ACT_NORM_PA1_ON) ? "" : "no ", VTY_NEWLINE);
        vty_out(vty, "  %sbts-service-on%s",
-               (actions & TEMP_ACT_NORM_BTS_SRV_ON) ? "" : "no ", VTY_NEWLINE);
+               (actions & SENSOR_ACT_NORM_BTS_SRV_ON) ? "" : "no ", 
VTY_NEWLINE);
 }
 
 static void write_action(struct vty *vty, const char *name, int actions)
 {
        vty_out(vty, " %s%s", name, VTY_NEWLINE);
        vty_out(vty, "  %spa0-off%s",
-               (actions & TEMP_ACT_PA0_OFF) ? "" : "no ", VTY_NEWLINE);
+               (actions & SENSOR_ACT_PA0_OFF) ? "" : "no ", VTY_NEWLINE);
        vty_out(vty, "  %spa1-off%s",
-               (actions & TEMP_ACT_PA1_OFF) ? "" : "no ", VTY_NEWLINE);
+               (actions & SENSOR_ACT_PA1_OFF) ? "" : "no ", VTY_NEWLINE);
        vty_out(vty, "  %sbts-service-off%s",
-               (actions & TEMP_ACT_BTS_SRV_OFF) ? "" : "no ", VTY_NEWLINE);
+               (actions & SENSOR_ACT_BTS_SRV_OFF) ? "" : "no ", VTY_NEWLINE);
 }
 
 static int config_write_mgr(struct vty *vty)
 {
        vty_out(vty, "lc15bts-mgr%s", VTY_NEWLINE);
 
-       write_temp_limit(vty, "limits supply", &s_mgr->temp.supply_limit);
-       write_temp_limit(vty, "limits soc", &s_mgr->temp.soc_limit);
-       write_temp_limit(vty, "limits fpga", &s_mgr->temp.fpga_limit);
-       write_temp_limit(vty, "limits logrf", &s_mgr->temp.logrf_limit);
-       write_temp_limit(vty, "limits ocxo", &s_mgr->temp.ocxo_limit);
-       write_temp_limit(vty, "limits tx0", &s_mgr->temp.tx0_limit);
-       write_temp_limit(vty, "limits tx1", &s_mgr->temp.tx1_limit);
-       write_temp_limit(vty, "limits pa0", &s_mgr->temp.pa0_limit);
-       write_temp_limit(vty, "limits pa1", &s_mgr->temp.pa1_limit);
+       write_volt_limit(vty, "limits supply_volt", 
&s_mgr->volt.supply_volt_limit);
+       write_pwr_limit(vty, "limits supply_pwr", &s_mgr->pwr.supply_pwr_limit);
+       write_vswr_limit(vty, "limits tx0_vswr", &s_mgr->vswr.tx0_vswr_limit);
+       write_vswr_limit(vty, "limits tx1_vswr", &s_mgr->vswr.tx1_vswr_limit);
 
-       write_norm_action(vty, "actions normal", s_mgr->temp.action_norm);
-       write_action(vty, "actions warn", s_mgr->temp.action_warn);
-       write_action(vty, "actions critical", s_mgr->temp.action_crit);
+       write_norm_action(vty, "actions normal", s_mgr->state.action_norm);
+       write_action(vty, "actions warn", s_mgr->state.action_warn);
+       write_action(vty, "actions critical", s_mgr->state.action_crit);
 
        return CMD_SUCCESS;
 }
@@ -255,7 +318,7 @@
        return CMD_SUCCESS;
 }
 
-#define CFG_LIMIT(name, expl, switch_to, variable)                     \
+#define CFG_LIMIT_TEMP(name, expl, switch_to, variable)                        
\
 DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd,                                
\
        "limits " #name,                                                \
        "Configure Limits\n" expl)                                      \
@@ -265,32 +328,123 @@
        return CMD_SUCCESS;                                             \
 }
 
-CFG_LIMIT(supply, "SUPPLY\n", LIMIT_SUPPLY_NODE, supply_limit)
-CFG_LIMIT(soc, "SOC\n", LIMIT_SOC_NODE, soc_limit)
-CFG_LIMIT(fpga, "FPGA\n", LIMIT_FPGA_NODE, fpga_limit)
-CFG_LIMIT(logrf, "LOGRF\n", LIMIT_LOGRF_NODE, logrf_limit)
-CFG_LIMIT(ocxo, "OCXO\n", LIMIT_OCXO_NODE, ocxo_limit)
-CFG_LIMIT(tx0, "TX0\n", LIMIT_TX0_NODE, tx0_limit)
-CFG_LIMIT(tx1, "TX1\n", LIMIT_TX1_NODE, tx1_limit)
-CFG_LIMIT(pa0, "PA0\n", LIMIT_PA0_NODE, pa0_limit)
-CFG_LIMIT(pa1, "PA1\n", LIMIT_PA1_NODE, pa1_limit)
-#undef CFG_LIMIT
+CFG_LIMIT_TEMP(supply_temp, "SUPPLY TEMP\n", LIMIT_SUPPLY_TEMP_NODE, 
supply_temp_limit)
+CFG_LIMIT_TEMP(soc_temp, "SOC TEMP\n", LIMIT_SOC_NODE, soc_temp_limit)
+CFG_LIMIT_TEMP(fpga_temp, "FPGA TEMP\n", LIMIT_FPGA_NODE, fpga_temp_limit)
+CFG_LIMIT_TEMP(rmsdet_temp, "RMSDET TEMP\n", LIMIT_RMSDET_NODE, 
rmsdet_temp_limit)
+CFG_LIMIT_TEMP(ocxo_temp, "OCXO TEMP\n", LIMIT_OCXO_NODE, ocxo_temp_limit)
+CFG_LIMIT_TEMP(tx0_temp, "TX0 TEMP\n", LIMIT_TX0_TEMP_NODE, tx0_temp_limit)
+CFG_LIMIT_TEMP(tx1_temp, "TX1 TEMP\n", LIMIT_TX1_TEMP_NODE, tx1_temp_limit)
+CFG_LIMIT_TEMP(pa0_temp, "PA0 TEMP\n", LIMIT_PA0_TEMP_NODE, pa0_temp_limit)
+CFG_LIMIT_TEMP(pa1_temp, "PA1 TEMP\n", LIMIT_PA1_TEMP_NODE, pa1_temp_limit)
+#undef CFG_LIMIT_TEMP
 
-DEFUN(cfg_limit_warning, cfg_thresh_warning_cmd,
-       "threshold warning <0-200>",
+#define CFG_LIMIT_VOLT(name, expl, switch_to, variable)                        
\
+DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd,                                
\
+       "limits " #name,                                                \
+       "Configure Limits\n" expl)                                      \
+{                                                                      \
+       vty->node = switch_to;                                          \
+       vty->index = &s_mgr->volt.variable;                             \
+       return CMD_SUCCESS;                                             \
+}
+
+CFG_LIMIT_VOLT(supply_volt, "SUPPLY VOLT\n", LIMIT_SUPPLY_VOLT_NODE, 
supply_volt_limit)
+#undef CFG_LIMIT_VOLT
+
+#define CFG_LIMIT_VSWR(name, expl, switch_to, variable)                        
\
+DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd,                                
\
+       "limits " #name,                                                \
+       "Configure Limits\n" expl)                                      \
+{                                                                      \
+       vty->node = switch_to;                                          \
+       vty->index = &s_mgr->vswr.variable;                             \
+       return CMD_SUCCESS;                                             \
+}
+
+CFG_LIMIT_VSWR(tx0_vswr, "TX0 VSWR\n", LIMIT_TX0_VSWR_NODE, tx0_vswr_limit)
+CFG_LIMIT_VSWR(tx1_vswr, "TX1 VSWR\n", LIMIT_TX1_VSWR_NODE, tx1_vswr_limit)
+#undef CFG_LIMIT_VSWR
+
+#define CFG_LIMIT_PWR(name, expl, switch_to, variable)                 \
+DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd,                                
\
+       "limits " #name,                                                \
+       "Configure Limits\n" expl)                                      \
+{                                                                      \
+       vty->node = switch_to;                                          \
+       vty->index = &s_mgr->pwr.variable;                              \
+       return CMD_SUCCESS;                                             \
+}
+
+CFG_LIMIT_PWR(supply_pwr, "SUPPLY PWR\n", LIMIT_SUPPLY_PWR_NODE, 
supply_pwr_limit)
+CFG_LIMIT_PWR(pa0_pwr, "PA0 PWR\n", LIMIT_PA0_PWR_NODE, pa0_pwr_limit)
+CFG_LIMIT_PWR(pa1_pwr, "PA1 PWR\n", LIMIT_PA1_PWR_NODE, pa1_pwr_limit)
+#undef CFG_LIMIT_PWR
+
+#define CFG_LIMIT_GPS_FIX(name, expl, switch_to, variable)                     
\
+DEFUN(cfg_limit_##name, cfg_limit_##name##_cmd,                                
\
+       "limits " #name,                                                \
+       "Configure Limits\n" expl)                                      \
+{                                                                      \
+       vty->node = switch_to;                                          \
+       vty->index = &s_mgr->gps.variable;                              \
+       return CMD_SUCCESS;                                             \
+}
+
+CFG_LIMIT_GPS_FIX(gps_fix, "GPS FIX\n", LIMIT_GPS_FIX_NODE, gps_fix_limit)
+#undef CFG_LIMIT_GPS_FIX
+
+DEFUN(cfg_limit_volt_warn_min, cfg_thresh_volt_warn_min_cmd,
+       "threshold warning min <0-48000>",
        "Threshold to reach\n" "Warning level\n" "Range\n")
 {
-       struct lc15bts_temp_limit *limit = vty->index;
-       limit->thresh_warn = atoi(argv[0]);
+       struct lc15bts_volt_limit *limit = vty->index;
+       limit->thresh_warn_min = atoi(argv[0]);
        return CMD_SUCCESS;
 }
 
-DEFUN(cfg_limit_crit, cfg_thresh_crit_cmd,
-       "threshold critical <0-200>",
-       "Threshold to reach\n" "Severe level\n" "Range\n")
+DEFUN(cfg_limit_volt_crit_min, cfg_thresh_volt_crit_min_cmd,
+       "threshold critical min <0-48000>",
+       "Threshold to reach\n" "Critical level\n" "Range\n")
 {
-       struct lc15bts_temp_limit *limit = vty->index;
-       limit->thresh_crit = atoi(argv[0]);
+       struct lc15bts_volt_limit *limit = vty->index;
+       limit->thresh_crit_min = atoi(argv[0]);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_limit_vswr_warn_max, cfg_thresh_vswr_warn_max_cmd,
+       "threshold warning max <1000-200000>",
+       "Threshold to reach\n" "Warning level\n" "Range\n")
+{
+       struct lc15bts_vswr_limit *limit = vty->index;
+       limit->thresh_warn_max = atoi(argv[0]);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_limit_vswr_crit_max, cfg_thresh_vswr_crit_max_cmd,
+       "threshold critical max <1000-200000>",
+       "Threshold to reach\n" "Warning level\n" "Range\n")
+{
+       struct lc15bts_vswr_limit *limit = vty->index;
+       limit->thresh_crit_max = atoi(argv[0]);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_limit_pwr_warn_max, cfg_thresh_pwr_warn_max_cmd,
+       "threshold warning max <0-200>",
+       "Threshold to reach\n" "Warning level\n" "Range\n")
+{
+       struct lc15bts_pwr_limit *limit = vty->index;
+       limit->thresh_warn_max = atoi(argv[0]);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_limit_pwr_crit_max, cfg_thresh_pwr_crit_max_cmd,
+       "threshold critical max <0-200>",
+       "Threshold to reach\n" "Warning level\n" "Range\n")
+{
+       struct lc15bts_pwr_limit *limit = vty->index;
+       limit->thresh_crit_max = atoi(argv[0]);
        return CMD_SUCCESS;
 }
 
@@ -300,7 +454,7 @@
        "Configure Actions\n" expl)                                     \
 {                                                                      \
        vty->node = switch_to;                                          \
-       vty->index = &s_mgr->temp.variable;                             \
+       vty->index = &s_mgr->state.variable;                            \
        return CMD_SUCCESS;                                             \
 }
 CFG_ACTION(normal, "Normal Actions\n", ACT_NORM_NODE, action_norm)
@@ -313,7 +467,7 @@
        "Switch the Power Amplifier #0 on\n")
 {
        int *action = vty->index;
-       *action |= TEMP_ACT_NORM_PA0_ON;
+       *action |= SENSOR_ACT_NORM_PA0_ON;
        return CMD_SUCCESS;
 }
 
@@ -322,7 +476,7 @@
        NO_STR "Switch the Power Amplifieri #0 on\n")
 {
        int *action = vty->index;
-       *action &= ~TEMP_ACT_NORM_PA0_ON;
+       *action &= ~SENSOR_ACT_NORM_PA0_ON;
        return CMD_SUCCESS;
 }
 
@@ -331,7 +485,7 @@
        "Switch the Power Amplifier #1 on\n")
 {
        int *action = vty->index;
-       *action |= TEMP_ACT_NORM_PA1_ON;
+       *action |= SENSOR_ACT_NORM_PA1_ON;
        return CMD_SUCCESS;
 }
 
@@ -340,7 +494,7 @@
        NO_STR "Switch the Power Amplifieri #1 on\n")
 {
        int *action = vty->index;
-       *action &= ~TEMP_ACT_NORM_PA1_ON;
+       *action &= ~SENSOR_ACT_NORM_PA1_ON;
        return CMD_SUCCESS;
 }
 
@@ -349,7 +503,7 @@
        "Start the systemd lc15bts.service\n")
 {
        int *action = vty->index;
-       *action |= TEMP_ACT_NORM_BTS_SRV_ON;
+       *action |= SENSOR_ACT_NORM_BTS_SRV_ON;
        return CMD_SUCCESS;
 }
 
@@ -358,7 +512,7 @@
        NO_STR "Start the systemd lc15bts.service\n")
 {
        int *action = vty->index;
-       *action &= ~TEMP_ACT_NORM_BTS_SRV_ON;
+       *action &= ~SENSOR_ACT_NORM_BTS_SRV_ON;
        return CMD_SUCCESS;
 }
 
@@ -367,7 +521,7 @@
        "Switch the Power Amplifier #0 off\n")
 {
        int *action = vty->index;
-       *action |= TEMP_ACT_PA0_OFF;
+       *action |= SENSOR_ACT_PA0_OFF;
        return CMD_SUCCESS;
 }
 
@@ -376,7 +530,7 @@
        NO_STR "Do not switch off the Power Amplifier #0\n")
 {
        int *action = vty->index;
-       *action &= ~TEMP_ACT_PA0_OFF;
+       *action &= ~SENSOR_ACT_PA0_OFF;
        return CMD_SUCCESS;
 }
 
@@ -385,7 +539,7 @@
         "Switch the Power Amplifier #1 off\n")
 {
         int *action = vty->index;
-        *action |= TEMP_ACT_PA1_OFF;
+        *action |= SENSOR_ACT_PA1_OFF;
         return CMD_SUCCESS;
 }
 
@@ -394,7 +548,7 @@
         NO_STR "Do not switch off the Power Amplifier #1\n")
 {
         int *action = vty->index;
-        *action &= ~TEMP_ACT_PA1_OFF;
+        *action &= ~SENSOR_ACT_PA1_OFF;
         return CMD_SUCCESS;
 }
 
@@ -403,7 +557,7 @@
        "Stop the systemd lc15bts.service\n")
 {
        int *action = vty->index;
-       *action |= TEMP_ACT_BTS_SRV_OFF;
+       *action |= SENSOR_ACT_BTS_SRV_OFF;
        return CMD_SUCCESS;
 }
 
@@ -412,71 +566,173 @@
        NO_STR "Stop the systemd lc15bts.service\n")
 {
        int *action = vty->index;
-       *action &= ~TEMP_ACT_BTS_SRV_OFF;
+       *action &= ~SENSOR_ACT_BTS_SRV_OFF;
        return CMD_SUCCESS;
 }
 
 DEFUN(show_mgr, show_mgr_cmd, "show manager",
       SHOW_STR "Display information about the manager")
 {
+       int temp, volt, current, power, vswr;
+       vty_out(vty, "Warning alarm flags: 0x%08x%s",
+               s_mgr->lc15bts_ctrl.warn_flags, VTY_NEWLINE);
+       vty_out(vty, "Critical alarm flags: 0x%08x%s",
+               s_mgr->lc15bts_ctrl.crit_flags, VTY_NEWLINE);
+       vty_out(vty, "Preventive action retried: %d%s",
+               s_mgr->alarms.preventive_retry, VTY_NEWLINE);
        vty_out(vty, "Temperature control state: %s%s",
-               lc15bts_mgr_temp_get_state(s_mgr->temp.state), VTY_NEWLINE);
+               lc15bts_mgr_sensor_get_state(s_mgr->state.state), VTY_NEWLINE);
        vty_out(vty, "Current Temperatures%s", VTY_NEWLINE);
-       vty_out(vty, " Main Supply : %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_SUPPLY) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_SUPPLY, &temp);
+       vty_out(vty, " Main Supply : %4.2f Celcius%s",
+                temp/ 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " SoC         : %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_SOC) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_SOC, &temp);
+       vty_out(vty, " SoC         : %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " FPGA        : %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_FPGA) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_FPGA, &temp);
+       vty_out(vty, " FPGA        : %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " LogRF       : %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_LOGRF) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_RMSDET, &temp);
+       vty_out(vty, " RMSDet      : %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " OCXO        : %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_OCXO) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_OCXO, &temp);
+       vty_out(vty, " OCXO        : %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " TX 0        : %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_TX0) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_TX0, &temp);
+       vty_out(vty, " TX 0        : %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " TX 1        : %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_TX1) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_TX1, &temp);
+       vty_out(vty, " TX 1        : %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " Power Amp #0: %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_PA0) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_PA0, &temp);
+       vty_out(vty, " Power Amp #0: %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
-       vty_out(vty, " Power Amp #1: %f Celcius%s",
-               lc15bts_temp_get(LC15BTS_TEMP_PA1) / 1000.0f, 
+       lc15bts_temp_get(LC15BTS_TEMP_PA1, &temp);
+       vty_out(vty, " Power Amp #1: %4.2f Celcius%s",
+               temp / 1000.0f,
                VTY_NEWLINE);
 
        vty_out(vty, "Power Status%s", VTY_NEWLINE);
+       lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY,
+                       LC15BTS_POWER_VOLTAGE, &volt);
+       lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY,
+                       LC15BTS_POWER_CURRENT, &current);
+       lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY,
+                       LC15BTS_POWER_POWER, &power);
        vty_out(vty, " Main Supply :  ON  [%6.2f Vdc, %4.2f A, %6.2f W]%s",
-               lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, 
-                       LC15BTS_POWER_VOLTAGE)/1000.0f,
-               lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, 
-                       LC15BTS_POWER_CURRENT)/1000.0f,
-               lc15bts_power_sensor_get(LC15BTS_POWER_SUPPLY, 
-                       LC15BTS_POWER_POWER)/1000000.0f,
+               volt /1000.0f,
+               current /1000.0f,
+               power /1000000.0f,
                VTY_NEWLINE);
+       lc15bts_power_sensor_get(LC15BTS_POWER_PA0,
+                       LC15BTS_POWER_VOLTAGE, &volt);
+       lc15bts_power_sensor_get(LC15BTS_POWER_PA0,
+                       LC15BTS_POWER_CURRENT, &current);
+       lc15bts_power_sensor_get(LC15BTS_POWER_PA0,
+                       LC15BTS_POWER_POWER, &power);
        vty_out(vty, " Power Amp #0:  %s [%6.2f Vdc, %4.2f A, %6.2f W]%s",
                lc15bts_power_get(LC15BTS_POWER_PA0) ? "ON " : "OFF",
-               lc15bts_power_sensor_get(LC15BTS_POWER_PA0, 
-                       LC15BTS_POWER_VOLTAGE)/1000.0f,
-               lc15bts_power_sensor_get(LC15BTS_POWER_PA0, 
-                       LC15BTS_POWER_CURRENT)/1000.0f,
-               lc15bts_power_sensor_get(LC15BTS_POWER_PA0, 
-                       LC15BTS_POWER_POWER)/1000000.0f,
+               volt /1000.0f,
+               current /1000.0f,
+               power /1000000.0f,
                VTY_NEWLINE);
+       lc15bts_power_sensor_get(LC15BTS_POWER_PA1,
+                       LC15BTS_POWER_VOLTAGE, &volt);
+       lc15bts_power_sensor_get(LC15BTS_POWER_PA1,
+                       LC15BTS_POWER_CURRENT, &current);
+       lc15bts_power_sensor_get(LC15BTS_POWER_PA1,
+                       LC15BTS_POWER_POWER, &power);
        vty_out(vty, " Power Amp #1:  %s [%6.2f Vdc, %4.2f A, %6.2f W]%s",
                lc15bts_power_get(LC15BTS_POWER_PA1) ? "ON " : "OFF",
-               lc15bts_power_sensor_get(LC15BTS_POWER_PA1, 
-                       LC15BTS_POWER_VOLTAGE)/1000.0f,
-               lc15bts_power_sensor_get(LC15BTS_POWER_PA1, 
-                       LC15BTS_POWER_CURRENT)/1000.0f,
-               lc15bts_power_sensor_get(LC15BTS_POWER_PA1, 
-                       LC15BTS_POWER_POWER)/1000000.0f,
+               volt /1000.0f,
+               current /1000.0f,
+               power /1000000.0f,
                VTY_NEWLINE);
+       vty_out(vty, "VSWR Status%s", VTY_NEWLINE);
+       lc15bts_vswr_get(LC15BTS_VSWR_TX0, &vswr);
+       vty_out(vty, " VSWR TX 0: %f %s",
+               vswr / 1000.0f,
+               VTY_NEWLINE);
+       lc15bts_vswr_get(LC15BTS_VSWR_TX1, &vswr);
+       vty_out(vty, " VSWR TX 1: %f %s",
+               vswr / 1000.0f,
+               VTY_NEWLINE);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(show_thresh, show_thresh_cmd, "show thresholds",
+      SHOW_STR "Display information about the thresholds")
+{
+       vty_out(vty, "Temperature limits (Celsius)%s", VTY_NEWLINE);
+       vty_out(vty, "  Main supply%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.supply_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.supply_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.supply_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  SoC%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.soc_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.soc_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.soc_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  FPGA%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.fpga_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.fpga_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  RMSDet%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.rmsdet_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.rmsdet_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  OCXO%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.ocxo_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.ocxo_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  TX0%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.tx0_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.tx0_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.tx0_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  TX1%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.tx1_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.tx1_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.tx1_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  PA0%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.pa0_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.pa0_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.pa0_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "  PA1%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->temp.pa1_temp_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->temp.pa1_temp_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->temp.pa1_temp_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "Power limits%s", VTY_NEWLINE);
+       vty_out(vty, "  Main supply (mV)%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->volt.supply_volt_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->volt.supply_volt_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning min  : 
%d%s",s_mgr->volt.supply_volt_limit.thresh_warn_min, VTY_NEWLINE);
+       vty_out(vty, "    Critical min : 
%d%s",s_mgr->volt.supply_volt_limit.thresh_crit_min, VTY_NEWLINE);
+       vty_out(vty, "  Main supply power (W)%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->pwr.supply_pwr_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->pwr.supply_pwr_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "  PA0 power (W)%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->pwr.pa0_pwr_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->pwr.pa0_pwr_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "  PA1 power (W)%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->pwr.pa1_pwr_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->pwr.pa1_pwr_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "VSWR limits%s", VTY_NEWLINE);
+       vty_out(vty, "  TX0%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->vswr.tx0_vswr_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->vswr.tx0_vswr_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "  TX1%s", VTY_NEWLINE);
+       vty_out(vty, "    Critical max : 
%d%s",s_mgr->vswr.tx1_vswr_limit.thresh_crit_max, VTY_NEWLINE);
+       vty_out(vty, "    Warning max  : 
%d%s",s_mgr->vswr.tx1_vswr_limit.thresh_warn_max, VTY_NEWLINE);
+       vty_out(vty, "Days since last GPS 3D fix%s", VTY_NEWLINE);
+       vty_out(vty, "    Warning max : 
%d%s",s_mgr->gps.gps_fix_limit.thresh_warn_max, VTY_NEWLINE);
 
        return CMD_SUCCESS;
 }
@@ -493,10 +749,153 @@
        return CMD_SUCCESS;
 }
 
-static void register_limit(int limit)
+DEFUN(set_led_pattern, set_led_pattern_cmd,
+      "set led pattern <0-255>",
+      "Set LED pattern\n"
+      "Set LED pattern for debugging purpose only. This pattern will be 
overridden after 60 seconds by LED pattern of actual system state\n")
 {
-       install_element(limit, &cfg_thresh_warning_cmd);
-       install_element(limit, &cfg_thresh_crit_cmd);
+       int pattern_id = atoi(argv[0]);
+
+       if ((pattern_id < 0) || (pattern_id > BLINK_PATTERN_MAX_ITEM)) {
+               vty_out(vty, "%%Invalid LED pattern ID. It must be in range of 
%d..%d %s", 0, BLINK_PATTERN_MAX_ITEM - 1, VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       led_set(s_mgr, pattern_id);
+       return CMD_SUCCESS;
+}
+
+DEFUN(force_mgr_state, force_mgr_state_cmd,
+      "force manager state  <0-255>",
+      "Force BTS manager state\n"
+      "Force BTS manager state for debugging purpose only\n")
+{
+       int state = atoi(argv[0]);
+
+       if ((state < 0) || (state > STATE_CRITICAL)) {
+               vty_out(vty, "%%Invalid BTS manager state. It must be in range 
of %d..%d %s", 0, STATE_CRITICAL, VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       s_mgr->state.state = state;
+       return CMD_SUCCESS;
+}
+
+#define LIMIT_TEMP(name, limit, expl, variable, criticity, min_max)            
        \
+DEFUN(limit_temp_##name##_##variable, limit_temp_##name##_##variable##_cmd,    
\
+       "limit temp " #name " " #criticity " " #min_max " <-200-200>",          
        \
+       "Limit to reach\n" expl)                                                
                                                \
+{                                                                              
                                                                        \
+       s_mgr->temp.limit.variable = atoi(argv[0]);                             
                                \
+       return CMD_SUCCESS;                                                     
                                                        \
+}
+
+LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_max, 
warning, max)
+LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_crit_max, 
critical, max)
+LIMIT_TEMP(supply, supply_temp_limit, "SUPPLY TEMP\n", thresh_warn_min, 
warning, min)
+LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_max, warning, max)
+LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_crit_max, critical, 
max)
+LIMIT_TEMP(soc, supply_temp_limit, "SOC TEMP\n", thresh_warn_min, warning, min)
+LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_max, warning, max)
+LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_crit_max, critical, 
max)
+LIMIT_TEMP(fpga, fpga_temp_limit, "FPGA TEMP\n", thresh_warn_min, warning, min)
+LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_max, 
warning, max)
+LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_crit_max, 
critical, max)
+LIMIT_TEMP(rmsdet, rmsdet_temp_limit, "RMSDET TEMP\n", thresh_warn_min, 
warning, min)
+LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_max, warning, max)
+LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_crit_max, critical, 
max)
+LIMIT_TEMP(ocxo, ocxo_temp_limit, "OCXO TEMP\n", thresh_warn_min, warning, min)
+LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_warn_max, warning, max)
+LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_crit_max, critical, max)
+LIMIT_TEMP(tx0, tx0_temp_limit, "TX0 TEMP\n", thresh_warn_min, warning, min)
+LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_warn_max, warning, max)
+LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_crit_max, critical, max)
+LIMIT_TEMP(tx1, tx1_temp_limit, "TX1 TEMP\n", thresh_warn_min, warning, min)
+LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_warn_max, warning, max)
+LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_crit_max, critical, max)
+LIMIT_TEMP(pa0, pa0_temp_limit, "PA0 TEMP\n", thresh_warn_min, warning, min)
+LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_warn_max, warning, max)
+LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_crit_max, critical, max)
+LIMIT_TEMP(pa1, pa1_temp_limit, "PA1 TEMP\n", thresh_warn_min, warning, min)
+#undef LIMIT_TEMP
+
+#define LIMIT_VOLT(name, limit, expl, variable, criticity, min_max)            
        \
+DEFUN(limit_volt_##name##_##variable, limit_volt_##name##_##variable##_cmd,    
\
+       "limit " #name " " #criticity " " #min_max " <0-48000>",                
                \
+       "Limit to reach\n" expl)                                                
                                                \
+{                                                                              
                                                                        \
+       s_mgr->volt.limit.variable = atoi(argv[0]);                             
                                \
+       return CMD_SUCCESS;                                                     
                                                        \
+}
+
+LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_max, 
warning, max)
+LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_max, 
critical, max)
+LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_warn_min, 
warning, min)
+LIMIT_VOLT(supply, supply_volt_limit, "SUPPLY VOLT\n", thresh_crit_min, 
critical, min)
+#undef LIMIT_VOLT
+
+#define LIMIT_PWR(name, limit, expl, variable, criticity, min_max)             
                        \
+       DEFUN(limit_pwr_##name##_##variable, 
limit_pwr_##name##_##variable##_cmd,               \
+       "limit power " #name " " #criticity " " #min_max " <0-200>",            
                        \
+       "Limit to reach\n" expl)                                                
                                                                \
+{                                                                              
                                                                                
        \
+       s_mgr->pwr.limit.variable = atoi(argv[0]);                              
                                                \
+       return CMD_SUCCESS;                                                     
                                                                        \
+}
+
+LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_warn_max, warning, 
max)
+LIMIT_PWR(supply, supply_pwr_limit, "SUPPLY PWR\n", thresh_crit_max, critical, 
max)
+LIMIT_PWR(pa0, pa0_pwr_limit, "PA0 PWR\n", thresh_warn_max, warning, max)
+LIMIT_PWR(pa0, pa0_pwr_limit, "PA0 PWR\n", thresh_crit_max, critical, max)
+LIMIT_PWR(pa1, pa1_pwr_limit, "PA1 PWR\n", thresh_warn_max, warning, max)
+LIMIT_PWR(pa1, pa1_pwr_limit, "PA1 PWR\n", thresh_crit_max, critical, max)
+#undef LIMIT_PWR
+
+#define LIMIT_VSWR(name, limit, expl, variable, criticity, min_max)            
        \
+DEFUN(limit_vswr_##name##_##variable, limit_vswr_##name##_##variable##_cmd,    
\
+       "limit vswr " #name " " #criticity " " #min_max " <1000-200000>",       
        \
+       "Limit to reach\n" expl)                                                
                                                \
+{                                                                              
                                                                        \
+       s_mgr->vswr.limit.variable = atoi(argv[0]);                             
                                \
+       return CMD_SUCCESS;                                                     
                                                        \
+}
+
+LIMIT_VSWR(tx0, tx0_vswr_limit, "TX0 VSWR\n", thresh_warn_max, warning, max)
+LIMIT_VSWR(tx0, tx0_vswr_limit, "TX0 VSWR\n", thresh_crit_max, critical, max)
+LIMIT_VSWR(tx1, tx1_vswr_limit, "TX1 VSWR\n", thresh_warn_max, warning, max)
+LIMIT_VSWR(tx1, tx1_vswr_limit, "TX1 VSWR\n", thresh_crit_max, critical, max)
+#undef LIMIT_VSWR
+
+#define LIMIT_GPSFIX(limit, expl, variable, criticity, min_max)                
        \
+DEFUN(limit_gpsfix_##variable, limit_gpsfix_##variable##_cmd,                  
\
+       "limit gpsfix " #criticity " " #min_max " <0-365>",                     
                \
+       "Limit to reach\n" expl)                                                
                                        \
+{                                                                              
                                                                \
+       s_mgr->gps.limit.variable = atoi(argv[0]);                              
                        \
+       return CMD_SUCCESS;                                                     
                                                \
+}
+
+LIMIT_GPSFIX(gps_fix_limit, "GPS FIX\n", thresh_warn_max, warning, max)
+#undef LIMIT_GPSFIX
+
+static void register_limit(int limit, uint32_t unit)
+{
+       switch (unit) {
+       case MGR_LIMIT_TYPE_VOLT:
+               install_element(limit, &cfg_thresh_volt_warn_min_cmd);
+               install_element(limit, &cfg_thresh_volt_crit_min_cmd);
+               break;
+       case MGR_LIMIT_TYPE_VSWR:
+               install_element(limit, &cfg_thresh_vswr_warn_max_cmd);
+               install_element(limit, &cfg_thresh_vswr_crit_max_cmd);
+               break;
+       case MGR_LIMIT_TYPE_PWR:
+               install_element(limit, &cfg_thresh_pwr_warn_max_cmd);
+               install_element(limit, &cfg_thresh_pwr_crit_max_cmd);
+               break;
+       default:
+               break;
+       }
 }
 
 static void register_normal_action(int act)
@@ -519,11 +918,62 @@
        install_element(act, &cfg_no_action_bts_srv_off_cmd);
 }
 
+static void register_hidden_commands()
+{
+       install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_supply_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_supply_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_soc_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_soc_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_fpga_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_fpga_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_rmsdet_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_ocxo_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_tx0_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_tx0_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_tx0_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_tx1_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_tx1_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_tx1_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_pa0_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_pa0_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_pa0_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_temp_pa1_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_pa1_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_temp_pa1_thresh_warn_min_cmd);
+
+       install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_volt_supply_thresh_warn_min_cmd);
+       install_element(ENABLE_NODE, &limit_volt_supply_thresh_crit_min_cmd);
+
+       install_element(ENABLE_NODE, &limit_pwr_supply_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_pwr_supply_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_pwr_pa0_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_pwr_pa0_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_pwr_pa1_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_pwr_pa1_thresh_crit_max_cmd);
+
+       install_element(ENABLE_NODE, &limit_vswr_tx0_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_vswr_tx0_thresh_crit_max_cmd);
+       install_element(ENABLE_NODE, &limit_vswr_tx1_thresh_warn_max_cmd);
+       install_element(ENABLE_NODE, &limit_vswr_tx1_thresh_crit_max_cmd);
+
+       install_element(ENABLE_NODE, &limit_gpsfix_thresh_warn_max_cmd);
+}
+
 int lc15bts_mgr_vty_init(void)
 {
        vty_init(&vty_info);
 
        install_element_ve(&show_mgr_cmd);
+       install_element_ve(&show_thresh_cmd);
 
        install_element(ENABLE_NODE, &calibrate_clock_cmd);
 
@@ -532,50 +982,73 @@
        vty_install_default(MGR_NODE);
 
        /* install the limit nodes */
-       install_node(&limit_supply_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_supply_cmd);
-       register_limit(LIMIT_SUPPLY_NODE);
-       vty_install_default(LIMIT_SUPPLY_NODE);
+       install_node(&limit_supply_temp_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_supply_temp_cmd);
+       vty_install_default(LIMIT_SUPPLY_TEMP_NODE);
 
        install_node(&limit_soc_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_soc_cmd);
-       register_limit(LIMIT_SOC_NODE);
+       install_element(MGR_NODE, &cfg_limit_soc_temp_cmd);
        vty_install_default(LIMIT_SOC_NODE);
 
        install_node(&limit_fpga_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_fpga_cmd);
-       register_limit(LIMIT_FPGA_NODE);
+       install_element(MGR_NODE, &cfg_limit_fpga_temp_cmd);
        vty_install_default(LIMIT_FPGA_NODE);
 
-       install_node(&limit_logrf_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_logrf_cmd);
-       register_limit(LIMIT_LOGRF_NODE);
-       vty_install_default(LIMIT_LOGRF_NODE);
+       install_node(&limit_rmsdet_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_rmsdet_temp_cmd);
+       vty_install_default(LIMIT_RMSDET_NODE);
 
        install_node(&limit_ocxo_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_ocxo_cmd);
-       register_limit(LIMIT_OCXO_NODE);
+       install_element(MGR_NODE, &cfg_limit_ocxo_temp_cmd);
        vty_install_default(LIMIT_OCXO_NODE);
 
-       install_node(&limit_tx0_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_tx0_cmd);
-       register_limit(LIMIT_TX0_NODE);
-       vty_install_default(LIMIT_TX0_NODE);
+       install_node(&limit_tx0_temp_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_tx0_temp_cmd);
+       vty_install_default(LIMIT_TX0_TEMP_NODE);
 
-       install_node(&limit_tx1_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_tx1_cmd);
-       register_limit(LIMIT_TX1_NODE);
-       vty_install_default(LIMIT_TX1_NODE);
+       install_node(&limit_tx1_temp_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_tx1_temp_cmd);
+       vty_install_default(LIMIT_TX1_TEMP_NODE);
 
-       install_node(&limit_pa0_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_pa0_cmd);
-       register_limit(LIMIT_PA0_NODE);
-       vty_install_default(LIMIT_PA0_NODE);
+       install_node(&limit_pa0_temp_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_pa0_temp_cmd);
+       vty_install_default(LIMIT_PA0_TEMP_NODE);
 
-       install_node(&limit_pa1_node, config_write_dummy);
-       install_element(MGR_NODE, &cfg_limit_pa1_cmd);
-       register_limit(LIMIT_PA1_NODE);
-       vty_install_default(LIMIT_PA1_NODE);
+       install_node(&limit_pa1_temp_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_pa1_temp_cmd);
+       vty_install_default(LIMIT_PA1_TEMP_NODE);
+
+       install_node(&limit_supply_volt_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_supply_volt_cmd);
+       register_limit(LIMIT_SUPPLY_VOLT_NODE, MGR_LIMIT_TYPE_VOLT);
+       vty_install_default(LIMIT_SUPPLY_VOLT_NODE);
+
+       install_node(&limit_tx0_vswr_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_tx0_vswr_cmd);
+       register_limit(LIMIT_TX0_VSWR_NODE, MGR_LIMIT_TYPE_VSWR);
+       vty_install_default(LIMIT_TX0_VSWR_NODE);
+
+       install_node(&limit_tx1_vswr_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_tx1_vswr_cmd);
+       register_limit(LIMIT_TX1_VSWR_NODE, MGR_LIMIT_TYPE_VSWR);
+       vty_install_default(LIMIT_TX1_VSWR_NODE);
+
+       install_node(&limit_supply_pwr_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_supply_pwr_cmd);
+       register_limit(LIMIT_SUPPLY_PWR_NODE, MGR_LIMIT_TYPE_PWR);
+       vty_install_default(LIMIT_SUPPLY_PWR_NODE);
+
+       install_node(&limit_pa0_pwr_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_pa0_pwr_cmd);
+       vty_install_default(LIMIT_PA0_PWR_NODE);
+
+       install_node(&limit_pa1_pwr_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_pa1_pwr_cmd);
+       vty_install_default(LIMIT_PA1_PWR_NODE);
+
+       install_node(&limit_gps_fix_node, config_write_dummy);
+       install_element(MGR_NODE, &cfg_limit_gps_fix_cmd);
+       vty_install_default(LIMIT_GPS_FIX_NODE);
 
        /* install the normal node */
        install_node(&act_norm_node, config_write_dummy);
@@ -593,6 +1066,12 @@
        register_action(ACT_CRIT_NODE);
        vty_install_default(ACT_CRIT_NODE);
 
+       /* install LED pattern command for debugging purpose */
+       install_element_ve(&set_led_pattern_cmd);
+       install_element_ve(&force_mgr_state_cmd);
+
+       register_hidden_commands();
+
        return 0;
 }
 
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_misc.c 
b/src/osmo-bts-litecell15/misc/lc15bts_misc.c
index fa59b7c..2cedc5d 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_misc.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_misc.c
@@ -41,11 +41,13 @@
 #include <osmocom/vty/telnet_interface.h>
 #include <osmocom/vty/logging.h>
 
+#include "lc15bts_mgr.h"
 #include "btsconfig.h"
 #include "lc15bts_misc.h"
 #include "lc15bts_par.h"
 #include "lc15bts_mgr.h"
 #include "lc15bts_temp.h"
+#include "lc15bts_power.h"
 
 /*********************************************************************
  * Temperature handling
@@ -58,52 +60,111 @@
        enum lc15bts_par ee_par;
 } temp_data[] = {
        {
-               .name = "supply",
+               .name = "supply_temp",
                .has_max = 1,
                .sensor = LC15BTS_TEMP_SUPPLY,
                .ee_par = LC15BTS_PAR_TEMP_SUPPLY_MAX,
        }, {
-               .name = "soc",
+               .name = "soc_temp",
                .has_max = 0,
                .sensor = LC15BTS_TEMP_SOC,
                .ee_par = LC15BTS_PAR_TEMP_SOC_MAX,
        }, {
-               .name = "fpga",
+               .name = "fpga_temp",
                .has_max = 0,
                .sensor = LC15BTS_TEMP_FPGA,
                .ee_par = LC15BTS_PAR_TEMP_FPGA_MAX,
 
        }, {
-               .name = "logrf",
+               .name = "rmsdet_temp",
                .has_max = 1,
-               .sensor = LC15BTS_TEMP_LOGRF,
-               .ee_par = LC15BTS_PAR_TEMP_LOGRF_MAX,
+               .sensor = LC15BTS_TEMP_RMSDET,
+               .ee_par = LC15BTS_PAR_TEMP_RMSDET_MAX,
        }, {
-               .name = "ocxo",
+               .name = "ocxo_temp",
                .has_max = 1,
                .sensor = LC15BTS_TEMP_OCXO,
                .ee_par = LC15BTS_PAR_TEMP_OCXO_MAX,
        }, {
-               .name = "tx0",
+               .name = "tx0_temp",
                .has_max = 0,
                .sensor = LC15BTS_TEMP_TX0,
                .ee_par = LC15BTS_PAR_TEMP_TX0_MAX,
        }, {
-               .name = "tx1",
+               .name = "tx1_temp",
                .has_max = 0,
                .sensor = LC15BTS_TEMP_TX1,
                .ee_par = LC15BTS_PAR_TEMP_TX1_MAX,
        }, {
-               .name = "pa0",
+               .name = "pa0_temp",
                .has_max = 1,
                .sensor = LC15BTS_TEMP_PA0,
                .ee_par = LC15BTS_PAR_TEMP_PA0_MAX,
        }, {
-               .name = "pa1",
+               .name = "pa1_temp",
                .has_max = 1,
                .sensor = LC15BTS_TEMP_PA1,
                .ee_par = LC15BTS_PAR_TEMP_PA1_MAX,
        }
+};
+
+static const struct {
+       const char *name;
+       int has_max;
+       enum lc15bts_power_source sensor_source;
+       enum lc15bts_power_type sensor_type;
+       enum lc15bts_par ee_par;
+} power_data[] = {
+       {
+               .name = "supply_volt",
+               .has_max = 1,
+               .sensor_source = LC15BTS_POWER_SUPPLY,
+               .sensor_type = LC15BTS_POWER_VOLTAGE,
+               .ee_par = LC15BTS_PAR_VOLT_SUPPLY_MAX,
+       }, {
+               .name = "supply_pwr",
+               .has_max = 1,
+               .sensor_source = LC15BTS_POWER_SUPPLY,
+               .sensor_type = LC15BTS_POWER_POWER,
+               .ee_par = LC15BTS_PAR_PWR_SUPPLY_MAX,
+       }, {
+               .name = "pa0_pwr",
+               .has_max = 1,
+               .sensor_source = LC15BTS_POWER_PA0,
+               .sensor_type = LC15BTS_POWER_POWER,
+               .ee_par = LC15BTS_PAR_PWR_PA0_MAX,
+       }, {
+               .name = "pa1_pwr",
+               .has_max = 1,
+               .sensor_source = LC15BTS_POWER_PA1,
+               .sensor_type = LC15BTS_POWER_POWER,
+               .ee_par = LC15BTS_PAR_PWR_PA1_MAX,
+       }
+};
+
+static const struct {
+       const char *name;
+       int has_max;
+       enum lc15bts_vswr_sensor sensor;
+       enum lc15bts_par ee_par;
+} vswr_data[] = {
+       {
+               .name = "tx0_vswr",
+               .has_max = 0,
+               .sensor = LC15BTS_VSWR_TX0,
+               .ee_par = LC15BTS_PAR_VSWR_TX0_MAX,
+       }, {
+               .name = "tx1_vswr",
+               .has_max = 0,
+               .sensor = LC15BTS_VSWR_TX1,
+               .ee_par = LC15BTS_PAR_VSWR_TX1_MAX,
+       }
+};
+
+static const struct value_string power_unit_strs[] = {
+       { LC15BTS_POWER_POWER, "W" },
+       { LC15BTS_POWER_VOLTAGE, "V" },
+       { 0, NULL }
 };
 
 void lc15bts_check_temp(int no_rom_write)
@@ -117,7 +178,7 @@
                rc = lc15bts_par_get_int(tall_mgr_ctx, temp_data[i].ee_par, 
&ret);
                temp_old[i] = ret * 1000;
 
-               temp_cur[i] = lc15bts_temp_get(temp_data[i].sensor);
+               lc15bts_temp_get(temp_data[i].sensor, &temp_cur[i]);
                if (temp_cur[i] < 0 && temp_cur[i] > -1000) {
                        LOGP(DTEMP, LOGL_ERROR, "Error reading temperature 
(%d): unexpected value %d\n",
                             temp_data[i].sensor, temp_cur[i]);
@@ -143,6 +204,91 @@
        }
 }
 
+void lc15bts_check_power(int no_rom_write)
+{
+       int power_old[ARRAY_SIZE(power_data)];
+       int power_cur[ARRAY_SIZE(power_data)];
+       int i, rc;
+       int div_ratio;
+
+       for (i = 0; i < ARRAY_SIZE(power_data); i++) {
+               int ret;
+               rc = lc15bts_par_get_int(tall_mgr_ctx, power_data[i].ee_par, 
&ret);
+               switch(power_data[i].sensor_type) {
+               case LC15BTS_POWER_VOLTAGE:
+                       div_ratio = 1000;
+                       break;
+               case LC15BTS_POWER_POWER:
+                       div_ratio = 1000000;
+                       break;
+               default:
+                       div_ratio = 1000;
+               }
+               power_old[i] = ret * div_ratio;
+
+               lc15bts_power_sensor_get(power_data[i].sensor_source, 
power_data[i].sensor_type, &power_cur[i]);
+               if (power_cur[i] < 0 && power_cur[i] > -1000) {
+                       LOGP(DTEMP, LOGL_ERROR, "Error reading power (%d) 
(%d)\n", power_data[i].sensor_source,
+                            power_data[i].sensor_type);
+                       continue;
+               }
+               LOGP(DTEMP, LOGL_DEBUG, "Current %s power: %d.%d %s\n",
+                               power_data[i].name, power_cur[i]/div_ratio, 
power_cur[i]%div_ratio,
+                               get_value_string(power_unit_strs, 
power_data[i].sensor_type));
+
+               if (power_cur[i] > power_old[i]) {
+                       LOGP(DTEMP, LOGL_NOTICE, "New maximum %s "
+                               "power: %d.%d %s\n", power_data[i].name,
+                               power_cur[i]/div_ratio, power_cur[i]%div_ratio,
+                                get_value_string(power_unit_strs, 
power_data[i].sensor_type));
+
+                       if (!no_rom_write) {
+                               rc = lc15bts_par_set_int(tall_mgr_ctx, 
power_data[i].ee_par, power_cur[i]/div_ratio);
+                               if (rc < 0)
+                                       LOGP(DTEMP, LOGL_ERROR, "error writing 
new %s "
+                                               "max power %d (%s)\n", 
power_data[i].name,
+                                               rc, strerror(errno));
+                       }
+               }
+       }
+}
+
+void lc15bts_check_vswr(int no_rom_write)
+{
+       int vswr_old[ARRAY_SIZE(vswr_data)];
+       int vswr_cur[ARRAY_SIZE(vswr_data)];
+       int i, rc;
+
+       for (i = 0; i < ARRAY_SIZE(vswr_data); i++) {
+               int ret;
+               rc = lc15bts_par_get_int(tall_mgr_ctx, vswr_data[i].ee_par, 
&ret);
+               vswr_old[i] = ret * 1000;
+
+               lc15bts_vswr_get(vswr_data[i].sensor, &vswr_cur[i]);
+               if (vswr_cur[i] < 0 && vswr_cur[i] > -1000) {
+                       LOGP(DTEMP, LOGL_ERROR, "Error reading vswr (%d)\n", 
vswr_data[i].sensor);
+                       continue;
+               }
+
+               LOGP(DTEMP, LOGL_DEBUG, "Current %s vswr: %d.%d\n",
+                    vswr_data[i].name, vswr_cur[i]/1000, vswr_cur[i]%1000);
+
+               if (vswr_cur[i] > vswr_old[i]) {
+                       LOGP(DTEMP, LOGL_NOTICE, "New maximum %s "
+                            "vswr: %d.%d C\n", vswr_data[i].name,
+                            vswr_cur[i]/1000, vswr_old[i]%1000);
+
+                       if (!no_rom_write) {
+                               rc = lc15bts_par_set_int(tall_mgr_ctx, 
vswr_data[i].ee_par, vswr_cur[i]/1000);
+                               if (rc < 0)
+                                       LOGP(DTEMP, LOGL_ERROR, "error writing 
new %s "
+                                            "max vswr %d (%s)\n", 
vswr_data[i].name,
+                                            rc, strerror(errno));
+                       }
+               }
+       }
+}
+
 /*********************************************************************
  * Hours handling
  *********************************************************************/
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_misc.h 
b/src/osmo-bts-litecell15/misc/lc15bts_misc.h
index 4c3a862..79e9e68 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_misc.h
+++ b/src/osmo-bts-litecell15/misc/lc15bts_misc.h
@@ -4,6 +4,8 @@
 #include <stdint.h>
 
 void lc15bts_check_temp(int no_rom_write);
+void lc15bts_check_power(int no_rom_write);
+void lc15bts_check_vswr(int no_rom_write);
 
 int lc15bts_update_hours(int no_rom_write);
 
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_par.c 
b/src/osmo-bts-litecell15/misc/lc15bts_par.c
index 13b0080..75314a4 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_par.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_par.c
@@ -43,12 +43,19 @@
        { LC15BTS_PAR_TEMP_SUPPLY_MAX,  "temp-supply-max" },
        { LC15BTS_PAR_TEMP_SOC_MAX,     "temp-soc-max" },
        { LC15BTS_PAR_TEMP_FPGA_MAX,    "temp-fpga-max" },
-       { LC15BTS_PAR_TEMP_LOGRF_MAX,   "temp-logrf-max" },
+       { LC15BTS_PAR_TEMP_RMSDET_MAX,  "temp-rmsdet-max" },
        { LC15BTS_PAR_TEMP_OCXO_MAX,    "temp-ocxo-max" },
        { LC15BTS_PAR_TEMP_TX0_MAX,     "temp-tx0-max" },
        { LC15BTS_PAR_TEMP_TX1_MAX,     "temp-tx1-max" },
        { LC15BTS_PAR_TEMP_PA0_MAX,     "temp-pa0-max" },
        { LC15BTS_PAR_TEMP_PA1_MAX,     "temp-pa1-max" },
+       { LC15BTS_PAR_VOLT_SUPPLY_MAX,  "volt-supply-max" },
+       { LC15BTS_PAR_PWR_SUPPLY_MAX,   "pwr-supply-max" },
+       { LC15BTS_PAR_PWR_PA0_MAX,      "pwr-pa0-max" },
+       { LC15BTS_PAR_PWR_PA1_MAX,      "pwr-pa1-max" },
+       { LC15BTS_PAR_VSWR_TX0_MAX,     "vswr-tx0-max" },
+       { LC15BTS_PAR_VSWR_TX1_MAX,     "vswr-tx1-max" },
+       { LC15BTS_PAR_GPS_FIX,          "gps-fix" },
        { LC15BTS_PAR_SERNR,            "serial-nr" },
        { LC15BTS_PAR_HOURS,            "hours-running" },
        { LC15BTS_PAR_BOOTS,            "boot-count" },
@@ -60,17 +67,23 @@
 {
        switch (par) {
        case LC15BTS_PAR_TEMP_SUPPLY_MAX:
-        case LC15BTS_PAR_TEMP_SOC_MAX:
-        case LC15BTS_PAR_TEMP_FPGA_MAX:
-        case LC15BTS_PAR_TEMP_LOGRF_MAX:
-        case LC15BTS_PAR_TEMP_OCXO_MAX:
-        case LC15BTS_PAR_TEMP_TX0_MAX:
-        case LC15BTS_PAR_TEMP_TX1_MAX:
-        case LC15BTS_PAR_TEMP_PA0_MAX:
-        case LC15BTS_PAR_TEMP_PA1_MAX:
+       case LC15BTS_PAR_TEMP_SOC_MAX:
+       case LC15BTS_PAR_TEMP_FPGA_MAX:
+       case LC15BTS_PAR_TEMP_RMSDET_MAX:
+       case LC15BTS_PAR_TEMP_OCXO_MAX:
+       case LC15BTS_PAR_TEMP_TX0_MAX:
+       case LC15BTS_PAR_TEMP_TX1_MAX:
+       case LC15BTS_PAR_TEMP_PA0_MAX:
+       case LC15BTS_PAR_TEMP_PA1_MAX:
+       case LC15BTS_PAR_VOLT_SUPPLY_MAX:
+       case LC15BTS_PAR_VSWR_TX0_MAX:
+       case LC15BTS_PAR_VSWR_TX1_MAX:
        case LC15BTS_PAR_SERNR:
        case LC15BTS_PAR_HOURS:
        case LC15BTS_PAR_BOOTS:
+       case LC15BTS_PAR_PWR_SUPPLY_MAX:
+       case LC15BTS_PAR_PWR_PA0_MAX:
+       case LC15BTS_PAR_PWR_PA1_MAX:
                return 1;
        default:
                return 0;
@@ -168,3 +181,52 @@
 
         return rc;
 }
+
+int lc15bts_par_get_gps_fix(time_t *ret)
+{
+       char fpath[PATH_MAX];
+       FILE *fp;
+       int rc;
+
+       snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, 
get_value_string(lc15bts_par_names, LC15BTS_PAR_GPS_FIX));
+       fpath[sizeof(fpath)-1] = '\0';
+
+       fp = fopen(fpath, "r");
+       if (fp == NULL) {
+               return -errno;
+       }
+
+       rc = fscanf(fp, "%lld", (long long *)ret);
+       if (rc != 1) {
+               fclose(fp);
+               return -EIO;
+       }
+       fclose(fp);
+
+       return 0;
+}
+
+int lc15bts_par_set_gps_fix(time_t val)
+{
+       char fpath[PATH_MAX];
+       FILE *fp;
+       int rc;
+
+       snprintf(fpath, sizeof(fpath)-1, "%s/%s", USER_ROM_PATH, 
get_value_string(lc15bts_par_names, LC15BTS_PAR_GPS_FIX));
+       fpath[sizeof(fpath)-1] = '\0';
+
+       fp = fopen(fpath, "w");
+       if (fp == NULL) {
+               return -errno;
+       }
+
+       rc = fprintf(fp, "%lld", (long long)val);
+       if (rc < 0) {
+               fclose(fp);
+               return -EIO;
+       }
+       fsync(fp);
+       fclose(fp);
+
+       return 0;
+}
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_par.h 
b/src/osmo-bts-litecell15/misc/lc15bts_par.h
index dd869d3..217ae5f 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_par.h
+++ b/src/osmo-bts-litecell15/misc/lc15bts_par.h
@@ -10,12 +10,19 @@
        LC15BTS_PAR_TEMP_SUPPLY_MAX,
        LC15BTS_PAR_TEMP_SOC_MAX,
        LC15BTS_PAR_TEMP_FPGA_MAX,
-       LC15BTS_PAR_TEMP_LOGRF_MAX,
+       LC15BTS_PAR_TEMP_RMSDET_MAX,
        LC15BTS_PAR_TEMP_OCXO_MAX,
        LC15BTS_PAR_TEMP_TX0_MAX,
        LC15BTS_PAR_TEMP_TX1_MAX,
        LC15BTS_PAR_TEMP_PA0_MAX,
        LC15BTS_PAR_TEMP_PA1_MAX,
+       LC15BTS_PAR_VOLT_SUPPLY_MAX,
+       LC15BTS_PAR_PWR_SUPPLY_MAX,
+       LC15BTS_PAR_PWR_PA0_MAX,
+       LC15BTS_PAR_PWR_PA1_MAX,
+       LC15BTS_PAR_VSWR_TX0_MAX,
+       LC15BTS_PAR_VSWR_TX1_MAX,
+       LC15BTS_PAR_GPS_FIX,
        LC15BTS_PAR_SERNR,
        LC15BTS_PAR_HOURS,
        LC15BTS_PAR_BOOTS,
@@ -31,5 +38,7 @@
 int lc15bts_par_set_buf(void *ctx, enum lc15bts_par par, const uint8_t *buf, 
unsigned int size);
 
 int lc15bts_par_is_int(enum lc15bts_par par);
+int lc15bts_par_get_gps_fix(time_t *ret);
+int lc15bts_par_set_gps_fix(time_t val);
 
 #endif
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_power.c 
b/src/osmo-bts-litecell15/misc/lc15bts_power.c
index 5b01d36..1a37d8e 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_power.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_power.c
@@ -39,7 +39,7 @@
 };
 
 static const char *power_sensor_devs[_NUM_POWER_SOURCES] = {
-       [LC15BTS_POWER_SUPPLY]  = "/var/lc15/pwr-sense/pa-supply/",
+       [LC15BTS_POWER_SUPPLY]  = "/var/lc15/pwr-sense/main-supply/",
        [LC15BTS_POWER_PA0]     = "/var/lc15/pwr-sense/pa0/",
        [LC15BTS_POWER_PA1]     = "/var/lc15/pwr-sense/pa1/",
 };
@@ -52,7 +52,8 @@
 
 int lc15bts_power_sensor_get(
         enum lc15bts_power_source source,
-        enum lc15bts_power_type type)
+        enum lc15bts_power_type type,
+       int *power)
 {
        char buf[PATH_MAX];
        char pwrstr[10];
@@ -82,8 +83,8 @@
                return -EIO;
        }
        close(fd);
-
-       return atoi(pwrstr);
+       *power = atoi(pwrstr);
+       return 0;
 }
 
 
@@ -171,3 +172,39 @@
        
         return retVal;
 }
+
+static const char *vswr_devs[_NUM_VSWR_SENSORS] = {
+       [LC15BTS_VSWR_TX0]              = "/var/lc15/vswr/tx0/vswr",
+       [LC15BTS_VSWR_TX1]              = "/var/lc15/vswr/tx1/vswr",
+};
+
+int lc15bts_vswr_get(enum lc15bts_vswr_sensor sensor, int *vswr)
+{
+       char buf[PATH_MAX];
+       char vswrstr[8];
+       int fd, rc;
+
+       if (sensor < 0 || sensor >= _NUM_VSWR_SENSORS)
+               return -EINVAL;
+
+       snprintf(buf, sizeof(buf)-1, "%s", vswr_devs[sensor]);
+       buf[sizeof(buf)-1] = '\0';
+
+       fd = open(buf, O_RDONLY);
+       if (fd < 0)
+               return fd;
+
+       rc = read(fd, vswrstr, sizeof(vswrstr));
+       vswrstr[sizeof(vswrstr)-1] = '\0';
+       if (rc < 0) {
+               close(fd);
+               return rc;
+       }
+       if (rc == 0) {
+               close(fd);
+               return -EIO;
+       }
+       close(fd);
+       *vswr = atoi(vswrstr);
+       return 0;
+}
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_power.h 
b/src/osmo-bts-litecell15/misc/lc15bts_power.h
index 8963b76..b48cfdc 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_power.h
+++ b/src/osmo-bts-litecell15/misc/lc15bts_power.h
@@ -17,7 +17,8 @@
 
 int lc15bts_power_sensor_get(
        enum lc15bts_power_source source,
-       enum lc15bts_power_type type);
+       enum lc15bts_power_type type,
+       int *volt);
 
 int lc15bts_power_set(
        enum lc15bts_power_source source,
@@ -26,4 +27,12 @@
 int lc15bts_power_get(
         enum lc15bts_power_source source);
 
+enum lc15bts_vswr_sensor {
+       LC15BTS_VSWR_TX0,
+       LC15BTS_VSWR_TX1,
+       _NUM_VSWR_SENSORS
+};
+
+int lc15bts_vswr_get(enum lc15bts_vswr_sensor sensor, int *vswr);
+
 #endif
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_temp.c 
b/src/osmo-bts-litecell15/misc/lc15bts_temp.c
index aa35854..45602dc 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_temp.c
+++ b/src/osmo-bts-litecell15/misc/lc15bts_temp.c
@@ -29,20 +29,19 @@
 
 #include "lc15bts_temp.h"
 
-
 static const char *temp_devs[_NUM_TEMP_SENSORS] = {
-       [LC15BTS_TEMP_SUPPLY]   = "/var/lc15/temp/pa-supply/temp",
-       [LC15BTS_TEMP_SOC]      = "/var/lc15/temp/cpu/temp",
-       [LC15BTS_TEMP_FPGA]     = "/var/lc15/temp/fpga/temp",
-       [LC15BTS_TEMP_LOGRF]    = "/var/lc15/temp/logrf/temp",
-       [LC15BTS_TEMP_OCXO]     = "/var/lc15/temp/ocxo/temp",
-       [LC15BTS_TEMP_TX0]      = "/var/lc15/temp/tx0/temp",
-       [LC15BTS_TEMP_TX1]      = "/var/lc15/temp/tx1/temp",
-       [LC15BTS_TEMP_PA0]      = "/var/lc15/temp/pa0/temp",
-       [LC15BTS_TEMP_PA1]      = "/var/lc15/temp/pa1/temp",
+       [LC15BTS_TEMP_SUPPLY]           = "/var/lc15/temp/main-supply/temp",
+       [LC15BTS_TEMP_SOC]              = "/var/lc15/temp/cpu/temp",
+       [LC15BTS_TEMP_FPGA]             = "/var/lc15/temp/fpga/temp",
+       [LC15BTS_TEMP_RMSDET]   = "/var/lc15/temp/rmsdet/temp",
+       [LC15BTS_TEMP_OCXO]             = "/var/lc15/temp/ocxo/temp",
+       [LC15BTS_TEMP_TX0]              = "/var/lc15/temp/tx0/temp",
+       [LC15BTS_TEMP_TX1]              = "/var/lc15/temp/tx1/temp",
+       [LC15BTS_TEMP_PA0]              = "/var/lc15/temp/pa0/temp",
+       [LC15BTS_TEMP_PA1]              = "/var/lc15/temp/pa1/temp",
 };
 
-int lc15bts_temp_get(enum lc15bts_temp_sensor sensor)
+int lc15bts_temp_get(enum lc15bts_temp_sensor sensor, int *temp)
 {
        char buf[PATH_MAX];
        char tempstr[8];
@@ -69,7 +68,7 @@
                return -EIO;
        }
        close(fd);
-
-       return atoi(tempstr);
+       *temp = atoi(tempstr);
+       return 0;
 }
 
diff --git a/src/osmo-bts-litecell15/misc/lc15bts_temp.h 
b/src/osmo-bts-litecell15/misc/lc15bts_temp.h
index aca8fe2..35d81f1 100644
--- a/src/osmo-bts-litecell15/misc/lc15bts_temp.h
+++ b/src/osmo-bts-litecell15/misc/lc15bts_temp.h
@@ -5,7 +5,7 @@
        LC15BTS_TEMP_SUPPLY,
        LC15BTS_TEMP_SOC,
        LC15BTS_TEMP_FPGA,
-       LC15BTS_TEMP_LOGRF,
+       LC15BTS_TEMP_RMSDET,
        LC15BTS_TEMP_OCXO,
        LC15BTS_TEMP_TX0,
        LC15BTS_TEMP_TX1,
@@ -22,6 +22,7 @@
        _NUM_TEMP_TYPES
 };
 
-int lc15bts_temp_get(enum lc15bts_temp_sensor sensor);
+int lc15bts_temp_get(enum lc15bts_temp_sensor sensor, int *temp);
+
 
 #endif

-- 
To view, visit https://gerrit.osmocom.org/3277
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Iabbaedc84aaaa594150a4e5445c16dd1f6f89858
Gerrit-PatchSet: 4
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Owner: Max <msur...@sysmocom.de>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Minh-Quang Nguyen <minh-quang.ngu...@nutaq.com>
Gerrit-Reviewer: jfdionne <jf.dio...@nutaq.com>

Reply via email to