+ Add system timestamps to lua read() and new lua read_line() per global options; prevented warnings

+ Add missing timestamp-format epoch; update send_ to use fsync and tcdrain like normal tty_sync does; rework read_line to save partial line at timeout
This commit is contained in:
Keith Hill 2024-10-25 11:22:56 -05:00
parent ab678e6c88
commit e5f9b947c4
13 changed files with 201 additions and 22 deletions

17
examples/lua/lines.lua Normal file
View file

@ -0,0 +1,17 @@
read(1000, 8000) -- read initial config
send("\n")
read(650, 100) -- main menu
send("S") -- S menu
n = 1
while n > 0 do -- while not empty, read more
n, str = read_line(25)
end
while true do
send("t") -- query PV table
msleep(880)
n = 1
while n > 0 do -- while not empty, read more
n, str = read_line(60)
msleep(60)
end
end

14
examples/lua/pts.lua Normal file
View file

@ -0,0 +1,14 @@
read(1000, 6000) -- initial config
send("\n")
msleep(100)
read(650, 60) -- main menu
send("S") -- S menu
msleep(30)
read(650, 60)
send("t") -- Parallel Value Table
read(650, 60)
while true do
msleep(1000)
send("t")
read(650, 50) -- repeat PVT forever
end

16
examples/lua/pvt.lua Normal file
View file

@ -0,0 +1,16 @@
send("\n")
msleep(100)
-- read buffer with 0.5 sec delay
read(160, 500)
send("S")
msleep(100)
-- read buffer
read(160, 500)
-- query Parallel Value Table
send("t")
print(read(300, 500))
while true do
sleep(1)
send("t")
print(read(300, 500))
end

View file

@ -467,7 +467,18 @@ until data is ready to read.
Returns number of bytes read on success, 0 on timeout, or -1 on error.
On success, returns read string as second return value.
On success, returns read string as second return value. Also emits a single
timestamp to stdout and log file per options.timestamp and options.log.
.IP "\fBread_line(timeout)"
Read line from serial device. If timeout is 0 or not provided it will wait
forever until data is ready to read.
Returns number of bytes read on success, 0 on timeout, or -1 on error.
On success, returns the string that was read as second return value. Also
emits a single timestamp to stdout and log file per options.timestamp
and options.log.
.IP "\fBset{line=state, ...}"
Set state of one or multiple tty modem lines.

View file

@ -373,7 +373,14 @@ SCRIPT API
Returns number of bytes read on success, 0 on timeout, or -1 on error.
On success, returns read string as second return value.
On success, returns read string as second return value. Also emits a single timestamp to stdout and log file per options.timestamp and options.log.
read_line(timeout)
Read line from serial device. If timeout is 0 or not provided it will wait forever until data is ready to read.
Returns number of bytes read on success, 0 on timeout, or -1 on error.
On success, returns the string that was read as second return value. Also emits a single timestamp to stdout and log file per options.timestamp and options.log.
set{line=state, ...}
Set state of one or multiple tty modem lines.

View file

