Improve Asclepius error handling, serial reconnection, and TTY configuration

This commit is contained in:
Julian Frohmüller
2026-07-18 17:17:46 +02:00
parent 1e68ceea29
commit f0f756ace0
10 changed files with 350 additions and 44 deletions
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

+122 -31
View File
@@ -104,30 +104,14 @@ static bool asclepius_read_status_packet(void)
return true;
}
void asclepius_connect(void)
static int asclepius_setup_tty(void)
{
if(asclepius_connected)
{
asclepius_disconnect();
}
asclepius_serial_port = open(ASCLEPIUS_TTY_DEVICE, O_RDWR | O_NOCTTY);
if(asclepius_serial_port < 0)
{
printf("Error %i from open: %s\n", errno, strerror(errno));
asclepius_connected = false;
return;
}
struct termios tty;
if(tcgetattr(asclepius_serial_port, &tty) != 0)
{
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
asclepius_connected = false;
close(asclepius_serial_port);
return;
return -1;
}
tty.c_cflag &= ~PARENB; // No parity
@@ -158,14 +142,64 @@ void asclepius_connect(void)
if(tcsetattr(asclepius_serial_port, TCSANOW, &tty) != 0)
{
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
asclepius_connected = false;
close(asclepius_serial_port);
return;
return -1;
}
tcflush(asclepius_serial_port, TCIOFLUSH);
return 0;
}
static bool asclepius_reconnect(void)
{
if(asclepius_serial_port >= 0)
{
close(asclepius_serial_port);
asclepius_serial_port = -1;
}
asclepius_serial_port = open(asclepius_tty_device_ccc, O_RDWR | O_NOCTTY);
if(asclepius_serial_port < 0)
{
printf("Error %i from open: %s\n", errno, strerror(errno));
return false;
}
if(asclepius_setup_tty() != 0)
{
close(asclepius_serial_port);
asclepius_serial_port = -1;
return false;
}
return true;
}
int asclepius_connect(void)
{
if(asclepius_connected)
{
asclepius_disconnect();
}
asclepius_serial_port = open(asclepius_tty_device_ccc, O_RDWR | O_NOCTTY);
if(asclepius_serial_port < 0)
{
printf("Error %i from open: %s\n", errno, strerror(errno));
asclepius_connected = false;
return -1;
}
if(asclepius_setup_tty() != 0)
{
asclepius_connected = false;
close(asclepius_serial_port);
return -1;
}
asclepius_connected = true;
return 0;
}
void asclepius_disconnect(void)
@@ -186,37 +220,65 @@ bool asclepius_get_connection_status()
return asclepius_connected;
}
void asclepius_enable_channel(uint8_t channel)
int asclepius_enable_channel(uint8_t channel)
{
if(!asclepius_connected)
{
return;
return -1;
}
asclepius_command.command = ASCLEPIUS_TURNON_IOCMD;
asclepius_command.channel = channel;
asclepius_write_all(&asclepius_command, sizeof(asclepius_command));
if(!asclepius_write_all(&asclepius_command, sizeof(asclepius_command)))
{
asclepius_connected = false;
if(asclepius_reconnect())
{
asclepius_connected = true;
if(asclepius_write_all(&asclepius_command, sizeof(asclepius_command)))
{
return 0;
}
}
return -1;
}
return 0;
}
void asclepius_disable_channel(uint8_t channel)
int asclepius_disable_channel(uint8_t channel)
{
if(!asclepius_connected)
{
return;
return -1;
}
asclepius_command.command = ASCLEPIUS_TURNOFF_IOCMD;
asclepius_command.channel = channel;
asclepius_write_all(&asclepius_command, sizeof(asclepius_command));
if(!asclepius_write_all(&asclepius_command, sizeof(asclepius_command)))
{
asclepius_connected = false;
if(asclepius_reconnect())
{
asclepius_connected = true;
if(asclepius_write_all(&asclepius_command, sizeof(asclepius_command)))
{
return 0;
}
}
return -1;
}
return 0;
}
void asclepius_get_status(void)
int asclepius_get_status(void)
{
if(!asclepius_connected)
{
return;
return -1;
}
asclepius_command.command = ASCLEPIUS_STATUS_IOCMD;
@@ -224,8 +286,37 @@ void asclepius_get_status(void)
if(!asclepius_write_all(&asclepius_command, sizeof(asclepius_command)))
{
return;
asclepius_connected = false;
if(asclepius_reconnect())
{
asclepius_connected = true;
if(asclepius_write_all(&asclepius_command, sizeof(asclepius_command)))
{
if(asclepius_read_status_packet())
{
return 0;
}
}
}
return -1;
}
asclepius_read_status_packet();
if(!asclepius_read_status_packet())
{
asclepius_connected = false;
if(asclepius_reconnect())
{
asclepius_connected = true;
if(asclepius_write_all(&asclepius_command, sizeof(asclepius_command)))
{
if(asclepius_read_status_packet())
{
return 0;
}
}
}
return -1;
}
return 0;
}
+5 -5
View File
@@ -13,7 +13,7 @@
#include <termios.h>
#include <unistd.h>
#define ASCLEPIUS_TTY_DEVICE "/dev/ttyascl"
extern char asclepius_tty_device_ccc[256];
#define ASCLEPIUS_BAUDRATE B115200
#define ASCLEPIUS_STATUS_IOCMD 1
@@ -49,14 +49,14 @@ struct
bool usb5v_enabled;
} asclepius_status;
void asclepius_connect(void);
int asclepius_connect(void);
void asclepius_disconnect(void);
bool asclepius_get_connection_status(void);
void asclepius_enable_channel(uint8_t channel);
int asclepius_enable_channel(uint8_t channel);
void asclepius_disable_channel(uint8_t channel);
int asclepius_disable_channel(uint8_t channel);
void asclepius_get_status(void);
int asclepius_get_status(void);
+92 -7
View File
@@ -3925,6 +3925,9 @@ void open_primary_relay_dialog_ccc(void)
data_current_relay_board_a_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "data_current_relay_board_a"));
asclepius_relay_source_label_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "asclepius_relay_source_label"));
asclepius_relay_source_combobox_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "asclepius_relay_source_combobox"));
asclepius_tty_device_text_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "asclepius_tty_device_text"));
asclepius_connect_button_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "asclepius_connect_button"));
asclepius_disconnect_button_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "asclepius_disconnect_button"));
primary_relay_board_settings_label_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "primary_relay_board_settings_label"));
primary_relay_activation_label_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "primary_relay_activation_label"));
activate_primary_relay1_checkbutton_ccc = GTK_WIDGET(gtk_builder_get_object(builder, "activate_primary_relay1_checkbutton"));
@@ -3990,13 +3993,17 @@ void open_primary_relay_dialog_ccc(void)
gtk_button_set_label(GTK_BUTTON(test_primary_relay_button_ccc), _("Test relay operation"));
gtk_button_set_label(GTK_BUTTON(activate_primary_relay_button_ccc), _("Activate (Power Off)"));
gtk_button_set_label(GTK_BUTTON(deactivate_primary_relay_button_ccc), _("Deactivate (Power On)"));
gtk_button_set_label(GTK_BUTTON(asclepius_connect_button_ccc), _("Connect Asclepius"));
gtk_button_set_label(GTK_BUTTON(asclepius_disconnect_button_ccc), _("Disconnect Asclepius"));
// gtk_entry_set_max_length (GTK_ENTRY (power_command_to_call_text_ccc), MAX_CALL_LENGTH);
gtk_entry_set_max_length(GTK_ENTRY(asclepius_tty_device_text_ccc), 255);
// g_signal_connect(G_OBJECT(phase_timers_checkbutton_ccc), "toggled", G_CALLBACK(set_state_from_button_ccc), GINT_TO_POINTER(BUTTONID_PHASETIMERS));
load_primary_relay_settings_ccc();
gtk_label_set_text(GTK_LABEL(data_current_relay_board_a_ccc), primary_relay_settings_ccc.primary_relay_name);
gtk_entry_set_text(GTK_ENTRY(asclepius_tty_device_text_ccc), primary_relay_settings_ccc.asclepius_tty_device);
update_primary_relay_button_settings_ccc();
gtk_window_set_title(GTK_WINDOW(dialog), _("Primary Relay Settings"));
@@ -4056,6 +4063,9 @@ void update_primary_relay_settings_from_buttons_ccc(void)
}
}
const gchar *tty_entry_text = gtk_entry_get_text(GTK_ENTRY(asclepius_tty_device_text_ccc));
strcpy(primary_relay_settings_ccc.asclepius_tty_device, tty_entry_text);
// = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON());
// = gtk_spin_button_get_value(GTK_SPIN_BUTTON());
}
@@ -4175,7 +4185,10 @@ int cycle_primary_relay_ccc(void)
if(asclepius_get_connection_status())
{
asclepius_disable_channel(asclepius_relay_source);
if (asclepius_disable_channel(asclepius_relay_source) != 0)
{
return 1;
}
// wait to deactivate
unsigned int i;
@@ -4185,7 +4198,10 @@ int cycle_primary_relay_ccc(void)
do_nanosleep_ccc(1000000000);
}
asclepius_enable_channel(asclepius_relay_source);
if (asclepius_enable_channel(asclepius_relay_source) != 0)
{
return 1;
}
// wait for delay time
for (i = primary_relay_delay_time_ccc; i > 0; i--)
@@ -4497,7 +4513,10 @@ void update_asclepius_status(void)
{
if (asclepius_get_connection_status())
{
asclepius_get_status();
if (asclepius_get_status() != 0)
{
return;
}
if (asclepius_status.main12v_enabled)
{
@@ -4507,6 +4526,10 @@ void update_asclepius_status(void)
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_12v_icon), status_icon_off_path);
}
if (asclepius_status.main12v_enabled && (asclepius_status.main12v_voltage < 10800 || asclepius_status.main12v_voltage > 13200))
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_12v_icon), status_warn_icon_path);
}
if (asclepius_status.main12v_ocp)
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_12v_icon), error_icon_on_path);
@@ -4520,6 +4543,10 @@ void update_asclepius_status(void)
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_5v_icon), status_icon_off_path);
}
if (asclepius_status.main5v_enabled && (asclepius_status.main5v_voltage < 4750 || asclepius_status.main5v_voltage > 5250))
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_5v_icon), status_warn_icon_path);
}
if (asclepius_status.main5v_ocp)
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_5v_icon), error_icon_on_path);
@@ -4533,6 +4560,10 @@ void update_asclepius_status(void)
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_usb_icon), status_icon_off_path);
}
if (asclepius_status.usb5v_enabled && (asclepius_status.main5v_voltage < 4750 || asclepius_status.main5v_voltage > 5250))
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_usb_icon), status_warn_icon_path);
}
if (asclepius_status.usb5v_ocp)
{
gtk_image_set_from_file(GTK_IMAGE(asclepius_usb_icon), error_icon_on_path);
@@ -4847,6 +4878,8 @@ void update_primary_relay_button_settings_ccc(void)
gtk_combo_box_set_active(GTK_COMBO_BOX(asclepius_relay_source_combobox_ccc), relay_source_index);
}
gtk_entry_set_text(GTK_ENTRY(asclepius_tty_device_text_ccc), primary_relay_settings_ccc.asclepius_tty_device);
// gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON (), primary_relay_settings_ccc. );
// gtk_adjustment_ccc = (GtkAdjustment *) gtk_adjustment_new (0, 1, 1, 1, 1, 0);
@@ -5327,7 +5360,13 @@ void do_activate_primary_relay_ccc(void)
if(asclepius_get_connection_status())
{
asclepius_disable_channel(asclepius_relay_source);
if (asclepius_disable_channel(asclepius_relay_source) != 0)
{
snprintf(tempmessage_ccc, TEMP_MESSAGE_SIZE, _("Error operating Asclepius relay, see console for more information"));
message_error_ccc(tempmessage_ccc);
print_gui_error_message_ccc(error_message_ccc, _("Error!"), 1);
clear_error_message_ccc();
}
return;
}
@@ -5426,7 +5465,13 @@ void do_deactivate_primary_relay_ccc(void)
if(asclepius_get_connection_status())
{
asclepius_enable_channel(asclepius_relay_source);
if (asclepius_enable_channel(asclepius_relay_source) != 0)
{
snprintf(tempmessage_ccc, TEMP_MESSAGE_SIZE, _("Error operating Asclepius relay, see console for more information"));
message_error_ccc(tempmessage_ccc);
print_gui_error_message_ccc(error_message_ccc, _("Error!"), 1);
clear_error_message_ccc();
}
return;
}
@@ -5491,6 +5536,24 @@ void do_deactivate_primary_relay_ccc(void)
update_primary_relay_settings_ccc();
}
void do_asclepius_connect_ccc(void)
{
const gchar *tty_device = gtk_entry_get_text(GTK_ENTRY(asclepius_tty_device_text_ccc));
strcpy(asclepius_tty_device_ccc, tty_device);
if (asclepius_connect() != 0)
{
snprintf(tempmessage_ccc, TEMP_MESSAGE_SIZE, _("Error connecting to Asclepius, see console for more information"));
message_error_ccc(tempmessage_ccc);
print_gui_error_message_ccc(error_message_ccc, _("Error!"), 1);
clear_error_message_ccc();
}
}
void do_asclepius_disconnect_ccc(void)
{
asclepius_disconnect();
}
void do_activate_primary_relay_main_ccc(void)
{
int asclepius_relay_source = primary_relay_settings_ccc.asclepius_relay_source;
@@ -5501,7 +5564,13 @@ void do_activate_primary_relay_main_ccc(void)
if(asclepius_get_connection_status())
{
asclepius_disable_channel(asclepius_relay_source);
if (asclepius_disable_channel(asclepius_relay_source) != 0)
{
snprintf(tempmessage_ccc, TEMP_MESSAGE_SIZE, _("Error operating Asclepius relay, see console for more information"));
message_error_ccc(tempmessage_ccc);
print_gui_error_message_ccc(error_message_ccc, _("Error!"), 1);
clear_error_message_ccc();
}
return;
}
@@ -5534,7 +5603,13 @@ void do_deactivate_primary_relay_main_ccc(void)
if(asclepius_get_connection_status())
{
asclepius_enable_channel(asclepius_relay_source);
if (asclepius_enable_channel(asclepius_relay_source) != 0)
{
snprintf(tempmessage_ccc, TEMP_MESSAGE_SIZE, _("Error operating Asclepius relay, see console for more information"));
message_error_ccc(tempmessage_ccc);
print_gui_error_message_ccc(error_message_ccc, _("Error!"), 1);
clear_error_message_ccc();
}
return;
}
@@ -6304,6 +6379,13 @@ void read_config_file_with_name_ccc(char* filename)
}
}
setting = config_setting_get_member(group, "asclepius_tty_device");
if (setting != NULL)
{
const char *atd = config_setting_get_string(setting);
snprintf(primary_relay_settings_ccc.asclepius_tty_device, sizeof(primary_relay_settings_ccc.asclepius_tty_device), "%s", atd);
}
// setting = config_setting_get_member(group, "primary_relay_name");;
// if (setting != NULL)
// {
@@ -6701,6 +6783,9 @@ void write_config_file_with_name_ccc(char* filename)
setting = config_setting_add(group, "asclepius_relay_source", CONFIG_TYPE_INT);
config_setting_set_int(setting, primary_relay_settings_ccc.asclepius_relay_source);
setting = config_setting_add(group, "asclepius_tty_device", CONFIG_TYPE_STRING);
config_setting_set_string(setting, primary_relay_settings_ccc.asclepius_tty_device);
// setting = config_setting_add(group, "primary_relay_name", CONFIG_TYPE_STRING);
// config_setting_set_string(setting, primary_relay_settings_ccc.primary_relay_name);
+4
View File
@@ -359,6 +359,9 @@ GtkWidget *label_current_primary_relay_board_ccc;
GtkWidget *data_current_relay_board_a_ccc;
GtkWidget *asclepius_relay_source_label_ccc;
GtkWidget *asclepius_relay_source_combobox_ccc;
GtkWidget *asclepius_tty_device_text_ccc;
GtkWidget *asclepius_connect_button_ccc;
GtkWidget *asclepius_disconnect_button_ccc;
GtkWidget *primary_relay_board_settings_label_ccc;
GtkWidget *primary_relay_activation_label_ccc;
GtkWidget *activate_primary_relay1_checkbutton_ccc;
@@ -476,6 +479,7 @@ bool button_labeled_start = true;
char *status_icon_off_path = OSC_RESOURCE_PATH "/img/status_off.png";
char *status_icon_on_path = OSC_RESOURCE_PATH "/img/status_on.png";
char *error_icon_on_path = OSC_RESOURCE_PATH "/img/error_on.png";
char *status_warn_icon_path = OSC_RESOURCE_PATH "/img/status_warn.png";
char *smart_info_icon_path = OSC_RESOURCE_PATH "/img/fontawesome/circle-info.svg";
char *smart_warning_icon_path = OSC_RESOURCE_PATH "/img/fontawesome/triangle-exclamation.svg";
char *smart_error_icon_path = OSC_RESOURCE_PATH "/img/fontawesome/xmark.svg";
+2
View File
@@ -117,6 +117,7 @@ char primary_relay_name_ccc[MAX_RELAY_NAME_LENGTH];
unsigned long long primary_relay_activation_time_ccc;
unsigned long long primary_relay_delay_time_ccc;
int asclepius_relay_source_ccc;
char asclepius_tty_device_ccc[256];
bool rebuild_assist_enabled_ccc;
bool use_fpdma_ccc;
bool wait_for_ds_bit_ccc;
@@ -272,6 +273,7 @@ struct
unsigned long long primary_relay_activation_time;
unsigned long long primary_relay_delay_time;
int asclepius_relay_source;
char asclepius_tty_device[256];
char primary_relay_name[MAX_RELAY_NAME_LENGTH];
} primary_relay_settings_ccc;
+1
View File
@@ -205,6 +205,7 @@ int main(int argc, char **argv)
primary_relay_activation_time_ccc = PRIMARY_RELAY_ACTIVATION_TIME;
primary_relay_delay_time_ccc = PRIMARY_RELAY_DELAY_TIME;
asclepius_relay_source_ccc = ASCLEPIUS_ALL;
strcpy(asclepius_tty_device_ccc, "/dev/ttyascl");
use_rebuild_assist_ccc = false;
rebuild_assist_enabled_ccc = false;
drive_port_ccc = -1;
+122 -1
View File
@@ -7900,6 +7900,127 @@ no data</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame_asclepius_tty_device">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment" id="alignment_asclepius_tty_device">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="left-padding">12</property>
<child>
<object class="GtkEntry" id="asclepius_tty_device_text">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="invisible-char">•</property>
<property name="primary-icon-activatable">False</property>
<property name="secondary-icon-activatable">False</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="asclepius_tty_device_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Asclepius TTY device</property>
<property name="use-markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox_asclepius_buttons">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkFrame" id="frame_asclepius_connect">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment" id="alignment_asclepius_connect">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="left-padding">12</property>
<child>
<object class="GtkButton" id="asclepius_connect_button">
<property name="label" translatable="yes">connect</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="do_asclepius_connect_ccc" swapped="no"/>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="asclepius_connect_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame_asclepius_disconnect">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label-xalign">0</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkAlignment" id="alignment_asclepius_disconnect">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="left-padding">12</property>
<child>
<object class="GtkButton" id="asclepius_disconnect_button">
<property name="label" translatable="yes">disconnect</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="do_asclepius_disconnect_ccc" swapped="no"/>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="asclepius_disconnect_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox36">
<property name="visible">True</property>
@@ -7981,7 +8102,7 @@ no data</property>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">5</property>
<property name="position">7</property>
</packing>
</child>
</object>
+2
View File
@@ -1246,6 +1246,7 @@ void load_primary_relay_settings_ccc(void)
primary_relay_settings_ccc.asclepius_relay_source = ASCLEPIUS_ALL;
}
strcpy(primary_relay_settings_ccc.primary_relay_name, primary_relay_name_ccc);
strcpy(primary_relay_settings_ccc.asclepius_tty_device, asclepius_tty_device_ccc);
}
void update_primary_relay_settings_ccc(void)
@@ -1278,6 +1279,7 @@ void update_primary_relay_settings_ccc(void)
asclepius_relay_source_ccc = ASCLEPIUS_ALL;
}
strcpy(primary_relay_name_ccc, primary_relay_settings_ccc.primary_relay_name);
strcpy(asclepius_tty_device_ccc, primary_relay_settings_ccc.asclepius_tty_device);
}
int get_primary_relay_settings_ccc(void)