Data Logger BLE Cellular Board
Loading...
Searching...
No Matches
jfet_commandLine.c
Go to the documentation of this file.
1/*!
2 * \file jfet_commandLine.c
3 *
4 * \brief Command Line Interface (CLI) functions and commands
5 *
6 * \copyright J Factor Embedded Technologies LLC. 2026
7 * \copyright TJM Embedded Software LLC. 2026
8 * \author T. J. Mulrooney
9 */
10/*
11 * All Rights Reserved
12 * UNPUBLISHED, LICENSED SOFTWARE.
13 *
14 * CONFIDENTIAL AND PROPRIETARY INFORMATION
15 * WHICH IS THE PROPERTY OF J-Factor Embedded Technologies.
16 *
17 */
18#define __USE_MINGW_ANSI_STDIO 1
19
20// #include <event_manager.h>
21// #include <drivers/uart.h>
22#include "jfet_files/common.h"
24#include <zephyr/drivers/i2c.h>
25// #include "cloud/cloud_codec/cloud_codec.h"
26#include "HDC2080.h"
27#include "ncs_version.h"
28#include <bluetooth/services/nus.h>
29#include <zephyr/drivers/uart.h>
30#include <zephyr/pm/device.h>
31
32////#include <net/aws_iot.h>
33// #include "time.h"
34// #include <date_time.h>
35//
36///* prottypes */
37// uint8_t getLine(void);
38void executeCmd(char *line);
39int8_t getCLICmd(char *line);
40void cliADC();
41void cliBatMon();
42void cliBME688();
43void cliBME688CS();
44void cliDeviceID();
45void cliDeviceInfo();
46void cliCustomer();
47void cliDateTime();
48void cliDutyCycle();
49void cliFlashErase();
51void cliFlashFillPage();
52void cliFlashID();
53void cliFlashNSS();
54void cliFlashReadPage();
55void cliFlashStatus();
57void cliGroup();
58void cliHelp();
59void cliHumidity();
60void cliNouart0(void);
61void cliI2CRead();
62void cliI2CWrite();
63void cliIgnoreBME688();
64void cliLocation();
65void cliManualTrigger(void);
66void cliPublishNow();
67void cliReset();
68void cliResetCause();
69void cliSaved();
70void cliSensorID();
71void cliSensorName();
72void cliSensors();
73void cliSilent();
74void cliTemperature();
75void cliVersion();
76void displayHelp(char c);
77int uart_init(void);
78
79// void displayTouchHandler(unsigned char *ptrBuf, int cnt);
80////int aws_iot_disconnect(void);
81// int time_NTP_server_get(void);
82//
83///* external */
84////extern struct cloud_data_cfg current_cfg;
85// extern struct time_aux {
86// int64_t date_time_utc;
87// int64_t last_date_time_update;
88// } time_aux;
89//
90////#include <strings.h>
91// enum at_cmd_state cmd_state; //!<state of AT command executed from command line
92//
93///* globals */
94// uint8_t escapeSeen = 0; //!<escape sequence seen
95
96/* enums */
140
141#define LINE_SIZE 90 //!< maximum number of characters on a CLI line
142#define NUM_LINES 10 //!< maximum number of lines in saved history
143
144/* Prototypes */
145
146/* externs */
147// extern UART_HandleTypeDef UartHandle;
148
149/* Locals */
150// static char line[LINE_SIZE]; //!< character array read
151////char lineDownlink[200]; //!< character array downlink
152////char downlinkIMEI[30]; //<! character array fro downlink IMEI
153static char lineTmp[LINE_SIZE]; //!< tempory line saved
154// static char lastLine[NUM_LINES][LINE_SIZE]; //!< array of previous command lines
155// static int8_t indexNextLineIn = 0; //!< index of next position to save current command line
156// static int8_t indexNextLineOut = 0; //!< index of next position to read out saved command lines
157// static int8_t linesInBuffer = 0; //!< number of lines in command line buffer
158// static int8_t charCount; //!< number of characters in the current command line
159// static int8_t cursorPosition; //!< current cursor position in the current command line
160//
161//
162/* sensor types and state (present = 1) */
163
164char *sensorTypeNames[] = //!< sensor types and state (present = 1)
165 {
166 "HDC2080 - temperature/Humidty Sensor(I2C 0x40)",
167 "W25Q64JV - 64MB Flash memory(SPI CS1)",
168 "BME688 - Gas/Pressure/temperature/Humidty Sensor(SPI CS2)",
169 "Unknown",
170};
171
172char const *validCLICmds[] = //!< array of valid commands - case insensitive
173 {
174 "adc",
175 // "alarmsenabled",
176 "batmon",
177 "bme688",
178 "bme688cs",
179 "datetime",
180 "deviceid",
181 "deviceinfo",
182 "customer",
183 // "distributor",
184 "dutycycle",
185 "flasherase",
186 "flasherasesector",
187 "flashfillpage",
188 "flashid",
189 "flashnss",
190 "flashreadpage",
191 "flashstatus",
192 "flashwritepage",
193 "flashparameters",
194 "group",
195 "help",
196 "humidity",
197 "i2cread",
198 "i2cwrite",
199 "ignorebme688",
200 "location",
201 "manualtrigger",
202 "nouart0",
203 "publishnow",
204 "rescan",
205 "reset",
206 "resetcause",
207 "saved",
208 "sensorid",
209 "sensorname",
210 "silent",
211 "sensors",
212 "temp",
213 "version",
214};
215
216char const *helpMessages[] = {
217 "adc - display Battery voltage AIN0",
218 // "alarmsenabled [0/1/t/T/f/F]- display/set alarms enabled",
219 "batmon - <0 | 1> enable or disable Battery monitor",
220 "bme688 <n> - read n sample from BME688",
221 "bme688cs <0 | 1> - display/set BME688 CS",
222 "datetime save data/time from gateway"
223 "deviceid - display Device ID",
224 "deviceinfo - display device information",
225 "customer [X]- display/set customer",
226 // "distributor [X]- display/set distributor",
227 "dutycycle [0 <minutes> | 1-7] - 0=minutes,1=2min,2=1min,3=10secs,4=5secs,5=1secs,6=.5secs,7=.2secs",
228 "flasherase - erase entire memory",
229 "flasherasesector - [sector] erase 256K Byte sector X (default 0) range ( 0 -> 31)",
230 "flashfillpage [page data length] - fill length pages with data starting at page",
231 "flashid - display serial flash ID",
232 "flashnss <0 | 1> - set SPI NSS",
233 "flashparameters - list the saved flash parameters",
234 "flashreadpage [page length] - read length pages starting at page",
235 "flashstatus - display serial flash status registers",
236 "flashwritepage page address data - write data to address in page",
237 //// "gps - display cirrent GPS location",
238 //// "gpsenable - [0/1] enable or disable gps",
239 //// "gpsfixcheck - [n] display/set GPS fix check time",
240 //// "gpsexternal - [0/1] external or internal gps",
241 "group [X]- display/set group",
242 "help [c] - display list of valid commands starting with c",
243 "humidity- display humidity",
244 "i2cread [add reg length] - read length bytes from I2C address starting at r",
245 "i2cwrite add reg data length - write byte to I2C address at reg",
246 "ignorebme688 [0 | 1] - display set ignore BME688 flag",
247 "location [X]- display/set location",
248 "manualtrigger [0 | 1] - display set manual trigger flag",
249 "nouart0 [0/1] - display/set No UART0",
250 "publishnow- publish a BLE payload now",
251 "rescan - rescan for connected devices",
252 "reset [x]- reset the board any paramter causes a WDT reset",
253 "resetCause - display reason for last reset ",
254 "saved [clear | n] [count]- display count saved flash JSON packets or clear all saved packets",
255 "sensorid [X]- display/set sensor ID",
256 "sensorname - display/set sensor name",
257 "sensors - display available sensors",
258 "silent [0 | 1]- display/set silent flag",
259 "temp- display sensor temperatures ",
260 "version - display version information",
261 "END",
262}; //!< array of help messages
263
264/*!
265 * \fn void executeCmd(char *line)
266 *
267 * \brief executes the command in line array.
268 *
269 */
270void executeCmd(char *line) {
271 int8_t cmd;
272 // uint32_t i;
273 // int ret;
274 // uint32_t length;
275 // char str[80];
276 //// uint32_t pageAddress;
277 // uint8_t write_buffer[DATA_LENGTH];
278 //// struct tm time;
279 // int j;
280 // int k;
281 //// int l,m;
282 // float temp, tempMin, tempMax;
283 // float tempHum;
284 // //float uva,uvb,uvi;
285 // double testd = 1.23;
286 // enum at_cmd_state state;
287 // char *ceregState[] =
288 // {
289 // "Not registered. User Equipment (UE) is not currently searching for an operator to register to",
290 // "Registered, home network",
291 // "Not registered, but UE is currently trying to attach or searching an operator to register to",
292 // "Registration denied",
293 // "Unknown (e.g. out of E-UTRAN coverage)",
294 // "Registered, roaming",
295 // "Not registered due to Universal Integrated Circuit Card (UICC) failure",
296 // };
297 strcpy(lineTmp, line); /* save command line */
298 cmd = getCLICmd(line);
299 myPrintk("\r\n");
300 // myPrintk("cmd: %d numParameters: %d\r\n",cmd,numParameters);
301
302 /* execute command */
303 switch (cmd) {
304 case ADCX:
305 cliADC();
306 break; /* read and display ADC voltage */
307 case BATMON:
308 cliBatMon();
309 break; /* set Battery Monitor GPIO */
310 case BME688:
311 cliBME688();
312 break; /* set BME688 read */
313 case BME688CS:
314 cliBME688CS();
315 break; /* set BME688 CS GPIO */
316 case CUSTOMER:
317 cliCustomer();
318 break; /* display Customer ID */
319 case DATETIME:
320 cliDateTime();
321 break; /* display Device ID*/
322 case DEVICEID:
323 cliDeviceID();
324 break; /* display Device ID*/
325 case DEVICEINFO:
327 break; /* display Device Information */
328 case DUTYCYCLE:
329 cliDutyCycle();
330 break; /* display Device ID*/
331 case FLASHERASE:
333 break; /* erase Flash entire device */
334 case FLASHERASESECTOR:
336 break; /* erase Flash sector */
337 case FLASHFILLPAGE:
339 break; /* fill flash page */
340 case FLASHID:
341 cliFlashID();
342 break; /* display Flash ID */
343 case FLASHNSS:
344 cliFlashNSS();
345 break; /* set/clear Flash NSS */
346 case FLASHPARAMETERS:
348 break; /* display all Flash Parameters */
349 case FLASHREADPAGE:
351 break; /* read n pages of Flash */
352 case FLASHSTATUS:
354 break; /* display Flash Status Info */
355 case FLASHWRITEPAGE:
357 break; /* write a byte to a page */
358 case GROUP:
359 cliGroup();
360 break; /* display group information */
361 case HELP:
362 cliHelp();
363 break; /* display help message */
364 case HUMIDITY:
365 cliHumidity();
366 break; /* display Humidity */
367 case I2CREAD:
368 cliI2CRead();
369 break; /* I2C read */
370 case I2CWRITE:
371 cliI2CWrite();
372 break; /* I2C Write */
373 case NOUART0:
374 cliNouart0();
375 break; /* set/display nouart0 */
376 case IGNOREBME688:
378 break; /* display/set ignore BME688 flag */
379 case LOCATION:
380 cliLocation();
381 break; /* display/set location */
382 case MANUALTRIGGER:
384 break; /* display/set manual trigger */
385 case PUBLISHNOW:
387 break; /* Publish BLE data immediately */
388 case RESCAN:
389 rescan();
390 break; /* rescan for connected devices */
391 case RESETX:
392 cliReset();
393 break; /* software reset processor */
394 case RESETCAUSE:
396 break; /* processor reset cause */
397 case SAVED:
398 cliSaved();
399 break; /* display connected sensors */
400 case SENSORID:
401 cliSensorID();
402 break; /* display/set sensor ID */
403 case SENSORNAME:
405 break; /* display/set sensor name */
406 case SENSORS:
407 cliSensors();
408 break; /* display connected sensors */
409 case SILENT:
410 cliSilent();
411 break; /* display connected sensors */
412 case TEMP:
414 break; /* display temperature */
415 case VERSIONX:
416 cliVersion();
417 break; /* display Version Info */
418
419 default:
420 if (((line[0] == 'a') || (line[0] == 'A')) && ((line[1] == 't') || (line[1] == 'T')))
421 break;
422 if (strlen(line) != 0) {
423 myPrintk("Unknown cmd: %s\r\nType help for list of valid commands\r\n", line);
424 // linesInBuffer--;
425 // indexNextLineIn--;
426 // if(linesInBuffer == NUM_LINES)
427 // indexNextLineIn = NUM_LINES -1;
428 }
429 break;
430 }
431}
432
433/*!
434 * \fn int8_t getCLICmd(char *line)
435 *
436 * \brief parses command line to find position of command in validCLICmds array.
437 *
438 * goes through line array separated by spaces. cmdLineParameter[numParameters]\n
439 * is an array of pointers to the various parameters in the line until the end of line then\n
440 * searches cmd array for a match in validCLICmds array.
441 *
442 * \return int8 - position of command in command array if found. -1 if not found\n
443 */
444int8_t getCLICmd(char *line) {
445 uint8_t i;
446 int len = strlen(line);
447
448 /* parse all parameters on the command line into cmdLineparameter array */
449 numParameters = 0; /* no parameters seen yet */
450
451 cmdLineParameter[numParameters++] = &line[0];
452 for (i = 0; i < len; i++) {
453 // printk("%d %c\r\n", i, line[i]);
454 if (line[i] == ' ') {
455 line[i] = '\0';
456 cmdLineParameter[numParameters++] = &line[i + 1];
457 }
458 // printk("%d %s\r\n", i, cmdLineParameter[i - 1]);
459 }
460 line[i] = '\0';
461
462#if 0
463 for(i=0;i<len+1;i++)
464 {
465 myPrintk("%d %c %02X\r\n",i,line[i],line[i]);
466 }
467 for(i=0;i<numParameters;i++)
468 {
469 myPrintk("i: %d Param: %s\r\n",i,cmdLineParameter[i]);
470 }
471#endif
472
473 for (i = 0; i < sizeof(validCLICmds) / sizeof(validCLICmds[0]); i++) {
474 if (strcmp(validCLICmds[i], cmdLineParameter[0]) == 0) {
475 return i;
476 }
477 }
478 return -1;
479}
480
481/*!
482 * \fn void displayHelp(char c)
483 *
484 * \brief displays a list of all available CLI commands
485 *
486 * \param c check for only help messages beginning with c
487 *
488 */
489void displayHelp(char c) {
490// #ifndef MEMORYSAVE
491#if 1
492 int i;
493
494 myPrintk("Valid Commands (%c)\r\n", c);
495 for (i = 0; 1; i++) {
496 if (strstr(helpMessages[i], "END") != NULL) {
497 break;
498 }
499 if ((helpMessages[i][0] == c) || (c == 'z')) {
500 myPrintk("%s\r\n", helpMessages[i]);
501 }
502 }
503#endif
504}
505//
506/////*!
507//// * \fn char * replace_char(char* str, char find, char replace)
508//// *
509//// * \brief replace characters in a string
510//// *
511//// * \param str pointer to string to search
512//// * \param find character to look for
513//// * \param replace character to replace found character with
514//// *
515//// * \return char * pointer to new string with replaced characters
516//// */
517////char * replace_char(char* str, char find, char replace)
518////{
519//// char *current_pos = strchr(str,find);
520//// while (current_pos)
521//// {
522//// *current_pos = replace;
523//// current_pos = strchr(current_pos,find);
524//// }
525//// return str;
526////}
527
528/**
529 * \fn void cliADC(void)
530 *
531 * \brief CLI command to sample and display the ADC voltage.
532 *
533 * This function triggers an ADC sampling process and prints the resulting
534 * voltage from the primary channel to the console.
535 */
536void cliADC(void) {
537 int err;
538
539 /* Perform an ADC sample to read the current voltage from hardware */
540 err = adc_sample();
541 if (err) {
542 myPrintk("Error in adc sampling: %d\n", err);
543 }
544
545 /* Display the sampled voltage from the first channel (index 0) */
546 myPrintk("ADC: %3.2f\r\n", (double)adc_voltage[0]);
547 return;
548}
549
550/**
551 * \fn void cliBatMon(void)
552 *
553 * @brief CLI command to enable or disable the battery monitor hardware.
554 *
555 * This function parses the command line parameter to set the state of the
556 * battery enable (BATEN) GPIO pin.
557 */
558void cliBatMon(void) {
559 int i;
560
561 i = 0;
562 /* Check if exactly one argument (0 or 1) is provided */
563 if (numParameters != 2) {
564 myPrintk("format batmon <0 | 1>\r\n");
565 return;
566 }
567 /* Convert parameter string to integer and update GPIO state */
568 i = atoi(cmdLineParameter[1]);
569 gpio_pin_set(baten.port, baten.pin, i);
570 /* Provide feedback to the user via console */
571 myPrintk("Battery Monitor: %s\r\n", i ? "Enabled" : "Disabled");
572 return;
573}
574
575/**
576 * \fn void cliBME688(void)
577 *
578 * @brief CLI command to read and display data from the BME688 sensor
579 */
580void cliBME688(void) {
581 int count = 1; // Default to 1 sample if no argument provided
582 int i;
583
584 /* Check if user provided a specific number of samples */
585 if (numParameters == 1) {
586 count = 1;
587 }
588 if (numParameters == 2) {
589 count = atoi(cmdLineParameter[1]);
590 }
591
592 /* Print header for the sensor data table */
593 myPrintk("Sample\tTemperature(deg C)\tPressure(Pa)\tHumidity(%%)\tGas resistance(ohm)\tStatus\n");
594 for (i = 0; i < count; i++) {
595 /* Fetch data from the sensor */
597 myPrintk("%u\t%.2f", i, (double)BME688Data.temperature);
598 myPrintk(" \t\t\t%.2f", (double)BME688Data.pressure);
599 myPrintk(" \t%.2f", (double)BME688Data.humidity);
600 /* Display gas resistance and status bits */
601 myPrintk(" \t\t%.2f", (double)BME688Data.gas_resistance);
602 myPrintk(" \t\t0x%02X\r\n", BME688Data.status);
603 }
604 return;
605}
606
607/**
608 * \fn void cliBME688CS(void)
609 * \brief CLI command to manually control the BME688 SPI Chip Select (CS) pin.
610 */
611void cliBME688CS(void) {
612 int i;
613 int bme688cs = 0;
614 ;
615
616 /* Validate that exactly one argument (0 or 1) is provided */
617 if (numParameters != 2) {
618 myPrintk("format bme688cs 0/1\r\n");
619 return;
620 }
621 if (numParameters == 2) {
622 i = atoi(cmdLineParameter[1]);
623 if (i == 0) {
624 /* Set GPIO high to de-assert the active-low Chip Select */
625 gpio_pin_set(spics2n.port, spics2n.pin, 1);
626 bme688cs = 0;
627 } else {
628 /* Set GPIO low to assert the active-low Chip Select */
629 gpio_pin_set(spics2n.port, spics2n.pin, 0);
630 bme688cs = 1;
631 }
632 }
633 myPrintk("BME688CS: %d\r\n", bme688cs);
634 return;
635}
636
637/**
638 * \fn void cliCustomer(void)
639 * \brief CLI command to set or display the customer name in flash parameters.
640 */
642 /* If arguments are provided, update the customer name */
643 if (numParameters > 1) {
644 /* Clear existing buffer */
645 for (int i = 0; i < sizeof(flashParameters.customer); i++)
646 flashParameters.customer[i] = '\0';
647
648 /* Copy new customer name from the raw command line (offset 9 for "customer ") */
649 strncpy(flashParameters.customer, &lineTmp[9], 39);
650 setFlashxParameters(false);
651 }
652 myPrintk("Customer: %s\r\n", flashParameters.customer);
653}
654
655/**
656 * \fn void int64_to_string(int64_t num, char *str)
657 *
658 * @brief Converts a 64-bit signed integer to a null-terminated string.
659 *
660 * @param num The 64-bit integer to convert.
661 * @param str Pointer to the destination buffer (must be large enough to hold the result).
662 */
663void int64_to_string(int64_t num, char *str) {
664 /* Handle negative numbers */
665 if (num < 0) {
666 *str++ = '-';
667 num = -num;
668 }
669
670 char buffer[20]; /* Temporary buffer to hold digits in reverse order (max 19 digits + sign) */
671 int i = 0;
672 /* Extract digits one by one */
673 do {
674 buffer[i++] = num % 10 + '0';
675 num /= 10;
676 } while (num != 0);
677
678 /* Reverse the digits into the output string */
679 while (i > 0) {
680 *str++ = buffer[--i];
681 }
682 *str = '\0';
683}
684
685/*!
686 * \fn void cliDateTime()
687 * \brief CLI command to set or display the gateway epoch timestamp.
688 */
690 char str[20]; // Buffer to hold the string representation of the epoch
691
692 /* Check if a new epoch timestamp was provided as an argument */
693 if (numParameters == 2) {
694 // printk("cmdLineParameter[1] %s\r\n", cmdLineParameter[1]);
695 /* Convert the string parameter to a 64-bit integer */
697 // int64_to_string(gatewayDateTime, gatewayEpoch);
698 // sprintf(myStr, "%s\t%s t1 %3.2f h1 %3.2f", gatewayEpoch, devIDStr, (double)hdcTemp, (double)hdcHumidity);
699 // bt_nus_send(NULL, myStr, strlen(myStr));
700 // myPrintkW("%s\r\n", myStr);
701 }
702 /* Convert the current gatewayDateTime back to a string for display */
704 // printk("gateway Date/Time (epoch) %s\r\n", str);
705
706 /* if manual trigger set send indication to waiting loop */
707 if (flashParameters.manualTrigger) {
709 k_sem_give(&hdc_rdy_seen); /* indicate HDC2080 RDY seen */
710 }
711}
712
713/** \fn void cliDeviceID(void)
714 *
715 * \brief Display the unique device identifier string
716 */
717void cliDeviceID(void) { myPrintkS("Device ID: %s\r\n", devIDStr); }
718
719/**
720 * \fn void cliDeviceInfo(void)
721 *
722 * \brief Transmit comprehensive device information over BLE NUS service.
723 *
724 * This function iterates through various device parameters (ID, Name, Customer, etc.)
725 * and sends them both to the local console and over the Bluetooth NUS service.
726 */
727void cliDeviceInfo(void) {
728 char myStr[256];
729 char str1[128];
730
731 myPrintkS("Device Information \r\n");
732 /* Set flag to indicate the system is currently transmitting device metadata */
733 sendingDeviceInfo = true;
734
735 /* send sensor ID*/
736 myPrintkS("Sensor ID: %s\r\n", flashParameters.sensorID);
737 sprintf(myStr, "%0d\t%s id %s", bleIndex, devIDStr, flashParameters.sensorID);
738 myPrintkS("%s\r\n", myStr);
739 bt_nus_send(NULL, myStr, strlen(myStr));
740 k_sleep(K_SECONDS(2)); /* Delay to prevent flooding the BLE link */
741
742 myPrintkS("Sensor Name: %s\r\n", flashParameters.sensorName);
743 sprintf(myStr, "%0d\t%s sn %s", bleIndex, devIDStr, flashParameters.sensorName);
744 myPrintkS("%s\r\n", myStr);
745 bt_nus_send(NULL, myStr, strlen(myStr));
746 k_sleep(K_SECONDS(2));
747
748 myPrintkS("Customer: %s\r\n", flashParameters.customer);
749 sprintf(myStr, "%0d\t%s cu %s", bleIndex, devIDStr, flashParameters.customer);
750 myPrintkS("%s\r\n", myStr);
751 bt_nus_send(NULL, myStr, strlen(myStr));
752 k_sleep(K_SECONDS(2));
753
754 myPrintkS("Group: %s\r\n", flashParameters.group);
755 sprintf(myStr, "%0d\t%s gr %s", bleIndex, devIDStr, flashParameters.group);
756 myPrintkS("%s\r\n", myStr);
757 bt_nus_send(NULL, myStr, strlen(myStr));
758 k_sleep(K_SECONDS(2));
759
760 myPrintkS("Location: %s\r\n", flashParameters.location);
761 sprintf(myStr, "%0d\t%s lo %s", bleIndex, devIDStr, flashParameters.location);
762 myPrintkS("%s\r\n", myStr);
763 bt_nus_send(NULL, myStr, strlen(myStr));
764 k_sleep(K_SECONDS(2));
765
766 // sprintf(str1, "%s%sV %d.%02d %s%s", BOARD_NAME, BOARD_NAME_EXT, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE, VERSION_DATE_EXT);
767 if (flashParameters.nouart0 == false) {
768 sprintf(str1, "V %d.%02d %s%s", VERSION_MAJOR, VERSION_MINOR, VERSION_DATE, VERSION_DATE_EXT1);
769 } else {
770 sprintf(str1, "V %d.%02d %s%s", VERSION_MAJOR, VERSION_MINOR, VERSION_DATE, VERSION_DATE_EXT2);
771 }
772#ifndef CONFIG_SERIAL
773 sprintf(str1, "V %d.%02d %s%s", VERSION_MAJOR, VERSION_MINOR, VERSION_DATE, VERSION_DATE_EXT3);
774#endif
775
776 myPrintkS("Version: %s\r\n", str1);
777 sprintf(myStr, "%0d\t%s ve %s", bleIndex, devIDStr, str1);
778 myPrintkS("%s\r\n", myStr);
779 bt_nus_send(NULL, myStr, strlen(myStr));
780 k_sleep(K_SECONDS(2));
781
782 sprintf(str1, "nRF52832");
783 myPrintkS("Board Version: %s\r\n", str1);
784 sprintf(myStr, "%0d\t%s brdV %s", bleIndex, devIDStr, str1);
785 myPrintkS("%s\r\n", myStr);
786 bt_nus_send(NULL, myStr, strlen(myStr));
787 k_sleep(K_SECONDS(2));
788
789 sprintf(str1, "%s%s", BOARD_NAME, BOARD_NAME_EXT);
790 myPrintkS("Hardware Version: %s\r\n", str1);
791 sprintf(myStr, "%0d\t%s hwV %s", bleIndex, devIDStr, str1);
792 myPrintkS("%s\r\n", myStr);
793 bt_nus_send(NULL, myStr, strlen(myStr));
794 k_sleep(K_SECONDS(2));
795
796 sprintf(str1, "nRF52832");
797 myPrintkS("Chip version: %s\r\n", str1);
798 sprintf(myStr, "%0d\t%s hwC %s", bleIndex, devIDStr, str1);
799 myPrintkS("%s\r\n", myStr);
800 bt_nus_send(NULL, myStr, strlen(myStr));
801 k_sleep(K_SECONDS(2));
802
803 /* Reset flag to resume normal sensor data transmission */
804 sendingDeviceInfo = false;
805
806 if (flashParameters.manualTrigger) {
807 myPrintkW("Manual trigger Enabled. Waiting for datetime command from gateway.\r\n");
809 }
810}
811
812/**
813 * \fn void cliDutyCycle(void)
814 *
815 * \brief CLI command to configure the sensor data sampling interval.
816 */
817void cliDutyCycle(void) {
818 int hdcCode; //!< HDC2080 specific rate code
819 char *end; //!< Pointer for strtoul parsing
820 char str[20]; //!< String representation of the duty cycle
821
822 /* Handle case where only the HDC2080 rate code is provided */
823 if (numParameters == 2) {
824 hdcCode = strtoul(cmdLineParameter[1], &end, 10);
825 if ((hdcCode > 0) && (hdcCode <= 7)) {
826 flashParameters.dutyCycle = hdcCode;
827 /* Apply the hardware conversion rate to the sensor */
828 setRate(hdcCode); /* set auto conversion rate */
829 setFlashxParameters(false);
830 } else {
831 myPrintk("format dutycycle [HDC2080 Setting 1-7] [minutes > 2 if setting == 0]");
832 return;
833 }
834 }
835 /* Handle case where manual minutes are provided (code must be 0) */
836 if (numParameters == 3) {
837 hdcCode = strtoul(cmdLineParameter[1], &end, 10);
838 hdcMinutes = strtoul(cmdLineParameter[2], &end, 10);
839 if ((hdcCode == 0) && (hdcMinutes > 2)) {
840 flashParameters.dutyCycle = hdcMinutes + 7;
841 /* Default to 1 minute hardware rate for long duty cycles */
842 setRate(ONE_MINS); /* set auto conversion rate */
843 setFlashxParameters(false);
844 } else {
845 myPrintk("format dutycycle [HDC2080 Setting 1-7] [minutes > 2 if setting == 0]");
846 return;
847 }
848 }
849 /* Display the current duty cycle status to the user */
850 if (flashParameters.dutyCycle < 7) {
851 switch (flashParameters.dutyCycle) {
852 case 1:
853 strcpy(str, "2 Minutes");
854 break;
855
856 case 2:
857 strcpy(str, "1 Minute");
858 break;
859
860 case 3:
861 strcpy(str, "10 Seconds");
862 break;
863
864 case 4:
865 strcpy(str, "5 Seconds");
866 break;
867
868 case 5:
869 strcpy(str, "1 Second");
870 break;
871
872 case 6:
873 strcpy(str, ".5 Seconds");
874 break;
875
876 case 7:
877 strcpy(str, ".2 Seconds");
878 break;
879 }
880 myPrintk("Duty Cycle: %d Setting %s\r\n", flashParameters.dutyCycle, str);
881 } else {
882 /* Calculate minutes from the offset dutyCycle value */
883 myPrintk("Duty Cycle: %d Minutes\r\n", flashParameters.dutyCycle - 7);
884 }
885 return;
886}
887
888/** \fn void cliFlashErase(void)
889 *
890 * \brief CLI command to erase the entire external flash memory.
891 */
892void cliFlashErase(void) {
893 /* Perform a full chip erase of the external flash memory */
894 flashxErase();
895
896 /* Notify user of completion */
897 myPrintk("Flash Erase complete\r\n");
898
899 /* Reset the local flash parameters structure to default values
900 * to ensure the RAM state matches the cleared flash state.
901 */
903 return;
904}
905
906/**
907 * \fn void cliFlashEraseSector(void)
908 *
909 * \brief CLI command to erase a specific 4KB sector of the external flash.
910 *
911 * If no parameter is provided, it defaults to erasing the parameter storage sector.
912 * Erasing the parameter sector also triggers a reset of the local parameter structure.
913 */
915 uint32_t address;
916 char *end;
917
918 if (numParameters == 1) {
919 /* Default to the start of the parameter storage if no sector specified */
920 address = FLASHPARAMETERSTART;
921 } else if (numParameters == 2) {
922 address = strtoul(cmdLineParameter[1], &end, 16);
923 } else {
924 myPrintk("format flasherasesector [sector]");
925 return;
926 }
927 if (address >= 32) {
928 /* Limit check based on the expected memory map/device size */
929 myPrintk("Sector address %d >= 32\r\n", address);
930 return;
931 }
932 /* Execute the hardware-level sector erase */
933 flashxEraseSector(address);
934 myPrintk("Flash Sector %d Erase complete\r\n", address);
935 if (address == FLASHPARAMETERSTART) {
936 /* Clear local RAM copy of parameters if the primary flash sector was wiped */
938 }
939}
940
941/**
942 * \fn void cliFlashFillPage(void)
943 *
944 * \brief CLI command to fill one or more flash pages with a specific 32-bit data pattern.
945 */
947 int address = 0;
948 int length = 1;
949 int32_t data;
950 int i;
951 char *end;
952
953 address = 0;
954 data = 0;
955 length = 1;
956 /* Parse arguments: [address] [data] [length] */
957 if (numParameters == 2) {
958 address = strtoul(cmdLineParameter[1], &end, 16);
959 } else if (numParameters == 3) {
960 address = strtoul(cmdLineParameter[1], &end, 16);
961 data = strtoul(cmdLineParameter[2], &end, 16);
962 } else if (numParameters == 4) {
963 address = strtoul(cmdLineParameter[1], &end, 16);
964 data = strtoul(cmdLineParameter[2], &end, 16);
965 length = atoi(cmdLineParameter[3]);
966 } else if (numParameters > 4) {
967 myPrintk("format flashFill [address][data] [length]");
968 return;
969 }
970 /* Validate page address range */
971 if (address >= 32768) {
972 myPrintk("Page address %d >= 32768\r\n", address);
973 return;
974 }
975 /* Iterate through the specified number of pages and write the pattern */
976 for (i = 0; i < length; i++, address++) {
977 myPrintk("flashFill page: 0x%X data: 0x%02X\r\n", address, data);
978 flashxFillPage(address, data);
979 myPrintk("flashFill complete\r\n");
980 }
981 return;
982 ;
983}
984
985/**
986 * \fn void cliFlashID(void)
987 *
988 * \brief CLI command to read and display the unique Flash memory ID.
989 *
990 * This function retrieves the manufacturer and device identification
991 * from the external SPI flash and prints it to the console.
992 */
993void cliFlashID(void) {
994 uint8_t flashIDIn[5];
995
996 readNVFlashxID(flashIDIn);
997 myPrintk("Flash ID: 0x%02X 0x%02X 0x%02X\r\n", flashIDIn[0], flashIDIn[1], flashIDIn[2]);
998}
999
1000/**
1001 * \fn void cliFlashNSS(void)
1002 *
1003 * \brief CLI command to manually toggle the SPI Chip Select (NSS) for the Flash memory.
1004 *
1005 * This is used for hardware debugging to verify the SPI CS1 line state.
1006 */
1007void cliFlashNSS(void) {
1008 int i;
1009 int flashNSS = 0;
1010 ;
1011
1012 if (numParameters != 2) {
1013 myPrintk("format flashnss 0/1\r\n");
1014 return;
1015 }
1016 if (numParameters == 2) {
1017 i = atoi(cmdLineParameter[1]);
1018 if (i == 0) {
1019 gpio_pin_set(spics1n.port, spics1n.pin, 1); /* active low so turn on */
1020 flashNSS = 0;
1021 } else {
1022 gpio_pin_set(spics1n.port, spics1n.pin, 0); /* active low so turn off */
1023 flashNSS = 1;
1024 }
1025 }
1026 myPrintk("flashnss: %d\r\n", flashNSS);
1027 return;
1028}
1029
1030/**
1031 * \fn void cliFlashReadPage(void)
1032 *
1033 * \brief CLI command to read and display the contents of external flash pages.
1034 *
1035 * This function reads 256-byte pages from the SPI flash and displays them
1036 * in a hex-dump format with corresponding ASCII representation.
1037 */
1039 int address = 0;
1040 int length = 1;
1041 int i, j, k;
1042 char *end;
1043 char ascii[17];
1044 char str[80];
1045
1046 /* Parse page address and optional number of pages to read */
1047 if (numParameters == 2) {
1048 address = strtoul(cmdLineParameter[1], &end, 16);
1049 } else if (numParameters == 3) {
1050 address = strtoul(cmdLineParameter[1], &end, 16);
1051 length = atoi(cmdLineParameter[2]);
1052 }
1053 if (address >= 32768) {
1054 myPrintk("Page address %d >= 32768\r\n", address);
1055 return;
1056 }
1057
1058 /* Iterate through and read the requested number of pages */
1059 for (k = 0; k < length; k++, address++) {
1060 flashxReadPage(address, flashReadIn);
1061 myPrintk("Read Page 0x%X\r\n", address);
1062 ascii[0x10] = '\0';
1063 /* Process 256 bytes per page */
1064 for (i = 0; i < 256; i++) {
1065 if ((i % 0x10) == 0) {
1066 if (i == 0) {
1067 sprintf(str, "0x%06X ", (unsigned int)(address * 256) + i);
1068 } else {
1069 /* Print the ASCII column and start a new line */
1070 myPrintk(str, " %s\r\n0x%06X ", ascii, (unsigned int)(address * 256) + i);
1071 for (j = 0; j < sizeof(ascii); j++) {
1072 ascii[j] = '\0';
1073 }
1074 }
1075 myPrintk("%s", str);
1076 }
1077 /* Filter non-printable characters for the ASCII display */
1078 if ((flashReadIn[i] < 0x20) || (flashReadIn[i] > 0x7E)) {
1079 ascii[i % 0x10] = '.';
1080 } else {
1081 ascii[i % 0x10] = flashReadIn[i];
1082 }
1083 /* Print the hex value of the byte */
1084 myPrintk("%02X ", flashReadIn[i]);
1085 }
1086 myPrintk(" %s\r\n", ascii);
1087 }
1088 return;
1089}
1090
1091/**
1092 * \fn void cliFlashStatus(void)
1093 *
1094 * \brief CLI command to read and display the status registers of the external flash.
1095 *
1096 * This function reads the three status registers from the SPI flash and decodes
1097 * individual bits such as Busy, Write Enable, and Protection settings.
1098 */
1099void cliFlashStatus(void) {
1100 uint8_t flashStatusIn[3];
1101
1102 readNVFlashxStatus(flashStatusIn);
1103 myPrintk("Flash Status 0x%02X 0x%02X 0x%02X\r\n", flashStatusIn[0], flashStatusIn[1], flashStatusIn[2]);
1104 myPrintk("Status register 1\r\n");
1105 myPrintk("%sBusy\r\n", flashStatusIn[0] & 0x01 ? "" : "Not ");
1106 myPrintk("Write %sabled\r\n", flashStatusIn[0] & 0x02 ? "en" : "dis");
1107 myPrintk("Block Protect %d\r\n", (flashStatusIn[0] & 0x1C) >> 2);
1108 myPrintk("%s Protect\r\n", flashStatusIn[0] & 0x20 ? "Bottom" : "Top");
1109 myPrintk("%sK Blocks\r\n", flashStatusIn[0] & 0x40 ? "4" : "64");
1110 myPrintk("Status Register%s Protected\r\n", flashStatusIn[0] & 0x80 ? "" : " Not");
1111 myPrintk("\r\nStatus register 2\r\n");
1112 myPrintk("Status Register %sLocked\r\n", flashStatusIn[1] & 0x01 ? "" : "Not ");
1113 myPrintk("QSPI %sEnabled\r\n", flashStatusIn[1] & 0x02 ? "" : "Not ");
1114 myPrintk("Lock Bits %d\r\n", (flashStatusIn[1] & 0x38) >> 3);
1115 myPrintk("Complement Protect %d\r\n", flashStatusIn[1] & 0x40);
1116 myPrintk("Suspend Status %d\r\n", flashStatusIn[1] & 0x80);
1117 myPrintk("\r\nStatus register 3\r\n");
1118 myPrintk("Write protect Selection %d\r\n", flashStatusIn[2] & 0x04);
1119 myPrintk("Drive Stength %d\r\n", (flashStatusIn[2] & 0x60) >> 5);
1120}
1121
1122/**
1123 * \fn void cliFlashWritePage(void)
1124 *
1125 * \brief CLI command to write a single byte of data to a specific address within a flash page.
1126 *
1127 * This function parses the page index, the byte offset within that page, and the data byte
1128 * to be written. It validates the ranges before calling the flash driver.
1129 */
1131 uint32_t page;
1132 int32_t data;
1133 int address = 0;
1134 char *end;
1135 uint8_t dataArray[2];
1136
1137 /* Ensure all required arguments are present: page, address, and data */
1138 if (numParameters != 4) {
1139 myPrintk("format flashWrite page address data\r\n");
1140 return;
1141 }
1142
1143 /* Convert hex string parameters to integers */
1144 page = strtoul(cmdLineParameter[1], &end, 16);
1145 address = strtoul(cmdLineParameter[2], &end, 16);
1146 data = strtoul(cmdLineParameter[3], &end, 16);
1147
1148 /* Check bounds: 32768 pages total, 256 bytes per page */
1149 if (page >= 32768) {
1150 myPrintk("Page %d >= 32768\r\n", page);
1151 return;
1152 }
1153 if (address >= 256) {
1154 myPrintk("Address %d >= 256\r\n", address);
1155 return;
1156 }
1157
1158 dataArray[0] = data;
1159 myPrintk("flashwrite page: 0x%X address: 0x%02X data: 0x%02X\r\n", page, address, dataArray[0]);
1160
1161 /* Execute the write operation via SPI */
1162 flashxWritePage(page, address, dataArray, 1);
1163 myPrintk("flashwrite complete\r\n");
1164 return;
1165}
1166
1167/**
1168 * \fn void cliGroup(void)
1169 *
1170 * \brief CLI command to set or display the sensor group name.
1171 *
1172 * If a parameter is provided, it updates the group name in the flash parameters.
1173 */
1174void cliGroup(void) {
1175 if (numParameters > 1) {
1176 /* Clear the existing group name buffer */
1177 for (int i = 0; i < sizeof(flashParameters.group); i++)
1178 flashParameters.group[i] = '\0';
1179 /* Copy the new group name from the command line starting after "group " */
1180 strncpy(flashParameters.group, &lineTmp[6], 39);
1181 setFlashxParameters(false);
1182 }
1183 myPrintk("Group: %s\r\n", flashParameters.group);
1184}
1185
1186/**
1187 * \fn void cliHelp(void)
1188 *
1189 * \brief CLI command to display help information for available commands.
1190 */
1191void cliHelp(void) {
1192 /* If a specific character is provided, show commands starting with that letter,
1193 * otherwise show all commands ('z' is the internal flag for all). */
1194 if (numParameters != 1) {
1196 } else {
1197 displayHelp('z');
1198 }
1199 return;
1200}
1201
1202/**
1203 * \fn void cliHumidity(void)
1204 *
1205 * \brief CLI command to display humidity data from connected sensors.
1206 */
1207void cliHumidity(void) {
1208 int i;
1209
1210 i = 0;
1211 /* Print table header for humidity data */
1212 myPrintk("Humidity (%%)\r\nDevice\tCurrent\tLow\tHigh\r\n");
1213
1214 /* Check if HDC2080 sensor is detected on the I2C bus */
1215 if ((sensorTypePresentAll & (1 << SENSORTYPEHDC2080))) {
1216 i++;
1217 /* Read current humidity and display along with configured thresholds */
1219 myPrintk("HDC2080\t%3.2f\t%3.2f\t%3.2f\r\n", (double)hdcHumidity, (double)readLowHumidityThreshold(),
1220 (double)readHighHumidityThreshold());
1221 }
1222
1223 /* Inform user if no compatible sensors were found */
1224 if (i == 0)
1225 myPrintk("No Humidity sensor connected\r\n");
1226 return;
1227}
1228
1229/**
1230 * \fn void cliI2CRead(void)
1231 *
1232 * \brief CLI command to read data from an I2C device.
1233 *
1234 * Parses the command line for I2C address, register, and length,
1235 * then performs the read operation and prints the results in hex.
1236 */
1237void cliI2CRead(void) {
1238 int i2cAddress, i2cRegister, length, i;
1239 char *end;
1240 uint8_t datas[DATA_LENGTH];
1241
1242 i2cAddress = 0x00;
1243 i2cRegister = 0x00;
1244 length = 1; /* Default values if parameters are missing */
1245
1246 if (numParameters == 2) {
1247 i2cAddress = strtoul(cmdLineParameter[1], &end, 16);
1248 } else if (numParameters == 3) {
1249 i2cAddress = strtoul(cmdLineParameter[1], &end, 16);
1250 i2cRegister = strtoul(cmdLineParameter[2], &end, 16);
1251 } else if (numParameters == 4) {
1252 i2cAddress = strtoul(cmdLineParameter[1], &end, 16);
1253 i2cRegister = strtoul(cmdLineParameter[2], &end, 16);
1254 length = atoi(cmdLineParameter[3]);
1255 }
1256
1257 /* Set the register pointer first */
1258 datas[0] = i2cRegister;
1259 i2c_write(i2c_dev, datas, 1, i2cAddress);
1260
1261 /* Read the requested number of bytes */
1262 i2c_read(i2c_dev, datas, length, 0x40);
1263 myPrintk("I2C Read Address: 0x%02X Reg: 0x%02X Length: %d\r\n", (unsigned int)i2cAddress, (int)i2cRegister, (int)length);
1264 for (i = 0; i < length; i++) {
1265 myPrintk("0x%02X 0x%02X\r\n", (unsigned int)(i2cRegister + i), datas[i]);
1266 }
1267 return;
1268}
1269
1270/**
1271 * \fn void cliI2CWrite(void)
1272 *
1273 * \brief CLI command to write data to a specific I2C device register.
1274 *
1275 * This function parses the I2C slave address, the target register, and the data byte
1276 * from the command line, then executes the I2C write transaction.
1277 */
1278void cliI2CWrite(void) {
1279 int i2cAddress, i2cRegister, data;
1280 char *end;
1281 uint8_t dataArray[4];
1282 /* Default values if parameters are missing */
1283
1284 i2cAddress = 0x00;
1285 i2cRegister = 0x00;
1286 data = 1; /* set to default address and data */
1287 if (numParameters == 2) {
1288 i2cAddress = strtoul(cmdLineParameter[1], &end, 16);
1289 } else if (numParameters == 3) {
1290 i2cAddress = strtoul(cmdLineParameter[1], &end, 16);
1291 i2cRegister = strtoul(cmdLineParameter[2], &end, 16);
1292 } else if (numParameters == 4) {
1293 i2cAddress = strtoul(cmdLineParameter[1], &end, 16);
1294 i2cRegister = strtoul(cmdLineParameter[2], &end, 16);
1295 data = strtoul(cmdLineParameter[3], &end, 16);
1296 }
1297 /* Prepare the data buffer: [Register Address, Data Byte] */
1298 dataArray[0] = i2cRegister;
1299 dataArray[1] = data;
1300 /* Execute the I2C write operation */
1301 i2c_write(i2c_dev, dataArray, 2, i2cAddress);
1302 myPrintk("I2C write Address: 0x%02X Reg: 0x%02X data: 0x%02X\r\n", (unsigned int)i2cAddress, (int)i2cRegister, (int)data);
1303 return;
1304}
1305
1306#if 1
1307/*!
1308 * \fn void nouart0(void)
1309 *
1310 * \brief set display nouart0
1311 *
1312 */
1313void cliNouart0(void) {
1314#if CONFIG_SERIAL
1315 int i;
1316 int err;
1317
1318 if (numParameters > 2) {
1319 printk("format nouart0 [0/1]\n");
1320 return;
1321 }
1322 if (numParameters == 2) {
1323 i = atoi(cmdLineParameter[1]);
1324 if (i == 1) {
1325 flashParameters.nouart0 = true;
1326 myPrintkW("UART0 Disable\r\n");
1327#if 1
1328 k_sleep(K_SECONDS(3));
1329 // 1. Disable RX first
1330 err = uart_rx_disable(uart0_dev);
1331 // __ASSERT(err == 0, "Failed to disable uart rx");
1332 if (err == 0) {
1333 myPrintkW("UART0 RX Disabled\r\n");
1334 } else {
1335 myPrintkW("UART0 RX Disable Failed: %d\r\n", err);
1336 return;
1337 }
1338 myPrintkW("UART0 SUSPEND: %d\r\n", err);
1339
1340 // 2. Wait for UART_RX_DISABLED event in your UART callback
1341 // (use a semaphore or flag set in the callback)
1342 k_sem_take(&uart_rx_disabled_sem, K_FOREVER); // Wait for the semaphore to be given in the callback
1343 // 3. Only then suspend the device
1344 err = pm_device_action_run(uart0_dev, PM_DEVICE_ACTION_SUSPEND);
1345#endif
1346 } else {
1347 flashParameters.nouart0 = false;
1348 err = pm_device_action_run(uart0_dev, PM_DEVICE_ACTION_RESUME);
1349// #if CONFIG_SERIAL
1350#if 0
1351 err = uart_init(); /* initialize UART */
1352 if (err) {
1353 myPrintkE("UART device is not ready\r\n");
1354 error();
1355 }
1356 myPrintkI("UART device is ready\r\n");
1357#endif
1358 k_sleep(K_SECONDS(5));
1359 myPrintkW("UART0 Enabled\n");
1360 myPrintkW("UART0 RESUME: %d\r\n", err);
1361 }
1362 setFlashxParameters(true);
1363 }
1364 myPrintk("nouart0: %d\n", flashParameters.nouart0);
1365#endif
1366
1367 return;
1368}
1369#endif
1370
1371/**
1372 * \fn void cliIgnoreBME688(void)
1373 *
1374 * \brief CLI command to set or display the ignore BME688 flag.
1375 */
1377 int i;
1378
1379 i = 0;
1380 /* If a parameter is provided, update the manual triugger mode setting */
1381 if (numParameters == 2) {
1382 i = atoi(cmdLineParameter[1]);
1383 if (i > 1)
1384 i = 1;
1385 flashParameters.ignoreBME688 = i; /* set ignore BME688 flash parameter */
1386 setFlashxParameters(false);
1387 myPrintk("Ignore BME688: %s\r\n", i ? "Enabled" : "Disabled");
1388 return;
1389 }
1390 /* If no parameter, display the current state */
1391 else if (numParameters == 1) {
1392 myPrintk("Ignore BME688: %s\r\n", flashParameters.ignoreBME688 ? "Enabled" : "Disabled");
1393 return;
1394 } else { /* Invalid number of arguments */
1395 myPrintk("format ignorebme688 [0 | 1]\r\n");
1396 return;
1397 }
1398}
1399
1400/**
1401 * \fn void cliLocation(void)
1402 *
1403 * \brief CLI command to set or display the sensor's physical location.
1404 *
1405 * If a location string is provided, it updates the flash parameters.
1406 */
1407void cliLocation(void) {
1408 if (numParameters > 1) {
1409 /* Clear existing location buffer */
1410 for (int i = 0; i < sizeof(flashParameters.location); i++)
1411 flashParameters.location[i] = '\0';
1412 /* Copy new location from command line (offset 9 for "location ") */
1413 strncpy(flashParameters.location, &lineTmp[9], 39);
1414 setFlashxParameters(false);
1415 }
1416 myPrintk("Location: %s\r\n", flashParameters.location);
1417}
1418
1419/**
1420 * \fn void cliManualTrigger(void)
1421 *
1422 * \brief CLI command to set or display the manual trigger mode flag.
1423 */
1425 int i;
1426
1427 i = 0;
1428 /* If a parameter is provided, update the manual triugger mode setting */
1429 if (numParameters == 2) {
1430 i = atoi(cmdLineParameter[1]);
1431 if (i > 1)
1432 i = 1;
1433 flashParameters.manualTrigger = i; /* set manual trigger flash parameter */
1434 setFlashxParameters(false);
1435 myPrintk("Manual Trigger: %s\r\n", i ? "Enabled" : "Disabled");
1436 return;
1437 }
1438 /* If no parameter, display the current state */
1439 else if (numParameters == 1) {
1440 myPrintk("Manual Trigger: %s\r\n", flashParameters.manualTrigger ? "Enabled" : "Disabled");
1441 return;
1442 } else { /* Invalid number of arguments */
1443 myPrintk("format manualtrigger [0 | 1]\r\n");
1444 return;
1445 }
1446}
1447
1448/**
1449 * \fn void cliPublishNow(void)
1450 *
1451 * \brief CLI command to trigger an immediate sensor data publication.
1452 *
1453 * This function releases the hdc_rdy_seen semaphore to bypass the normal
1454 * duty cycle timer and force a sensor read/BLE transmission.
1455 */
1456void cliPublishNow(void) {
1457 myPrintk("Send BLE data immediately\r\n");
1458 /* show RX received */
1459 k_sem_give(&hdc_rdy_seen); /* indicate HDC2080 RDY seen */
1460 return;
1461}
1462
1463/**
1464 * \fn void cliReset(void)
1465 *
1466 * \brief CLI command to reset the processor.
1467 *
1468 * If called without parameters, it performs a clean system reset.
1469 * If called with any parameter, it stops the watchdog feeder to force a WDT reset.
1470 */
1471void cliReset(void) {
1472 if (numParameters == 1) {
1473 myPrintk("Software Reset the board\r\n");
1474#if defined(CONFIG_REBOOT)
1475 // sys_reboot(SYS_REBOOT_COLD);
1476 NVIC_SystemReset();
1477#endif
1478 } else {
1479 myPrintk("Forced WDT reset of the processor. WDT feed Stopped!\r\n");
1480 stopWDTFeed = 1;
1481 }
1482 return;
1483}
1484
1485/**
1486 * \fn void cliResetCause(void)
1487 *
1488 * \brief CLI command to display the reason for the last processor reset.
1489 */
1490void cliResetCause(void) {
1491 myPrintk("resetCause: %s\r\n", resetCause);
1492 return;
1493}
1494
1495/**
1496 * \fn void cliSaved(void)
1497 *
1498 * \brief CLI command to manage and display JSON packets saved in external flash.
1499 *
1500 * This function allows the user to clear all saved packets, read a specific packet,
1501 * or display a range of packets stored in the flash memory.
1502 */
1503void cliSaved(void) {
1504#if 1
1505 int sectorCount;
1506 int data;
1507 int i, j;
1508
1509 /* Validate argument count */
1510 if (numParameters > 3) {
1511 myPrintk("format saved [clear/n] [len]\r\n");
1512 return;
1513 } else if (numParameters == 2) {
1514 /* Handle 'clear' command to wipe saved data */
1515 if ((cmdLineParameter[1][0] == 'c') || (cmdLineParameter[1][0] == 'C')) {
1516 flashParameters.nextSavedRead = 0;
1517 flashParameters.nextSavedWrite = 0;
1518 flashParameters.savedCount = 0;
1519 myPrintkI("Saved JSON Packets Cleared\r\n");
1520 setFlashxParameters(false);
1521 sectorCount = (MAX_NUMBER_BLE_PACKETS / 0x10) + 1; /* get number of sectors needed for number of BLE packets*/
1522 for (int i = 0; i < sectorCount; i++) {
1523 flashxEraseSector((FLASHBLESTART / 0x10) + i); /* erase the next sector */
1524 }
1525 return;
1526 } else {
1527 /* Read and display a single specific packet index */
1528 data = atoi(cmdLineParameter[1]); /* get packet to read */
1529 if (data < flashParameters.savedCount) {
1531 myPrintkI("Page: 0x%04X %s", data + FLASHBLESTART, flashReadIn);
1532 myPrintk("\r\n");
1533 } else {
1534 myPrintkW("%d >= %d packets saved\r\n", data, flashParameters.savedCount);
1535 }
1536 return;
1537 }
1538 } else if (numParameters == 3) {
1539 /* Read and display a range of packets starting from an index */
1540 data = atoi(cmdLineParameter[1]); /* get starting packet */
1541 if (data >= flashParameters.savedCount) {
1542 myPrintkW("%d >= %d packets saved\r\n", data, flashParameters.savedCount);
1543 return;
1544 }
1545 j = atoi(cmdLineParameter[2]); /* get number of packets to display*/
1546 for (i = 0; i < j; i++) {
1547 if ((data + i) >= flashParameters.savedCount) {
1548 myPrintkW("%d >= %d packets saved\r\n", (data + i), flashParameters.savedCount);
1549 return;
1550 }
1552 myPrintkI("Page: 0x%04X %s", data + FLASHBLESTART + i, flashReadIn);
1553 myPrintk("\r\n");
1554 }
1555 } else if (numParameters == 1) {
1556 /* Display summary of saved packet statistics */
1557 myPrintk("Saved BLE Packets: %d Next Read: %d Next Write: %d Max: %d\r\n", flashParameters.savedCount, flashParameters.nextSavedRead,
1558 flashParameters.nextSavedWrite, MAX_NUMBER_BLE_PACKETS);
1559 }
1560#endif
1561 return;
1562}
1563
1564/**
1565 * \fn void cliSensorID(void)
1566 *
1567 * \brief CLI command to set or display the unique sensor ID.
1568 *
1569 * If a parameter is provided, it updates the sensorID in flash memory.
1570 */
1571void cliSensorID(void) {
1572 if (numParameters > 1) {
1573 /* Clear existing ID buffer */
1574 for (int i = 0; i < sizeof(flashParameters.sensorID); i++)
1575 flashParameters.sensorID[i] = '\0';
1576 /* Copy new ID from command line (offset 9 for "sensorid ") */
1577 strncpy(flashParameters.sensorID, &lineTmp[9], 6);
1578 setFlashxParameters(false);
1579 }
1580 myPrintk("Sensor ID: %s\r\n", flashParameters.sensorID);
1581}
1582
1583/**
1584 * \fn void cliSensorName(void)
1585 *
1586 * \brief CLI command to set or display the human-readable sensor name.
1587 *
1588 * Updates the sensorName in flash parameters if a new name is provided.
1589 */
1590void cliSensorName(void) {
1591 if (numParameters > 1) {
1592 /* Clear existing name buffer */
1593 for (int i = 0; i < sizeof(flashParameters.sensorName); i++)
1594 flashParameters.sensorName[i] = '\0';
1595 /* Copy new name from command line (offset 11 for "sensorname ") */
1596 strncpy(flashParameters.sensorName, &lineTmp[11], 39);
1597 setFlashxParameters(false);
1598 }
1599 myPrintk("Sensor Name: %s\r\n", flashParameters.sensorName);
1600}
1601
1602/**
1603 * \fn void cliSensors(void)
1604 *
1605 * \brief CLI command to list all supported sensors and their detection status.
1606 *
1607 * Checks the sensorTypePresentAll bitmask against the known sensor list.
1608 */
1609void cliSensors(void) {
1610 int i;
1611
1612 myPrintk("sensorTypePresentAll %08X\r\n", sensorTypePresentAll);
1613 for (i = 0; 1; i++) {
1614 /* Formatting: new line every 4 entries */
1615 if ((i & 0x3) == 0)
1616 myPrintk("\r\n");
1617 if (strcmp(sensorTypeNames[i], "Unknown") == 0)
1618 break;
1619 /* Check if the bit corresponding to the sensor type is set */
1620 if ((sensorTypePresentAll & (1 << i)) == 0) {
1621 myPrintkW("%s %s\r\n", sensorTypeNames[i], "Not Present");
1622 } else {
1623 myPrintkI("%s %s\r\n", sensorTypeNames[i], "Present");
1624 }
1625 }
1626 return;
1627}
1628
1629/**
1630 * \fn void cliSilent(void)
1631 *
1632 * \brief CLI command to set or display the silent mode flag.
1633 */
1634void cliSilent(void) {
1635 int i;
1636
1637 i = 0;
1638 /* If a parameter is provided, update the silent mode setting */
1639 if (numParameters == 2) {
1640 i = atoi(cmdLineParameter[1]);
1641 if (i > 1)
1642 i = 1;
1643 flashParameters.silent = i; /* set silent flash parameter */
1644 setFlashxParameters(false);
1645 myPrintk("Silent: %s\r\n", i ? "Enabled" : "Disabled");
1646 return;
1647 }
1648 /* If no parameter, display the current state */
1649 else if (numParameters == 1) {
1650 myPrintk("Silent: %s\r\n", flashParameters.silent ? "Enabled" : "Disabled");
1651 return;
1652 } else { /* Invalid number of arguments */
1653 myPrintk("format silent [0 | 1]\r\n");
1654 return;
1655 }
1656}
1657
1658/**
1659 * \fn void cliTemperature(void)
1660 *
1661 * \brief CLI command to display temperature data from connected sensors.
1662 *
1663 * Reads the current temperature from the HDC2080 and displays it alongside
1664 * the configured low and high alarm thresholds.
1665 */
1666void cliTemperature(void) {
1667 int i;
1668
1669 i = 0;
1670 myPrintk("Temperature (deg C)\r\nDevice\tCurrent\tLow\tHigh\r\n");
1671
1672 /* Check if HDC2080 sensor is present on the I2C bus */
1673 if ((sensorTypePresentAll & (1 << SENSORTYPEHDC2080))) {
1674 i++;
1675 hdcTemp = readTemp();
1676 ;
1677 myPrintk("HDC2080\t%3.2f\t%3.2f\t%3.2f\r\n", (double)hdcTemp, (double)readLowTempThreshold(), (double)readHighTempThreshold());
1678 }
1679 /* Notify user if no temperature sensors were detected */
1680 if (i == 0)
1681 myPrintk("No Temperature sensor connected\r\n");
1682 return;
1683}
1684
1685/**
1686 * \fn void cliVersion(void)
1687 * \brief CLI command to display firmware, hardware, and SDK version information.
1688 */
1689void cliVersion(void) {
1690 /* display version and build information */
1691 if (flashParameters.nouart0 == false) {
1692 myPrintk("Board: %s%s\r\nFW VERSION: V %d.%02d %s%s\r\n", BOARD_NAME, BOARD_NAME_EXT, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE,
1694 } else {
1695 myPrintk("Board: %s%s\r\nFW VERSION: V %d.%02d %s%s\r\n", BOARD_NAME, BOARD_NAME_EXT, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE,
1697 }
1698
1699#ifndef CONFIG_SERIAL
1700 myPrintk("Board: %s%s\r\nFW VERSION: V %d.%02d %s%s\r\n", BOARD_NAME, BOARD_NAME_EXT, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE,
1702#endif
1703
1704 myPrintk("SDK Version: %s\r\n", EXPAND_AND_STR(NCS_BUILD_VERSION));
1705 myPrintk("Built:%s %s\r\n", __DATE__, __TIME__);
1706 if (IS_ENABLED(CONFIG_LTE_NETWORK_MODE_LTE_M)) {
1707 myPrintk("GPS not available!\r\n");
1708 }
1709 if (IS_ENABLED(CONFIG_LTE_NETWORK_MODE_LTE_M_GPS)) {
1710 myPrintk("GPS available!\r\n");
1711 }
1712 return;
1713}
void setRate(int rate)
Sets the automatic measurement frequency.
Definition HDC2080.c:585
float readLowTempThreshold(void)
Reads the low temperature threshold currently set in the sensor.
Definition HDC2080.c:361
float readHighTempThreshold(void)
Reads the high temperature threshold currently set in the sensor.
Definition HDC2080.c:378
float readHumidity(void)
Reads the relative humidity from the HDC2080 sensor.
Definition HDC2080.c:79
void triggerMeasurement(void)
Manually triggers a single measurement cycle.
Definition HDC2080.c:511
float readHighHumidityThreshold(void)
Reads the high humidity threshold currently set in the sensor.
Definition HDC2080.c:344
float readLowHumidityThreshold(void)
Reads the low humidity threshold currently set in the sensor.
Definition HDC2080.c:327
void disableInterrupt(void)
Disables the physical interrupt/DRDY pin (sets to High-Z).
Definition HDC2080.c:567
float readTemp(void)
Reads the temperature data from the HDC2080 sensor.
Definition HDC2080.c:24
#define ONE_MINS
Definition HDC2080.h:32
W25Q64JV driver header file.
int getBME688Data(int count, uint8_t quiet)
Triggers and retrieves measurement data from the BME688.
Definition bme68x.c:1916
uint8_t flashReadIn[MAX_FLASH_BYTES]
Definition globals.c:32
float hdcHumidity
Definition globals.c:26
flashParametersStruct flashParameters
working valuses of flash parameters in RAM
Definition globals.c:35
uint32_t bleIndex
Definition globals.c:37
uint32_t sensorTypePresentAll
Definition globals.c:30
float adc_voltage[2]
last ADC voltage read [0] battery
Definition globals.c:31
const struct gpio_dt_spec spics2n
Definition globals.c:63
uint8_t sendingDeviceInfo
flag to indicate sending device info in BLE packet instead of sensor data
Definition globals.c:46
uint8_t stopWDTFeed
stop Watch Dog Timer feed causing a WDT interrupt for testing
Definition globals.c:38
long long gatewayDateTime
Definition globals.c:47
char * cmdLineParameter[MAX_PARAMETERS]
array of pointers to command line parameter strings
Definition globals.c:27
struct bme68x_data BME688Data
Definition globals.c:44
uint8_t hdcMinutes
Definition globals.c:39
char resetCause[100]
Definition globals.c:33
char devIDStr[70]
Definition globals.c:29
uint8_t numParameters
Definition globals.c:28
char myStr[256]
Definition globals.c:34
const struct gpio_dt_spec spics1n
Definition globals.c:55
float hdcTemp
Definition globals.c:25
void cliFlashID()
CLI command to read and display the unique Flash memory ID.
void cliADC()
CLI command to sample and display the ADC voltage.
void cliVersion()
CLI command to display firmware, hardware, and SDK version information.
void cliCustomer()
CLI command to set or display the customer name in flash parameters.
int8_t getCLICmd(char *line)
parses command line to find position of command in validCLICmds array.
void cliSensors()
CLI command to list all supported sensors and their detection status.
void cliFlashFillPage()
CLI command to fill one or more flash pages with a specific 32-bit data pattern.
void cliDateTime()
CLI command to set or display the gateway epoch timestamp.
void cliSensorName()
CLI command to set or display the human-readable sensor name.
void cliFlashErase()
CLI command to erase the entire external flash memory.
void cliBME688()
CLI command to read and display data from the BME688 sensor.
void cliFlashEraseSector()
CLI command to erase a specific 4KB sector of the external flash.
void cliI2CWrite()
CLI command to write data to a specific I2C device register.
COMMANDS
< vaild command indexes
@ ADCX
@ SENSORNAME
@ LOCATION
@ IGNOREBME688
@ DUTYCYCLE
@ FLASHERASE
@ FLASHREADPAGE
@ BME688
@ CUSTOMER
@ SENSORID
@ FLASHERASESECTOR
@ NOUART0
@ FLASHWRITEPAGE
@ SAVED
@ DEVICEID
@ FLASHPARAMETERS
@ DATETIME
@ SENSORS
@ BME688CS
@ RESETCAUSE
@ GROUP
@ FLASHID
@ FLASHSTATUS
@ I2CWRITE
@ FLASHNSS
@ SILENT
@ I2CREAD
@ RESETX
@ FLASHFILLPAGE
@ RESCAN
@ MANUALTRIGGER
@ VERSIONX
@ BATMON
@ DEVICEINFO
@ PUBLISHNOW
@ HUMIDITY
void cliNouart0(void)
void cliDutyCycle()
CLI command to configure the sensor data sampling interval.
void cliBME688CS()
CLI command to manually control the BME688 SPI Chip Select (CS) pin.
void displayHelp(char c)
displays a list of all available CLI commands
void cliIgnoreBME688()
CLI command to set or display the ignore BME688 flag.
void cliLocation()
CLI command to set or display the sensor's physical location.
char const * validCLICmds[]
array of valid commands - case insensitive
static char lineTmp[LINE_SIZE]
tempory line saved
#define LINE_SIZE
maximum number of characters on a CLI line
void cliSilent()
CLI command to set or display the silent mode flag.
void cliSaved()
CLI command to manage and display JSON packets saved in external flash.
void cliPublishNow()
CLI command to trigger an immediate sensor data publication.
void cliDeviceInfo()
Transmit comprehensive device information over BLE NUS service.
void cliDeviceID()
Display the unique device identifier string.
void cliHelp()
CLI command to display help information for available commands.
void cliHumidity()
CLI command to display humidity data from connected sensors.
void cliSensorID()
CLI command to set or display the unique sensor ID.
void cliFlashNSS()
CLI command to manually toggle the SPI Chip Select (NSS) for the Flash memory.
void executeCmd(char *line)
executes the command in line array.
void cliReset()
CLI command to reset the processor.
void cliManualTrigger(void)
CLI command to set or display the manual trigger mode flag.
char const * helpMessages[]
array of help messages
void cliFlashWritePage()
CLI command to write a single byte of data to a specific address within a flash page.
void cliI2CRead()
CLI command to read data from an I2C device.
void cliResetCause()
CLI command to display the reason for the last processor reset.
char * sensorTypeNames[]
sensor types and state (present = 1)
void cliTemperature()
CLI command to display temperature data from connected sensors.
void cliGroup()
CLI command to set or display the sensor group name.
void cliFlashStatus()
CLI command to read and display the status registers of the external flash.
int uart_init(void)
void int64_to_string(int64_t num, char *str)
Converts a 64-bit signed integer to a null-terminated string.
void cliBatMon()
CLI command to enable or disable the battery monitor hardware.
void cliFlashReadPage()
CLI command to read and display the contents of external flash pages.
#define BOARD_NAME
Definition jfet_common.h:34
#define MAX_NUMBER_BLE_PACKETS
Definition jfet_common.h:82
int myPrintk(char *restrict fmt,...)
Definition main.c:2310
#define VERSION_MAJOR
Definition jfet_common.h:30
void displayFlashxParameters(void)
displays the NV flash parameters.
Definition w25q64jv.c:1021
#define VERSION_DATE
Definition jfet_common.h:33
void flashxClearParameters(void)
clears/initializes the flash parameters in RAM
Definition w25q64jv.c:939
#define VERSION_DATE_EXT2
Definition jfet_common.h:37
#define VERSION_DATE_EXT3
Definition jfet_common.h:38
int myPrintkS(char *restrict fmt,...)
prints a status message to the UART
Definition main.c:2419
void flashxWritePage(uint32_t page, uint32_t address, uint8_t *data, uint16_t count)
writes data to address in serial flash over the SPI bus.
Definition w25q64jv.c:542
void readNVFlashxID(uint8_t *flashId)
reads the NV Flash ID over the SPI bus.
Definition w25q64jv.c:34
struct k_sem uart_rx_disabled_sem
struct k_sem hdc_rdy_seen
int adc_sample(void)
get a single reading from ADC channel
Definition main.c:343
#define FLASHPARAMETERSTART
Definition jfet_common.h:77
int myPrintkI(char *restrict fmt,...)
prints an information message to the UART
Definition main.c:2386
void flashxReadPage(uint32_t address, uint8_t *flashRead)
reads a 256 byte page over the SPI bus.
Definition w25q64jv.c:427
#define EXPAND_AND_STR(x)
Definition jfet_common.h:54
const struct device *const i2c_dev
get the device structure for the I2C device defined by I2C_DEV_NODE
Definition main.c:106
int myPrintkE(char *restrict fmt,...)
prints an error message to the UART
Definition main.c:2452
#define VERSION_DATE_EXT1
Definition jfet_common.h:36
void flashxEraseSector(uint32_t address)
erases a 256K byte sector over the SPI bus.
Definition w25q64jv.c:330
void flashxFillPage(uint32_t address, uint16_t data)
fills a 256 byte page with data over the SPI bus.
Definition w25q64jv.c:752
const struct gpio_dt_spec baten
get the GPIO specification for the BATEN pin defined by BATEN_NODE
Definition main.c:175
void rescan(void)
rescan all I2C and SPI devices
Definition main.c:2281
#define TRUE
Definition jfet_common.h:42
#define FLASHBLESTART
Definition jfet_common.h:78
const struct device *const uart0_dev
void setFlashxParameters(uint8_t display)
loads the NV Flash parameters from teh RAM flash parameters
Definition w25q64jv.c:1122
void flashxErase(void)
erases the entire 8 Mb over the SPI bus.
Definition w25q64jv.c:379
void readNVFlashxStatus(uint8_t *flashStatus)
reads the 3 NV Flash status registers over the SPI bus.
Definition w25q64jv.c:61
#define BOARD_NAME_EXT
Definition jfet_common.h:39
#define VERSION_MINOR
Definition jfet_common.h:31
@ SENSORTYPEHDC2080
Definition jfet_common.h:69
#define DATA_LENGTH
Definition jfet_common.h:51
int myPrintkW(char *restrict fmt,...)
prints a warning message to the UART
Definition main.c:2353
void error(void)
Function to handle fatal errors This function is called when a fatal error occurs in the system....
Definition main.c:1107