@ -209,7 +209,7 @@ static void config_parse_keys(GKeyFile *key_file, char *group)
{
option.timestamp = TIMESTAMP_24HOUR;
}
config_get_string(key_file, group, "timestamp-format", &string, "24hour", "24hour-start", "24hour-delta", "iso8601", NULL);
config_get_string(key_file, group, "timestamp-format", &string, "24hour", "24hour-start", "24hour-delta", "iso8601", "epoch", NULL);
if (string != NULL)
{
option_parse_timestamp(string, &option.timestamp);

View file

@ -19,8 +19,7 @@
* 02110-1301, USA.
*/
#define __STDC_WANT_LIB_EXT2__ 1 // To access vasprintf
#define _GNU_SOURCE // To access vasprintf
#include <stdio.h>
#include "print.h"

View file

@ -19,8 +19,7 @@
* 02110-1301, USA.
*/
#define __STDC_WANT_LIB_EXT2__ 1 // To access vasprintf
#define _GNU_SOURCE // To access vasprintf
#include <sys/time.h>
#include <libgen.h>
#include <errno.h>

View file

@ -19,6 +19,8 @@
* 02110-1301, USA.
*/
#define _GNU_SOURCE // To access vasprintf
#include <assert.h>
#include <regex.h>
#include <getopt.h>

View file

@ -37,6 +37,8 @@
#include "log.h"
#include "script.h"
#include "fs.h"
#include "timestamp.h"
#include "termios.h"
#define MAX_BUFFER_SIZE 2000 // Maximum size of circular buffer
@ -192,6 +194,8 @@ static int send_(lua_State *L)
}
ret = write(device_fd, string, strlen(string));
fsync(device_fd); // flush these characters now
tcdrain(device_fd); //ensure we flushed characters to our device
lua_pushnumber(L, ret);
@ -248,18 +252,47 @@ static bool match_regex(regex_t *regex)
return false;
}
// lua: ret,string = read_string(size, timeout)
// Function to echo a buffer to stdout and to the log
// per the option.timestamp and option.log settings
static void echo_buffer(char buffer[], ssize_t len)
{
if (option.timestamp)
{
char *pTimeStampNow;
pTimeStampNow = timestamp_current_time();
if (pTimeStampNow)
{
tio_printf("%s", buffer); //does timestamps for us
if (option.log)
{
log_printf("\n[%s] %s", pTimeStampNow, buffer);
}
}
} else {
for (ssize_t i=0; i<len; i++)
{
putchar(buffer[i]);
if (option.log)
{
log_putc(buffer[i]);
}
}
}
}
// lua: ret,string = read(size, timeout)
static int read_string(lua_State *L)
{
int size = lua_tointeger(L, 1);
int size = lua_tointeger(L, 1) + 1; //plus one for null-terminated string
int timeout = lua_tointeger(L, 2);
int ret = 0;
char *buffer = malloc(size);
char *buffer = calloc(1, size);
if (buffer == NULL)
{
ret = -1; // Error
goto error;
goto error_rs;
}
if (timeout == 0)
@ -271,33 +304,112 @@ static int read_string(lua_State *L)
if (bytes_read < 0)
{
ret = -1; // Error
goto error;
goto error_rs;
}
else if (bytes_read == 0)
{
ret = 0; // Timeout
goto error;
goto error_rs;
}
else
{
buffer[bytes_read] = (char)0;
}
for (ssize_t i=0; i<bytes_read; i++)
{
putchar(buffer[i]);
echo_buffer(&buffer[0], bytes_read);
ret = bytes_read;
if (option.log)
error_rs:
lua_pushnumber(L, ret);
if (buffer != NULL)
{
lua_pushstring(L, ret > 0 ? buffer : "");
free(buffer);
}
else
{
lua_pushstring(L, ""); // give empty string to caller
}
return 2;
}
#define READ_LINE_SIZE 4096 // read_line buffer length
// lua: ret,string = read_line(timeout)
static int read_line(lua_State *L)
{
int timeout = lua_tointeger(L, 1); //ms
int ret = 0;
int nl_seen = 0;
int read_result = 1; //enable reading input from device
char ch;
int bytes_read = 0;
char *buffer = calloc(1, READ_LINE_SIZE);
if (buffer == NULL)
{
ret = -1; // Error
read_result = -1; //disable reading input from device
}
if (timeout == 0)
{
timeout = -1; // Wait forever
}
// loop reading input until a newline seen or timeout
while (!nl_seen && (read_result > 0))
{
read_result = read_poll(device_fd, &ch, 1, timeout);
if (read_result < 0)
{
log_putc(buffer[i]);
ret = -1; // Error
}
else if (!read_result)
{
// Timeout returns a non-empty buffer as a 'line'
if (bytes_read)
{
nl_seen = 1;
ret = bytes_read;
}
else
{
ret = 0;
}
}
else // we got a character, so handle it
{
if (ch == '\n')
{
nl_seen = 1;
}
else if (bytes_read <= (READ_LINE_SIZE-2))
{
if (ch != '\r') // skip pesky control characters
{
buffer[bytes_read++] = ch;
}
}
}
}
ret = bytes_read;
if (nl_seen || (read_result > 0))
{
echo_buffer(&buffer[0], bytes_read);
ret = bytes_read;
}
error:
lua_pushnumber(L, ret);
if (buffer != NULL)
{
lua_pushstring(L, buffer);
free(buffer);
}
else
{
lua_pushstring(L, ""); // give empty string to caller
}
return 2;
}
@ -457,6 +569,7 @@ static const struct luaL_Reg tio_lib[] =
{ "modem_send", modem_send},
{ "send", send_},
{ "read", read_string},
{ "read_line", read_line},
{ "expect", expect},
{ "exit", exit_},
{ "tty_search", tty_search_},

View file

@ -29,8 +29,6 @@
#include "options.h"
#include "timestamp.h"
#define TIME_STRING_SIZE_MAX 24
char *timestamp_current_time(void)
{
static char time_string[TIME_STRING_SIZE_MAX];

View file

@ -32,5 +32,7 @@ typedef enum
TIMESTAMP_END,
} timestamp_t;
#define TIME_STRING_SIZE_MAX 24
char *timestamp_current_time(void);

View file

@ -1615,6 +1615,7 @@ const char* get_serial_port_type(const char* port_name)
const char* get_serial_port_type(const char* port_name)
{
(void)port_name;
return "";
}