diff --git a/include/DoocsProcessArray.h b/include/DoocsProcessArray.h
index 490b8037eebbdcf2c43ff90ac75ce8a02433652c..4c5d8eb7cc93fb555ec7bcb640b3418ad53cd456 100644
--- a/include/DoocsProcessArray.h
+++ b/include/DoocsProcessArray.h
@@ -50,6 +50,25 @@ namespace ChimeraTK {
     void set(EqAdr* eqAdr, EqData* data1, EqData* data2, EqFct* eqFct) override {
       DOOCS_T::set(eqAdr, data1, data2, eqFct);
       sendToDevice();
+      // send data via ZeroMQ if enabled
+      if(publishZMQ) {
+        auto timestamp = _processArray->getVersionNumber().getTime();
+        auto seconds = std::chrono::system_clock::to_time_t(timestamp);
+        auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(
+            timestamp - std::chrono::system_clock::from_time_t(seconds))
+                                .count();
+        dmsg_info info;
+        memset(&info, 0, sizeof(info));
+        info.sec = seconds;
+        info.usec = microseconds;
+        if(_macroPulseNumberSource != nullptr) {
+          info.ident = _macroPulseNumberSource->accessData(0);
+        }
+        else {
+          info.ident = 0;
+        }
+        this->send(&info);
+      }
     }
 
     /**
diff --git a/include/DoocsProcessScalar.h b/include/DoocsProcessScalar.h
index 4f8cbe3fc96e94543c85b2197b955663a01cfcf7..b68e7123a0406493d3a74700a3993b2ab5c4a505 100644
--- a/include/DoocsProcessScalar.h
+++ b/include/DoocsProcessScalar.h
@@ -148,6 +148,25 @@ namespace ChimeraTK {
       else {
         throw ChimeraTK::logic_error("Trying to write to a non-writable variable");
       }
+      // send data via ZeroMQ if enabled
+      if(_publishZMQ) {
+        auto timestamp = _processScalar->getVersionNumber().getTime();
+        auto seconds = std::chrono::system_clock::to_time_t(timestamp);
+        auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(
+            timestamp - std::chrono::system_clock::from_time_t(seconds))
+                                .count();
+        dmsg_info info;
+        memset(&info, 0, sizeof(info));
+        info.sec = seconds;
+        info.usec = microseconds;
+        if(_macroPulseNumberSource != nullptr) {
+          info.ident = _macroPulseNumberSource->accessData(0);
+        }
+        else {
+          info.ident = 0;
+        }
+        this->send(&info);
+      }
     }
 
     /**
diff --git a/src/DoocsIfff.cc b/src/DoocsIfff.cc
index b3ee22a6f2c2b142d29543457b81cf56ae401d20..4e665977db4a474cc94d725fd4f52d15e33b1a08 100644
--- a/src/DoocsIfff.cc
+++ b/src/DoocsIfff.cc
@@ -132,6 +132,25 @@ namespace ChimeraTK {
   void DoocsIfff::set(EqAdr* eqAdr, EqData* data1, EqData* data2, EqFct* eqFct) {
     D_ifff::set(eqAdr, data1, data2, eqFct); // inherited functionality fill the local doocs buffer
     sendToApplication();
+
+    if(_publishZMQ) {
+      auto timestamp = _i1Value->getVersionNumber().getTime();
+      auto seconds = std::chrono::system_clock::to_time_t(timestamp);
+      auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(
+          timestamp - std::chrono::system_clock::from_time_t(seconds))
+                              .count();
+      dmsg_info info;
+      memset(&info, 0, sizeof(info));
+      info.sec = seconds;
+      info.usec = microseconds;
+      if(_macroPulseNumberSource != nullptr) {
+        info.ident = _macroPulseNumberSource->accessData(0);
+      }
+      else {
+        info.ident = 0;
+      }
+      this->send(&info);
+    }
   }
 
   void DoocsIfff::auto_init(void) {
diff --git a/src/DoocsSpectrum.cc b/src/DoocsSpectrum.cc
index 70725d6222e371bdee2a6e7742798ce1cf5b7d7d..5fcd87c55864417bd6cc2014291d0e5a26cd9f23 100644
--- a/src/DoocsSpectrum.cc
+++ b/src/DoocsSpectrum.cc
@@ -62,6 +62,25 @@ namespace ChimeraTK {
     D_spectrum::set(eqAdr, data1, data2, eqFct);
     modified = true;
     sendToDevice();
+
+    if(publishZMQ) {
+      auto timestamp = _processArray->getVersionNumber().getTime();
+      auto seconds = std::chrono::system_clock::to_time_t(timestamp);
+      auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(
+          timestamp - std::chrono::system_clock::from_time_t(seconds))
+                              .count();
+      dmsg_info info;
+      memset(&info, 0, sizeof(info));
+      info.sec = seconds;
+      info.usec = microseconds;
+      if(_macroPulseNumberSource != nullptr) {
+        info.ident = _macroPulseNumberSource->accessData(0);
+      }
+      else {
+        info.ident = 0;
+      }
+      this->send(&info);
+    }
   }
 
   void DoocsSpectrum::auto_init(void) {