diff --git a/plugins/src/tascarmod_osceog.cc b/plugins/src/tascarmod_osceog.cc
new file mode 100644
index 00000000..99467570
--- /dev/null
+++ b/plugins/src/tascarmod_osceog.cc
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the TASCAR software, see
+ *
+ * Copyright (c) 2020 Giso Grimm
+ * Copyright (c) 2021 Giso Grimm
+ */
+/*
+ * TASCAR is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, version 3 of the License.
+ *
+ * TASCAR is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHATABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License, version 3 for more details.
+ *
+ * You should have received a copy of the GNU General Public License,
+ * Version 3 along with TASCAR. If not, see .
+ */
+
+#include "session.h"
+#include
+#include
+#include
+
+class osceog_t : public TASCAR::module_base_t {
+public:
+ osceog_t(const TASCAR::module_cfg_t& cfg);
+ virtual ~osceog_t();
+ static int osc_update(const char*, const char*, lo_arg**, int argc,
+ lo_message, void* user_data)
+ {
+ if(user_data && (argc == 3))
+ // first data element is time, discarded for now
+ ((osceog_t*)user_data)->update_eog();
+ return 1;
+ }
+ void update_eog();
+
+private:
+ void connect();
+ void disconnect();
+ void connectservice();
+
+ // EOG path:
+ std::string eogpath = "/eog";
+ // configuration variables:
+ std::string name;
+ // connect to sensor to external WLAN:
+ bool connectwlan = false;
+ // SSID of external WLAN:
+ std::string wlanssid;
+ // password of external WLAN:
+ std::string wlanpass;
+ // target IP address when using external WLAN:
+ std::string targetip;
+ // sample rate
+ uint32_t srate = 128;
+
+ // measure time since last callback, for reconnection attempts if no data
+ // arrives:
+ TASCAR::tictoc_t tictoc;
+ // target address of head tracker, 192.168.100.1:9999 as defined in firmware:
+ lo_address headtrackertarget = NULL;
+ // additional thread which monitors the connection and re-connects in case of
+ // no incoming data
+ std::thread connectsrv;
+ std::atomic run_service;
+ // shortcut for name prefix:
+ std::string p;
+};
+
+void osceog_t::connect()
+{
+ if(connectwlan) {
+ lo_send(headtrackertarget, "/wlan/connect", "sssi", wlanssid.c_str(),
+ wlanpass.c_str(), targetip.c_str(), session->get_srv_port());
+ } else {
+ lo_send(headtrackertarget, "/eog/connect", "is", session->get_srv_port(),
+ eogpath.c_str());
+ }
+ lo_send(headtrackertarget, "/eog/srate", "i", srate);
+}
+
+void osceog_t::disconnect()
+{
+ lo_send(headtrackertarget, "/eog/disconnect", "");
+}
+
+osceog_t::osceog_t(const TASCAR::module_cfg_t& cfg)
+ : module_base_t(cfg), name("osceog"),
+ headtrackertarget(lo_address_new("192.168.100.1", "9999"))
+{
+ GET_ATTRIBUTE(name, "", "Prefix in OSC control variables");
+ GET_ATTRIBUTE(srate, "Hz",
+ "Sensor sampling rate (8, 16, 32, 64, 128, 250, 475, 860)");
+ GET_ATTRIBUTE(eogpath, "",
+ "OSC target path for EOG data, or empty for no EOG");
+ GET_ATTRIBUTE_BOOL(connectwlan, "connect to sensor to external WLAN");
+ GET_ATTRIBUTE(wlanssid, "", "SSID of external WLAN");
+ GET_ATTRIBUTE(wlanpass, "", "passphrase of external WLAN");
+ GET_ATTRIBUTE(targetip, "", "target IP address when using external WLAN");
+ if(connectwlan && (wlanssid.size() == 0))
+ throw TASCAR::ErrMsg(
+ "If sensor is to be connected to WLAN, the SSID must be provided");
+ tictoc.tic();
+ connect();
+ run_service = true;
+ connectsrv = std::thread(&osceog_t::connectservice, this);
+ if(name.size())
+ p = "/" + name;
+ session->add_method(p + eogpath, "dff", &osc_update, this);
+}
+
+void osceog_t::update_eog()
+{
+ tictoc.tic();
+}
+
+osceog_t::~osceog_t()
+{
+ run_service = false;
+ if(connectsrv.joinable())
+ connectsrv.join();
+ disconnect();
+}
+
+void osceog_t::connectservice()
+{
+ size_t cnt = 0;
+ while(run_service) {
+ if(tictoc.toc() > 1) {
+ if(cnt)
+ --cnt;
+ else {
+ // set counter to 1000, to wait for 1 second between reconnection
+ // attempts:
+ cnt = 1000;
+ connect();
+ }
+ }
+ // wait for 1 millisecond:
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+}
+
+REGISTER_MODULE(osceog_t);
+
+/*
+ * Local Variables:
+ * mode: c++
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * compile-command: "make -C .."
+ * End:
+ */