summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorGravatar Gediminas Jakutis <gediminas@varciai.lt> 2018-05-19 12:02:08 +0300
committerGravatar Gediminas Jakutis <gediminas@varciai.lt> 2018-05-19 12:02:08 +0300
commit03b7473d4faddcb87a5e82205a42028768e7c177 (patch)
tree8c21b9d4ef03a82740fc63f7b0512200dbdd4a0d /src/server
parent224585cfb9502534032078f4f059588185490c09 (diff)
downloadcoffeetemp-03b7473d4faddcb87a5e82205a42028768e7c177.tar.gz
coffeetemp-03b7473d4faddcb87a5e82205a42028768e7c177.tar.bz2
coffeetemp-03b7473d4faddcb87a5e82205a42028768e7c177.zip
add support for "live"-flashing new settings.
Diffstat (limited to 'src/server')
-rw-r--r--src/server/gtk.c216
-rw-r--r--src/server/gtk.h1
-rw-r--r--src/server/gtk.obin15864 -> 0 bytes
-rw-r--r--src/server/gtklayout.ui333
-rw-r--r--src/server/gtklayout_flash.ui371
-rw-r--r--src/server/meson.build1
-rw-r--r--src/server/util.c142
-rw-r--r--src/server/util.h11
8 files changed, 962 insertions, 113 deletions
diff --git a/src/server/gtk.c b/src/server/gtk.c
index 36b36bb..f48d1d9 100644
--- a/src/server/gtk.c
+++ b/src/server/gtk.c
@@ -20,6 +20,7 @@
#include <gtk/gtk.h>
#include <time.h>
+#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "gtk.h"
@@ -37,20 +38,45 @@ struct gtkui {
GObject *voltage;
GObject *reslabel;
GObject *voltlabel;
- GObject *showmorebutton;
- GObject *button_on;
- GObject *button_off;
+ GObject *show_more;
+ GObject *show_less;
GObject *ticker;
GError *error;
int showmore;
};
+struct gtkui_flash {
+ GtkBuilder *builder;
+ GObject *window;
+ GObject *ssid;
+ GObject *password;
+ GObject *htemp;
+ GObject *mhtemp;
+ GObject *mltemp;
+ GObject *ltemp;
+ GObject *flashdialog;
+ GObject *dialog_ok;
+ GObject *dialog_text;
+ const char *confdata[6];
+ int close_with_dialog;
+};
+
static struct settings settings;
static struct gtkui gtkui;
+static struct gtkui_flash gtkui_flash;
static int gtkui_update(void *data);
static void gtkui_die(void *data);
-static void gtkui_togglemore(void);
+static int strtokel(const char * const s);
+void gtkui_togglemore(void);
+void gtkui_flashwindow_create(void);
+void gtkui_flashwindow_destroy(void);
+void gtkui_flashwindow_clean(void);
+void gtkui_issue_flash_request(void);
+void gtkui_readhtemp(void);
+void gtkui_readmhtemp(void);
+void gtkui_readmltemp(void);
+void gtkui_readltemp(void);
int gtkui_init(int *argc, char ***argv, int nd, struct timespec period)
{
@@ -66,10 +92,7 @@ int gtkui_init(int *argc, char ***argv, int nd, struct timespec period)
gtkui.builder = gtk_builder_new();
- if (!gtk_builder_add_from_file(gtkui.builder, DATA_DIR "/gtklayout.ui", &gtkui.error)) {
- ret = ERROR;
- goto fail;
- }
+ gtkui.builder = gtk_builder_new_from_file(DATA_DIR "/gtklayout.ui");
gtkui.window = gtk_builder_get_object(gtkui.builder, "window");
gtkui.tempvalue = gtk_builder_get_object(gtkui.builder, "tempvalue");
@@ -77,12 +100,13 @@ int gtkui_init(int *argc, char ***argv, int nd, struct timespec period)
gtkui.voltage = gtk_builder_get_object(gtkui.builder, "voltage");
gtkui.reslabel = gtk_builder_get_object(gtkui.builder, "reslabel");
gtkui.voltlabel = gtk_builder_get_object(gtkui.builder, "voltlabel");
- gtkui.showmorebutton = gtk_builder_get_object(gtkui.builder, "showmore");
- gtkui.button_on = gtk_builder_get_object(gtkui.builder, "button_on");
- gtkui.button_off = gtk_builder_get_object(gtkui.builder, "button_off");
+ gtkui.show_more = gtk_builder_get_object(gtkui.builder, "show_more");
+ gtkui.show_less = gtk_builder_get_object(gtkui.builder, "show_less");
gtkui.ticker = gtk_builder_get_object(gtkui.builder, "ticker");
- g_signal_connect(gtkui.window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
- g_signal_connect(gtkui.showmorebutton, "toggled", G_CALLBACK(gtkui_togglemore), NULL);
+ gtk_builder_connect_signals(gtkui.builder, NULL);
+ g_object_unref(G_OBJECT(gtkui.builder));
+ gtkui.builder = NULL;
+
gtkui.showmore = 1; /* we are setting this so we can toggle this off on the following call */
gtkui_togglemore();
@@ -137,13 +161,165 @@ static void gtkui_die(void *data)
return;
}
-static void gtkui_togglemore(void)
+static int strtokel(const char * const s)
+{
+ int ret;
+
+ ret = atoi(s);
+ ret += 273;
+ ret *= 10;
+
+ return ret;
+}
+
+void gtkui_togglemore(void)
{
gtkui.showmore = !gtkui.showmore;
- gtkui.showmore ? gtk_button_set_image(GTK_BUTTON(gtkui.showmorebutton), GTK_WIDGET(gtkui.button_on)) :
- gtk_button_set_image(GTK_BUTTON(gtkui.showmorebutton), GTK_WIDGET(gtkui.button_off));
- gtk_widget_set_visible (GTK_WIDGET(gtkui.resistance), gtkui.showmore);
- gtk_widget_set_visible (GTK_WIDGET(gtkui.voltage), gtkui.showmore);
- gtk_widget_set_visible (GTK_WIDGET(gtkui.reslabel), gtkui.showmore);
- gtk_widget_set_visible (GTK_WIDGET(gtkui.voltlabel), gtkui.showmore);
+
+ /* this actually switches them around their state */
+ gtk_widget_set_visible(GTK_WIDGET(gtkui.show_more), !gtkui.showmore);
+ gtk_widget_set_visible(GTK_WIDGET(gtkui.show_less), gtkui.showmore);
+
+ gtk_widget_set_visible(GTK_WIDGET(gtkui.resistance), gtkui.showmore);
+ gtk_widget_set_visible(GTK_WIDGET(gtkui.voltage), gtkui.showmore);
+ gtk_widget_set_visible(GTK_WIDGET(gtkui.reslabel), gtkui.showmore);
+ gtk_widget_set_visible(GTK_WIDGET(gtkui.voltlabel), gtkui.showmore);
+}
+
+void gtkui_flashwindow_create(void)
+{
+ if (gtkui_flash.window) {
+ goto fail;
+ }
+
+ gtkui_flash.builder = gtk_builder_new_from_file(DATA_DIR "/gtklayout_flash.ui");
+ gtkui_flash.window = gtk_builder_get_object(gtkui_flash.builder, "flashwindow");
+ gtkui_flash.ssid = gtk_builder_get_object(gtkui_flash.builder, "ssid_entry");
+ gtkui_flash.password = gtk_builder_get_object(gtkui_flash.builder, "pass_entry");
+ gtkui_flash.htemp = gtk_builder_get_object(gtkui_flash.builder, "htemp_entry");
+ gtkui_flash.mhtemp = gtk_builder_get_object(gtkui_flash.builder, "mhtemp_entry");
+ gtkui_flash.mltemp = gtk_builder_get_object(gtkui_flash.builder, "mltemp_entry");
+ gtkui_flash.ltemp = gtk_builder_get_object(gtkui_flash.builder, "ltemp_entry");
+ gtkui_flash.flashdialog = gtk_builder_get_object(gtkui_flash.builder, "flashdialog");
+ gtkui_flash.dialog_ok = gtk_builder_get_object(gtkui_flash.builder, "dialog_ok");
+ gtkui_flash.dialog_text = gtk_builder_get_object(gtkui_flash.builder, "dialog_text");
+ gtk_builder_connect_signals(gtkui_flash.builder, NULL);
+ g_object_unref(G_OBJECT(gtkui_flash.builder));
+ gtkui_flash.builder = NULL;
+
+fail:
+ return;
+}
+
+void gtkui_window_destroy(void *window)
+{
+ gtk_window_close(GTK_WINDOW(window));
+}
+
+void gtkui_flashwindow_clean(void)
+{
+ gtkui_flash.window = NULL;
+}
+
+void gtkui_issue_flash_request(void)
+{
+ static const struct configuration def = {{{
+ PADDING_START,
+ "ssid", /* ssid */
+ "password", /* password */
+ {3330, 3230, 3130, 3030}, /* calibration */
+ PADDING_END
+ }}};
+
+ struct configuration conf;
+ size_t i;
+ size_t len;
+ const char *tmp;
+
+ gtk_widget_set_visible(GTK_WIDGET(gtkui_flash.flashdialog), 1);
+
+ for (i = 0; i < sizeof (gtkui_flash.confdata); ++i) {
+ switch (i) {
+ case 0:
+ tmp = gtkui_flash.confdata[i] ? gtkui_flash.confdata[i] : def.ssid;
+ len = strlen(tmp) > (sizeof(conf.ssid) - 1) ? sizeof(conf.ssid) - 1 : strlen(tmp);
+ memcpy(conf.ssid, tmp, len);
+ conf.ssid[len] = '\0';
+ break;
+ case 1:
+ tmp = gtkui_flash.confdata[i] ? gtkui_flash.confdata[i] : def.password;
+ len = strlen(tmp) > (sizeof(conf.password) - 1) ? sizeof(conf.password) - 1 : strlen(tmp);
+ memcpy(conf.password, tmp, len);
+ conf.password[len] = '\0';
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ tmp = gtkui_flash.confdata[i] ? (char *) strlen(gtkui_flash.confdata[i]) : NULL;
+ conf.calibration[i - 2] = tmp ? strtokel(gtkui_flash.confdata[i]) : def.calibration[i -2];
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ write_settings(DATA_DIR "/fw.bin", &conf);
+}
+
+void gtkui_readssid(void)
+{
+ gtkui_flash.confdata[0] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.ssid));
+}
+
+void gtkui_readpass(void)
+{
+ gtkui_flash.confdata[1] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.password));
+}
+
+void gtkui_readhtemp(void)
+{
+ gtkui_flash.confdata[2] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.htemp));
+}
+
+void gtkui_readmhtemp(void)
+{
+ gtkui_flash.confdata[3] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.mhtemp));
+}
+
+void gtkui_readmltemp(void)
+{
+ gtkui_flash.confdata[4] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.mltemp));
+}
+
+void gtkui_readltemp(void)
+{
+ gtkui_flash.confdata[5] = gtk_entry_get_text(GTK_ENTRY(gtkui_flash.ltemp));
+}
+
+void gtkui_manhandle_flashdialog(void *dialog)
+{
+ gtk_label_set_markup(GTK_LABEL(gtkui_flash.dialog_text), "Writing to flash... ");
+ if (gtkui_flash.close_with_dialog) {
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+ /* we also want to close tha parent */
+ gtk_window_close(GTK_WINDOW(gtkui_flash.window));
+ } else {
+ gtk_widget_set_visible(GTK_WIDGET(dialog), 0);
+ }
+}
+
+void gtkui_dialog_done(int status)
+{
+ static const char * const text[2] = {"done", "FAIL"};
+ static const char * const color[2] = {"#4E9A06", "#EF2929"};
+ char msg[128];
+
+ status = status ? 1 : status;
+ gtkui_flash.close_with_dialog = !status;
+ sprintf(msg, "Writing to flash... <span foreground=\"%s\" font_weight=\"bold\">%s!</span>", color[status], text[status]);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(gtkui_flash.dialog_ok), 1);
+ gtk_label_set_markup(GTK_LABEL(gtkui_flash.dialog_text), msg);
}
diff --git a/src/server/gtk.h b/src/server/gtk.h
index 0c47b0b..ad739e5 100644
--- a/src/server/gtk.h
+++ b/src/server/gtk.h
@@ -27,5 +27,6 @@
int gtkui_init(int *argc, char ***argv, int nd, struct timespec period);
int gtkui_loop(void);
+void gtkui_dialog_done(int status);
#endif /* GTK_H_INCLUDED */
diff --git a/src/server/gtk.o b/src/server/gtk.o
deleted file mode 100644
index 0c2098d..0000000
--- a/src/server/gtk.o
+++ /dev/null
Binary files differ
diff --git a/src/server/gtklayout.ui b/src/server/gtklayout.ui
index 69fd947..e6d3f5a 100644
--- a/src/server/gtklayout.ui
+++ b/src/server/gtklayout.ui
@@ -2,12 +2,17 @@
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
- <object class="GtkImage" id="button_off">
+ <object class="GtkImage" id="gtk-flash">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-properties</property>
+ </object>
+ <object class="GtkImage" id="gtk-no-stock">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-no</property>
</object>
- <object class="GtkImage" id="button_on">
+ <object class="GtkImage" id="gtk-yes-stock">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-yes</property>
@@ -15,112 +20,260 @@
<object class="GtkWindow" id="window">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="title" translatable="yes">Coffeetemp</property>
<property name="resizable">False</property>
+ <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child>
- <object class="GtkGrid">
+ <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="ticker">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes"> Temperature: </property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="tempvalue">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkToggleButton" id="showmore">
- <property name="label" translatable="yes">show all</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">button_on</property>
- <property name="always_show_image">True</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="left_attach">3</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="reslabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes"> Resistence: </property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="resistance">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="voltage">
+ <object class="GtkMenuBar" id="menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="gtk_main_quit" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">_Reflash</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="image">gtk-flash</property>
+ <property name="use_stock">False</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="gtkui_flashwindow_create" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem" id="show_more">
+ <property name="label">Show _more</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="image">gtk-yes-stock</property>
+ <property name="use_stock">False</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="gtkui_togglemore" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="show_less">
+ <property name="label">Show _less</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="image">gtk-no-stock</property>
+ <property name="use_stock">False</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="gtkui_togglemore" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem">
+ <property name="label">gtk-about</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <property name="always_show_image">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
<packing>
- <property name="left_attach">2</property>
- <property name="top_attach">2</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="voltlabel">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes"> Voltage: </property>
+ <child>
+ <object class="GtkLabel" id="ticker">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">4</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes"> Temperature: </property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="tempvalue">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="reslabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes"> Resistence: </property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="resistance">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="voltage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="voltlabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes"> Voltage: </property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
</object>
</child>
</object>
diff --git a/src/server/gtklayout_flash.ui b/src/server/gtklayout_flash.ui
new file mode 100644
index 0000000..9972a4e
--- /dev/null
+++ b/src/server/gtklayout_flash.ui
@@ -0,0 +1,371 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkImage" id="cancel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-cancel</property>
+ </object>
+ <object class="GtkImage" id="ok">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-apply</property>
+ </object>
+ <object class="GtkWindow" id="flashwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">coffeetemp – write flash</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">True</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <signal name="destroy" handler="gtkui_flashwindow_clean" swapped="no"/>
+ <child>
+ <object class="GtkEntry" id="ssid_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">32</property>
+ <signal name="changed" handler="gtkui_readssid" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pass_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">32</property>
+ <property name="visibility">False</property>
+ <property name="input_purpose">password</property>
+ <signal name="changed" handler="gtkui_readpass" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="htemp_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">6</property>
+ <property name="input_purpose">digits</property>
+ <signal name="changed" handler="gtkui_readhtemp" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">SSID:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Password:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">High Temp:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Mid-high Temp:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="mhtemp_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">6</property>
+ <property name="input_purpose">digits</property>
+ <signal name="changed" handler="gtkui_readmhtemp" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">°C</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">°C</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancelbutton">
+ <property name="label" translatable="yes">Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">cancel</property>
+ <signal name="clicked" handler="gtk_window_close" object="flashwindow" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="flashbutton">
+ <property name="label" translatable="yes">Write Flash</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">ok</property>
+ <signal name="clicked" handler="gtkui_issue_flash_request" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Low Temp:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="ltemp_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">6</property>
+ <property name="input_purpose">digits</property>
+ <signal name="changed" handler="gtkui_readltemp" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">°C</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">1</property>
+ <property name="margin_bottom">1</property>
+ <property name="label" translatable="yes">°C</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">1</property>
+ <property name="margin_bottom">1</property>
+ <property name="label" translatable="yes">Mid-low Temp:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="mltemp_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">6</property>
+ <property name="input_purpose">digits</property>
+ <signal name="changed" handler="gtkui_readmltemp" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkDialog" id="flashdialog">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Flashing...</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="transient_for">flashwindow</property>
+ <property name="attached_to">flashwindow</property>
+ <signal name="close" handler="gtkui_manhandle_flashdialog" swapped="no"/>
+ <signal name="delete-event" handler="gtk_widget_hide_on_delete" swapped="no"/>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="dialog_ok">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="gtkui_manhandle_flashdialog" object="flashdialog" swapped="yes"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dialog_text">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">3</property>
+ <property name="margin_right">3</property>
+ <property name="margin_top">3</property>
+ <property name="margin_bottom">3</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Writing to flash... </property>
+ <property name="width_chars">25</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/src/server/meson.build b/src/server/meson.build
index c95f9a9..2b7af61 100644
--- a/src/server/meson.build
+++ b/src/server/meson.build
@@ -14,6 +14,7 @@ dp_filenames = [
dp_extra_filenames = [
'gtklayout.ui',
+ 'gtklayout_flash.ui',
]
dp_sources = files(dp_filenames)
diff --git a/src/server/util.c b/src/server/util.c
index bb494c8..4aee886 100644
--- a/src/server/util.c
+++ b/src/server/util.c
@@ -18,12 +18,32 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <gtk/gtk.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <endian.h>
#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
#include "util.h"
#include "net.h"
+#include "gtk.h"
+
+struct child_data {
+ char **argv;
+ int fd;
+ char *buf;
+};
static float digest_temp(const short int rawtemp);
static float digest_volt(const short int rawvolt);
+static int find_settings_region(char *start, char *end, char *buf, size_t n);
+static int flash(char *buf, size_t address, size_t size, char* port);
+void reap_dead_children(int pid, int status, void *data);
/*
* raw data is in 0.1°K per 1. Subtract 2730 to get Celsius.
@@ -57,3 +77,125 @@ int refresh_data(int nd, struct tempmodule_state *state)
return ret;
}
+
+
+int write_settings(char *imagename, const struct configuration * const conf)
+{
+ /* the largest flash size supported by ESP-8266 is 16MiB, so let's just use that. */
+ static const size_t flash_size = 16 * 1024 * 1024;
+ char pattern_a[4] = PADDING_START;
+ char pattern_b[4] = PADDING_END;
+ ssize_t buf_used;
+ ssize_t offset;
+ char *buf = NULL;
+ int fd;
+ int ret = ERROR;
+
+ fd = open(imagename, O_RDONLY);
+ if (fd < 0) {
+ goto fail;
+ }
+ buf = malloc(flash_size);
+ buf_used = read(fd, buf, flash_size);
+ close(fd);
+ if (buf_used < sizeof(struct configuration)) {
+ goto fail;
+ }
+
+ offset = find_settings_region(pattern_a, pattern_b, buf, buf_used);
+ if (offset == ERROR) {
+ goto fail;
+ };
+
+ memcpy(buf + offset, conf, sizeof(struct configuration));
+ /* make sure the block written is aligned on 4k boundry
+ * and is 4k of size.
+ *
+ * see:
+ * https://github.com/espressif/esptool/issues/306
+ */
+ offset &= ~(0xfff);
+ ret = flash(buf + offset, offset, 4 * 1024, NULL);
+
+fail:
+ free(buf);
+ return ret;
+}
+
+static int find_settings_region(char *start, char *end, char *buf, size_t n)
+{
+ int ret = ERROR;
+ char *a;
+
+ if (!(a = memmem(buf, n, start, 4))) {
+ goto fail;
+ }
+
+ if ((a - buf + sizeof(struct configuration)) > n) {
+ goto fail;
+ }
+
+ if (memcmp(a + sizeof(struct configuration) - 4, end, 4)) {
+ goto fail;
+ }
+
+ ret = a - buf;
+fail:
+ return ret;
+}
+
+static int flash(char *buf, size_t address, size_t size, char* port)
+{
+ static const char esptool[] = "esptool.py";
+ static const char command[] = "write_flash";
+ struct child_data *cdata;
+ char tmpfn[] = "espXXXXXX"; /* temporary file name template */
+ char *fifn; /* flash image file name */
+ char textbuf[32];
+ char *argv[7] = {0};
+ int ret = ERROR;
+ pid_t pid;
+ int fd;
+ size_t i = 1;
+
+ fd = mkstemp(tmpfn);
+ write(fd, buf, size);
+ fifn = malloc(0x100);
+ memset(fifn, '\0', 0x100);
+ sprintf(textbuf, "/proc/self/fd/%d", fd);
+ if (readlink(textbuf, fifn, 0x100) == -1) {
+ exit(TMPFILE);
+ }
+
+ argv[0] = strdup(esptool);
+ if (port) {
+ argv[i++] = strdup("--port");
+ argv[i++] = strdup(port);
+ }
+ argv[i++] = strdup(command);
+ sprintf(textbuf, "%#.4lx", address);
+ argv[i++] = strdup(textbuf);
+ argv[i++] = strdup(fifn);
+ argv[i] = NULL;
+
+ cdata = malloc(sizeof(*cdata));
+ cdata->argv = argv;
+ cdata->fd = fd;
+ cdata->buf = fifn;
+
+ g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL, NULL, NULL, NULL);
+ g_child_watch_add(pid, reap_dead_children, cdata);
+ return ret;
+}
+
+void reap_dead_children(int pid, int status, void *data)
+{
+ struct child_data *a;
+
+ a = data;
+ free(a->buf);
+ close(a->fd);
+ free(data);
+ g_spawn_close_pid(pid);
+ gtkui_dialog_done(status);
+}
diff --git a/src/server/util.h b/src/server/util.h
index 9c0f907..ef5cde2 100644
--- a/src/server/util.h
+++ b/src/server/util.h
@@ -21,13 +21,17 @@
#ifndef UTIL_H_INCLUDED
#define UTIL_H_INCLUDED
+#include "datatypes.h"
+
#define arrsize(a) (sizeof(a)/sizeof(*a))
enum response {
ERROR = -1,
- A_OK = 0,
- NONEWDATA = 1,
- DEAD = 2
+ A_OK = 0, /* would be "OK", but clashes with some lib definitions */
+ NONEWDATA,
+ DEAD,
+ NO_ESPTOOL,
+ TMPFILE,
};
struct tempmodule_state {
@@ -51,5 +55,6 @@ struct tempmodule_state {
};
int refresh_data(int nd, struct tempmodule_state *state);
+int write_settings(char *imagename, const struct configuration * const conf);
#endif /* UTIL_H_INCLUDED */