<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Apache StreamPipes Blog</title>
        <link>https://streampipes.apache.org/blog</link>
        <description>Apache StreamPipes Blog</description>
        <lastBuildDate>Sat, 21 Mar 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[StreamPipes on Windows with Podman]]></title>
            <link>https://streampipes.apache.org/blog/2026/03/21/_streampipes-with-windows-and-podman</link>
            <guid>https://streampipes.apache.org/blog/2026/03/21/_streampipes-with-windows-and-podman</guid>
            <pubDate>Sat, 21 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[When it comes to ease of use, Docker Desktop is the goto on windows platform, however for business use there are licensing involved.]]></description>
            <content:encoded><![CDATA[<p>When it comes to ease of use, Docker Desktop is the goto on windows platform, however for business use there are licensing involved.</p><p>So why not use Podman Desktop, it’s Docker compatible?
Well yes, almost, would be the answer.<br>
For Podman Desktop to handle Apache StreamPipes we need to do a few tricks.</p><p>This guide walks you through installing and running Apache StreamPipes using Podman inside a WSL environment and will try to explain to you the how’s and why’s.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisits">Prerequisits<a href="#prerequisits" class="hash-link" aria-label="Direct link to Prerequisits" title="Direct link to Prerequisits">​</a></h2><a href="https://learn.microsoft.com/en-us/windows/wsl/install" target="_blank" rel="noopener noreferrer">Enable WSL on your machine.</a><br><a href="https://podman-desktop.io/" target="_blank" rel="noopener noreferrer"> Install Podman Desktop.</a><p>After installing Podman Desktop you need to run the setup to enable Podman core.</p><img loading="lazy" src="/img/blog/2026-03-21/podman-setup.png" alt="Setup Podman" class="img_ev3q"><p>Alter this you can setup a virtual machine in which to host Apache Streampipes on.</p><img loading="lazy" src="/img/blog/2026-03-21/create-podman-machine.png" alt="Setup virtual machine" class="img_ev3q"><p>Now we have to embark on a voyage into the (dark) Linux terminal country, so that we can later enjoy the use of a familiar Windows UI in Podman Desktop.</p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="connect-to-your-podman-wsl-machine">Connect to Your Podman WSL Machine<a href="#connect-to-your-podman-wsl-machine" class="hash-link" aria-label="Direct link to Connect to Your Podman WSL Machine" title="Direct link to Connect to Your Podman WSL Machine">​</a></h2><p>Open PowerShell to get a list of available machines.</p><div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">wsl -l</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><img loading="lazy" src="/img/blog/2026-03-21/wsl.png" alt="Available machines" class="img_ev3q"><br><br><p>Or you can see the Podman machine in the tray menu</p><img loading="lazy" src="/img/blog/2026-03-21/podman-machine.png" alt="Available machines tray" class="img_ev3q"><br><p>In PowerShell connect to the Podman machine.</p><div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">wsl -d podman-machine-default</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="install-required-tools">Install Required Tools<a href="#install-required-tools" class="hash-link" aria-label="Direct link to Install Required Tools" title="Direct link to Install Required Tools">​</a></h2><p>Podman uses Fedora Linux and the dnf package manager. Install the following packages to make your life easier.</p><ul><li>podman-compose</li></ul><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> dnf </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> podman-compose.noarch </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ul><li>unzip</li></ul><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> dnf </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> unzip.x86_64 </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ul><li>nano</li></ul><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> dnf </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> nano.x86_64 </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ul><li>mc</li></ul><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> dnf </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> mc.x86_64 </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-apache-streampipes">Get Apache StreamPipes<a href="#get-apache-streampipes" class="hash-link" aria-label="Direct link to Get Apache StreamPipes" title="Direct link to Get Apache StreamPipes">​</a></h2><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><p>For ease save it in a subfolder on your C-drive, e.g. c:\Download <br>
Lets make a folder in WSL to hold our files, and go into it.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">mkdir</span><span class="token plain"> StreamPipes</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">cd</span><span class="token plain"> StreamPipes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>We can now directly copy the downloaded *.zip file to our WSL, note the version number on the zip file.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">cp</span><span class="token plain"> /mnt/c/Download/apache-streampipes-0.98.0-source-release.zip /home/user/StreamPipes/</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>If the terminal is still a bit outside you'r comfort zone Midnight Commander can help you.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">mc</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><img loading="lazy" src="/img/blog/2026-03-21/mc-copy.png" alt="Use Midnight Commander" class="img_ev3q"><p>It is possible to reach your WSL from Windows filemanager, but unzipping files will give issues due to long filenames.
Therefore the approch of handling the files from WSL is preferable.</p><img loading="lazy" src="/img/blog/2026-03-21/zip-fail.jpg" alt="Fail" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="unpack-and-navigate-to-the-compose-directory">Unpack and Navigate to the Compose Directory<a href="#unpack-and-navigate-to-the-compose-directory" class="hash-link" aria-label="Direct link to Unpack and Navigate to the Compose Directory" title="Direct link to Unpack and Navigate to the Compose Directory">​</a></h2><p>Unzip the package by using the unzip command and navigate to the extracted folder and go to 'installer/compose' directory.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">unzip</span><span class="token plain"> apache-streampipes-0.98.0-source-release.zip</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token builtin class-name" style="color:rgb(255, 203, 107)">cd</span><span class="token plain"> apache-streampipes-0.98.0/installer/compose</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="update-docker-composeyml">Update docker-compose.yml<a href="#update-docker-composeyml" class="hash-link" aria-label="Direct link to Update docker-compose.yml" title="Direct link to Update docker-compose.yml">​</a></h2><p>Modify the docker-compose-yml with nano</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">nano</span><span class="token plain"> docker-compose.yml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>And add the following.</p><div class="language-config codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-config codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">- ./nginx_config/default.conf:/etc/nginx/conf.d/default.conf:ro</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Looking like this.</p><img loading="lazy" src="/img/blog/2026-03-21/nano-docker-compose.jpg" alt="Edit compose" class="img_ev3q"><p>Remove this line since it is not relevant for this setup.  </p><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> SP_HTTP_SERVER_ADAPTER_ENDPOINT=extensions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">all</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">iiot</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token number" style="color:rgb(247, 140, 108)">8090</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>And yes you can copy paste from windows into nano.
Use CRTL + x to quit, and answer ‘y’ to save the file.
Here is how the docker-compose.yml should look loke</p><div class="language-compose codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-compose codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Licensed to the Apache Software Foundation (ASF) under one or more</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># contributor license agreements.  See the NOTICE file distributed with</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># this work for additional information regarding copyright ownership.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># The ASF licenses this file to You under the Apache License, Version 2.0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># (the "License"); you may not use this file except in compliance with</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># the License.  You may obtain a copy of the License at</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">#</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">#    http://www.apache.org/licenses/LICENSE-2.0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">#</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Unless required by applicable law or agreed to in writing, software</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># distributed under the License is distributed on an "AS IS" BASIS,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># See the License for the specific language governing permissions and</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># limitations under the License.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># global logging</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">x-logging:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  &amp;default-logging</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  options:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    max-size: '12m'</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    max-file: '5'</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  driver: json-file</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">services:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  # StreamPipes services</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  backend:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    image: "${SP_DOCKER_REGISTRY}/backend:${SP_VERSION}"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    depends_on:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - couchdb</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    environment:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - SP_PRIORITIZED_PROTOCOL=nats</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    volumes:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - backend:/root/.streampipes</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    logging: *default-logging</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    restart: unless-stopped</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    networks:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      spnet:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  ui:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    image: "${SP_DOCKER_REGISTRY}/ui:${SP_VERSION}"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    ports:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - "80:8088"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    depends_on:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - couchdb</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - backend</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    volumes:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - nginx:/etc/nginx/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - ./nginx_config/default.conf:/etc/nginx/conf.d/default.conf:ro</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    logging: *default-logging</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    restart: unless-stopped</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    networks:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      spnet:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  couchdb:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    image: couchdb:3.3.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    environment:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - COUCHDB_USER=admin</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - COUCHDB_PASSWORD=admin</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    volumes:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - couchdb:/opt/couchdb/data</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    logging: *default-logging</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    restart: unless-stopped</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    networks:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      spnet:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  influxdb:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    image: influxdb:2.6</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    environment:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - INFLUXDB_DATA_ENGINE=tsm1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - INFLUXDB_REPORTING_DISABLED=false</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - INFLUXDB_ADMIN_ENABLED=true</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - DOCKER_INFLUXDB_INIT_USERNAME=admin</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - DOCKER_INFLUXDB_INIT_PASSWORD=sp-admin</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=sp-admin</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - DOCKER_INFLUXDB_INIT_ORG=sp</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - DOCKER_INFLUXDB_INIT_BUCKET=sp</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - DOCKER_INFLUXDB_INIT_MODE=${SP_INFLUX_INIT_MODE}</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    volumes:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - influxdb:/var/lib/influxdb</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      - influxdb2:/var/lib/influxdb2</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    logging: *default-logging</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    restart: unless-stopped</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    networks:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      spnet:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  nats:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    image: nats</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    restart: unless-stopped</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    networks:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      spnet:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  # Lite version pipeline elements</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  extensions-all-iiot:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    image: "${SP_DOCKER_REGISTRY}/extensions-all-iiot:${SP_VERSION}"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    logging: *default-logging</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    restart: unless-stopped</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    networks:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      spnet:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">volumes:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  backend:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  couchdb:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  influxdb:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  influxdb2:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  nginx:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">networks:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  spnet:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    driver: bridge</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="add-custom-nginx-configuration">Add Custom Nginx Configuration<a href="#add-custom-nginx-configuration" class="hash-link" aria-label="Direct link to Add Custom Nginx Configuration" title="Direct link to Add Custom Nginx Configuration">​</a></h2><p>Create a 'nginx_config' directory </p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">mkdir</span><span class="token plain"> nginx_config</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>In that directory you add a 'default.conf' with the help of Nano.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token builtin class-name" style="color:rgb(255, 203, 107)">cd</span><span class="token plain"> nginx_config</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">nano</span><span class="token plain"> default.conf</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The following nginx.conf is almost identical to the default Docker-based setup, with the only change being that the resolve parameter is removed as it doesn't work reliably with Podman's networking. </p><div class="language-config codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-config codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">server {</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  listen       8088 default_server;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  root /usr/share/nginx/html;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  # Enable gzip compression</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip on;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip_static on;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip_proxied  any;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip_vary on;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip_comp_level 6;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip_buffers 16 8k;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  gzip_http_version 1.1;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  # StreamPipes Backend Proxy</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  location /streampipes-backend {</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    proxy_set_header X-Real-IP $remote_addr;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    proxy_set_header X-NginX-Proxy true;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    proxy_pass http://backend:8030;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    proxy_ssl_session_reuse off;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    proxy_set_header Host $http_host;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    proxy_redirect off;</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Now we are almost there, and you are getting good at this terminal thing, so is there a use for Podman Desktop, you ask yourself?</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="start-up-streampipes-using-podman-compose">Start Up StreamPipes Using Podman Compose<a href="#start-up-streampipes-using-podman-compose" class="hash-link" aria-label="Direct link to Start Up StreamPipes Using Podman Compose" title="Direct link to Start Up StreamPipes Using Podman Compose">​</a></h2><p>Do</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">podman-compose</span><span class="token plain"> -f docker-compose.yml up -d</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>to import and run all containers. </p><img loading="lazy" src="/img/blog/2026-03-21/podman-compose-done.png" alt="Done" class="img_ev3q"><br>Once complete, Apache StreamPipes will be available in Podman Desktop and accessible at <a href="http://localhost:80" target="_blank" rel="noopener noreferrer">http://localhost:80</a>.<img loading="lazy" src="/img/blog/2026-03-21/podman-running.png" alt="Running" class="img_ev3q"><p>Congratulations, now we can start to use the strongpoints of Podman which enable us in a fast and terminal free way to make backups of our projects or scale them further with Kubernetes.</p><p>Happy StreamPiping on Windows with Podman Desktop</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Persistent State for StreamPipes Functions]]></title>
            <link>https://streampipes.apache.org/blog/2026/02/23/_streampipes-functions</link>
            <guid>https://streampipes.apache.org/blog/2026/02/23/_streampipes-functions</guid>
            <pubDate>Mon, 23 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[With the introduction of StreamPipes Functions, Apache StreamPipes provides a lightweight way to attach fixed runtime logic to existing streams — without creating a full pipeline element.]]></description>
            <content:encoded><![CDATA[<p>With the introduction of <strong>StreamPipes Functions</strong>, Apache StreamPipes provides a lightweight way to attach fixed runtime logic to existing streams — without creating a full pipeline element.</p><p>Functions are ideal when:</p><ul><li>A full processor would be overkill  </li><li>You want logic that runs with the extensions service lifecycle  </li><li>You need direct access to incoming events  </li></ul><p>Previously, functions could maintain in-memory state during runtime, but any restart of the extensions service resulted in a complete state reset.</p><p>We now provide a new functionality in <strong>developer preview</strong> that introduces typed state persistence for Functions, allowing state to survive service restarts.</p><p>This allows functions to survive restarts and resume exactly where they stopped.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-stateful-functions">Why Stateful Functions?<a href="#why-stateful-functions" class="hash-link" aria-label="Direct link to Why Stateful Functions?" title="Direct link to Why Stateful Functions?">​</a></h2><p>Many real-world use cases require minimal but persistent runtime state:</p><ul><li>Counting processed events  </li><li>Tracking the last processed timestamp  </li><li>Storing threshold configurations  </li><li>Keeping lightweight usage statistics  </li></ul><p>Previously, developers had to implement external persistence manually.<br>
<!-- -->Now, state management is built directly into the Function lifecycle.</p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-new-state-store-api">The New State Store API<a href="#the-new-state-store-api" class="hash-link" aria-label="Direct link to The New State Store API" title="Direct link to The New State Store API">​</a></h2><p>The <code>FunctionContext</code> now provides access to a typed state store:</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token class-name" style="color:rgb(255, 203, 107)">StateStore</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generics class-name" style="color:rgb(255, 203, 107)">T</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getStateStore</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Class</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generics class-name" style="color:rgb(255, 203, 107)">T</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> stateClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This API allows you to:</p><ul><li>Load persisted state during startup</li><li>Persist state on shutdown</li></ul><p>State handling is <strong>fully optional and backward compatible</strong>.
If you don’t request a state store, your function behaves exactly as before.</p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="lifecycle-integration">Lifecycle Integration<a href="#lifecycle-integration" class="hash-link" aria-label="Direct link to Lifecycle Integration" title="Direct link to Lifecycle Integration">​</a></h2><p>Functions still follow the same lifecycle:</p><ul><li><code>onServiceStarted(FunctionContext context)</code></li><li><code>onEvent(Event event, String streamId)</code></li><li><code>onServiceStopped()</code></li></ul><p>The only difference is that you can now initialize a <code>StateStore</code> during startup.</p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="example-threshold-monitoring-function">Example: Threshold Monitoring Function<a href="#example-threshold-monitoring-function" class="hash-link" aria-label="Direct link to Example: Threshold Monitoring Function" title="Direct link to Example: Threshold Monitoring Function">​</a></h2><p>Let’s implement a simple function that:</p><ul><li>Counts processed events</li><li>Tracks the last processed timestamp</li><li>Logs a message when a threshold is reached</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-define-the-state-object">1. Define the State Object<a href="#1-define-the-state-object" class="hash-link" aria-label="Direct link to 1. Define the State Object" title="Direct link to 1. Define the State Object">​</a></h3><p>State is defined as a typed POJO.</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ProcessingState</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">int</span><span class="token plain"> schemaVersion </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">long</span><span class="token plain"> processedEventCount </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">long</span><span class="token plain"> lastProcessedEpochMs </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">long</span><span class="token plain"> alertThreshold </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ProcessingState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// getters/setters omitted for brevity</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><hr><h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-implement-the-stateful-function">2. Implement the Stateful Function<a href="#2-implement-the-stateful-function" class="hash-link" aria-label="Direct link to 2. Implement the Stateful Function" title="Direct link to 2. Implement the Stateful Function">​</a></h3><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ThresholdMonitoringFunction</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">StreamPipesFunction</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">StateStore</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generics class-name" style="color:rgb(255, 203, 107)">ProcessingState</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> stateStore</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ProcessingState</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getFunctionId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"threshold-monitoring-function"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">List</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generics class-name" style="color:rgb(255, 203, 107)">String</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">requiredStreamIds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">List</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">of</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"your-stream-resource-id"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStarted</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Request typed state store</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">this</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">stateStore </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getStateStore</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">ProcessingState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">class</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Load existing state or use default</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">this</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">state </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> stateStore</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">load</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ProcessingState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onEvent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Event</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token plain"> streamId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">setProcessedEventCount</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getProcessedEventCount</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">setLastProcessedEpochMs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token class-name" style="color:rgb(255, 203, 107)">System</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">currentTimeMillis</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getProcessedEventCount</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;=</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getAlertThreshold</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Handle alert once when threshold is reached</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStopped</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Persist state before shutdown</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        stateStore</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">persist</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="state-persistence-lifecycle">State Persistence Lifecycle<a href="#state-persistence-lifecycle" class="hash-link" aria-label="Direct link to State Persistence Lifecycle" title="Direct link to State Persistence Lifecycle">​</a></h2><p>The persistence mechanism follows a simple and predictable pattern:</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="startup">Startup<a href="#startup" class="hash-link" aria-label="Direct link to Startup" title="Direct link to Startup">​</a></h3><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">state </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> stateStore</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">load</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token keyword" style="font-style:italic">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ProcessingState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ul><li>If persisted state exists → it is restored</li><li>If not → the provided default object is used</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="runtime">Runtime<a href="#runtime" class="hash-link" aria-label="Direct link to Runtime" title="Direct link to Runtime">​</a></h3><ul><li>State is modified in memory during <code>onEvent</code></li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="shutdown">Shutdown<a href="#shutdown" class="hash-link" aria-label="Direct link to Shutdown" title="Direct link to Shutdown">​</a></h3><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">stateStore</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">persist</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><ul><li>The current state is stored before the service stops</li></ul><p>After a restart, the function continues with the restored values.</p><p>No external database setup.
No manual serialization logic.
No additional infrastructure required.</p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="backward-compatibility">Backward Compatibility<a href="#backward-compatibility" class="hash-link" aria-label="Direct link to Backward Compatibility" title="Direct link to Backward Compatibility">​</a></h2><p>Stateful behavior is <strong>opt-in</strong>.</p><p>Existing functions:</p><ul><li>Continue to work unchanged</li><li>Require no migration</li><li>Remain fully stateless unless <code>getStateStore(...)</code> is used</li></ul><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion--feedback">Conclusion &amp; Feedback<a href="#conclusion--feedback" class="hash-link" aria-label="Direct link to Conclusion &amp; Feedback" title="Direct link to Conclusion &amp; Feedback">​</a></h2><p>Functions and state persistence are currently available in <strong>developer preview</strong>, and the API may evolve.</p><p>We are open to feedback from developers, if you try out stateful functions, let us know your thoughts and suggestions.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.98.0]]></title>
            <link>https://streampipes.apache.org/blog/2025/12/15/_release-098</link>
            <guid>https://streampipes.apache.org/blog/2025/12/15/_release-098</guid>
            <pubDate>Mon, 15 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache StreamPipes 0.98.0 is a major step forward in the evolution of the platform, delivering powerful dashboard]]></description>
            <content:encoded><![CDATA[<p>Apache StreamPipes 0.98.0 is a major step forward in the evolution of the platform, delivering <strong>powerful dashboard
enhancements, extended OPC UA capabilities, improved security and authentication</strong>, and a large set of <strong>UX and
architectural refinements</strong>.</p><p>This release focuses on consolidating visualization and dashboard functionality, improving operational transparency, and
modernizing the underlying architecture. Highlights include <strong>dashboard cloning and kiosk mode</strong>, <strong>new aggregation
functions</strong>, <strong>enhanced OPC UA authentication and certificate handling</strong>, <strong>file logging support</strong>, and a <strong>modernized
UI</strong>.</p><p>In total, this release closes around 100 issues across enhancements, bug fixes, and maintenance tasks.</p><p>Read on to discover what’s new in StreamPipes 0.98.0!</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="industrial-connectivity--opc-ua">Industrial Connectivity &amp; OPC-UA<a href="#industrial-connectivity--opc-ua" class="hash-link" aria-label="Direct link to Industrial Connectivity &amp; OPC-UA" title="Direct link to Industrial Connectivity &amp; OPC-UA">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="redesign-of-the-adapter-creation-page">Redesign of the adapter creation page<a href="#redesign-of-the-adapter-creation-page" class="hash-link" aria-label="Direct link to Redesign of the adapter creation page" title="Direct link to Redesign of the adapter creation page">​</a></h3><p>StreamPipes Connect is the central interface to connect a wide variety of industrial protocols with Apache StreamPipes.
In this release, a new overview page simplifies selection of appropriate adapters, taking less space and allowing users
to get a better overview over available connectors.</p><img loading="lazy" src="/img/blog/2025-12-15/adapter-selection.png" alt="Excel export" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="opc-ua-x509-authentication--certificate-management">OPC UA X.509 Authentication &amp; Certificate Management<a href="#opc-ua-x509-authentication--certificate-management" class="hash-link" aria-label="Direct link to OPC UA X.509 Authentication &amp; Certificate Management" title="Direct link to OPC UA X.509 Authentication &amp; Certificate Management">​</a></h3><p>Support for OPC-UA security is greatly enhanced in 0.98.0.
We added a new authentication option that supports <strong>X.509 user authentication</strong>. Users can now directly upload their
X.509 certificates which are securely stored within StreamPipes.</p><p>For encrypted communication, we also added enterprise features to handle OPC-UA certificates.
Until now, certificates had to be managed through environment variables. In the new release, server certificates can be
<strong>centrally managed</strong> from the user interface, simplifying secure deployments.
In case a non-trusted certificate is provided by the OPC-UA server, the certificate is stored in the StreamPipes core
for manual approval. In the settings menu, admins can explicitly trust or reject a given certificate.
The UI view also contains extended certificate information, making it easy to get an overview of all OPC-UA certificates
that are currently used.</p><p>Version 0.98.0 also supports more OPC-UA data types such as better support of <strong>ExtensionObjects</strong>, allowing more
complex OPC-UA data structures to be processed.</p><p>These improvements strengthen StreamPipes as a secure and enterprise-ready IIoT integration platform.</p><img loading="lazy" src="/img/blog/2025-12-15/opc-ua-x509.png" alt="OPC-UA X.509 User Authentication   " class="img_ev3q"><img loading="lazy" src="/img/blog/2025-12-15/opc-ua-certificate.png" alt="Certificate approval" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="other-improvements">Other improvements<a href="#other-improvements" class="hash-link" aria-label="Direct link to Other improvements" title="Direct link to Other improvements">​</a></h3><p>Minor improvements for other adapters include:</p><ul><li>Configurable <strong>wait and lease times</strong> for PLC connectors.</li><li>Improved adapter state handling and recovery options.</li><li>Better schema guessing and duplicate field handling in OPC-UA adapters.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="dashboards--data-explorer">Dashboards &amp; Data Explorer<a href="#dashboards--data-explorer" class="hash-link" aria-label="Direct link to Dashboards &amp; Data Explorer" title="Direct link to Dashboards &amp; Data Explorer">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="harmonized-data-explorer--dashboard-experience">Harmonized Data Explorer &amp; Dashboard Experience<a href="#harmonized-data-explorer--dashboard-experience" class="hash-link" aria-label="Direct link to Harmonized Data Explorer &amp; Dashboard Experience" title="Direct link to Harmonized Data Explorer &amp; Dashboard Experience">​</a></h3><p>The consolidation of visualization tools is finished in 0.98.0.
The <strong>Chart and Dashboard</strong> views have been further harmonized, ensuring consistent configuration and behavior.
The deprecated dashboard has been removed and the new dashboard tool is fully in place. Users can now add any chart
directly to the live dashboard.</p><p>This work lays the foundation for faster innovation and a more consistent visualization experience going forward.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="dashboard-cloning--kiosk-mode">Dashboard Cloning &amp; Kiosk Mode<a href="#dashboard-cloning--kiosk-mode" class="hash-link" aria-label="Direct link to Dashboard Cloning &amp; Kiosk Mode" title="Direct link to Dashboard Cloning &amp; Kiosk Mode">​</a></h3><p>Dashboards have received further several long-awaited improvements:</p><ul><li><strong>Dashboard cloning</strong> allows users to quickly duplicate existing dashboards and reuse configurations.</li><li><strong>Kiosk mode</strong> enables distraction-free, full-screen dashboards—ideal for shop floor displays and control rooms.</li><li>Improved configuration panel now clearly indicate missing or incomplete dashboard and chart configurations.</li></ul><p>These enhancements significantly simplify dashboard reuse and deployment in operational environments.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-visualizations--chart-improvements">New Visualizations &amp; Chart Improvements<a href="#new-visualizations--chart-improvements" class="hash-link" aria-label="Direct link to New Visualizations &amp; Chart Improvements" title="Direct link to New Visualizations &amp; Chart Improvements">​</a></h3><p>Several new visualization and charting capabilities were added:
The <strong>status heatmap visualization</strong> was enhanced with a dedicated color-mapping component, in the <strong>chart appearance
settings</strong>, additional chart-specific configurations were added, including improved heatmap configuration with
customizable min/max values.
To improve usability, icons and descriptions were added to the chart type dropdown, making chart selection more
intuitive.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-aggregation-functions">New Aggregation Functions<a href="#new-aggregation-functions" class="hash-link" aria-label="Direct link to New Aggregation Functions" title="Direct link to New Aggregation Functions">​</a></h3><p>The chart view now supports additional aggregation functions:</p><ul><li><strong>MEDIAN</strong></li><li><strong>SPREAD</strong></li><li><strong>STDDEV</strong></li></ul><p>These functions enable more advanced statistical analysis directly within pipelines and the Chart view.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="excel-export">Excel export<a href="#excel-export" class="hash-link" aria-label="Direct link to Excel export" title="Direct link to Excel export">​</a></h3><p>Besides CSV and JSON, datasets can now be directly exported to a Microsoft Excel format (xlsx). In addition, Excel
templates can be uploaded that can be used to add any company-specific header data to an Excel export.</p><img loading="lazy" src="/img/blog/2025-12-15/excel-export.png" alt="Excel export" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="security--authentication">Security &amp; Authentication<a href="#security--authentication" class="hash-link" aria-label="Direct link to Security &amp; Authentication" title="Direct link to Security &amp; Authentication">​</a></h2><p>Since we aim for enterprise-grade security, we added additional advanced configuration options to integrate Apache
StreamPipes with 3rd-party authentication providers.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="oauth--external-authentication-improvements">OAuth &amp; External Authentication Improvements<a href="#oauth--external-authentication-improvements" class="hash-link" aria-label="Direct link to OAuth &amp; External Authentication Improvements" title="Direct link to OAuth &amp; External Authentication Improvements">​</a></h3><p>Security and identity management received several upgrades.</p><p><strong>External role assignment</strong> is now supported in the OAuth configurations. Besides default roles, users can now be
assigned their roles directly from an external authentication service.
To further increase flexibility, StreamPipes-internal roles and groups can be assigned an <strong>alternate ID</strong>, which can be
used to map external role names to StreamPipes roles and groups.</p><p><strong>OAuth and OpenID configurations</strong> are now loaded at startup time, so that invalid settings are detected earlier upon
startup.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="user-management-enhancements">User Management Enhancements<a href="#user-management-enhancements" class="hash-link" aria-label="Direct link to User Management Enhancements" title="Direct link to User Management Enhancements">​</a></h3><p>User transparency was improved with:</p><ul><li>Tracking and displaying <strong>user creation date</strong> and <strong>last login date</strong> in the user configuration.</li><li>Optional <strong>terms acknowledgment</strong>, allowing organizations to enforce acceptance of usage terms.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="ux--ui-improvements">UX &amp; UI Improvements<a href="#ux--ui-improvements" class="hash-link" aria-label="Direct link to UX &amp; UI Improvements" title="Direct link to UX &amp; UI Improvements">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="modernized-ui-with-material-3">Modernized UI with Material 3<a href="#modernized-ui-with-material-3" class="hash-link" aria-label="Direct link to Modernized UI with Material 3" title="Direct link to Modernized UI with Material 3">​</a></h3><p>The StreamPipes UI has been upgraded to <strong>Material Design 3</strong>, delivering a cleaner, more modern look and feel.
Additional UI improvements include:</p><ul><li>Broader use of design tokens so that theming becomes easier for external developers.</li><li>Panel resize components for flexible layouts.</li><li>Improved breadcrumb navigation in dashboards.</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-becomes-multilingual">StreamPipes becomes multilingual<a href="#streampipes-becomes-multilingual" class="hash-link" aria-label="Direct link to StreamPipes becomes multilingual" title="Direct link to StreamPipes becomes multilingual">​</a></h3><p>Release 0.98.0 starts to add internationalization features to Apache StreamPipes.
While this will be a greater effort spanning multiple releases, this new release lays the groundwork for a completely
localized Apache StreamPipes experience.</p><p>As a first feature, we've localized most parts of the UI to the german language. More languages will follow in the
future - if you are willing to help us translate StreamPipes to more languages, let us know!</p><img loading="lazy" src="/img/blog/2025-12-15/i18n.png" alt="Localized StreamPipes version in German" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="actions-menu">Actions menu<a href="#actions-menu" class="hash-link" aria-label="Direct link to Actions menu" title="Direct link to Actions menu">​</a></h3><p>To ensure a consistent design and a clean, streamlined look and feel, all data tables across StreamPipes now use a
unified actions menu. Instead of displaying multiple action buttons inline, available actions are grouped under a
three-dot menu. Simply hover over the icon to reveal the actions for a given resource, making tables easier to scan
while keeping all functionality readily accessible.</p><img loading="lazy" src="/img/blog/2025-12-15/actions-menu.png" alt="New actions menu" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="developer-experience">Developer experience<a href="#developer-experience" class="hash-link" aria-label="Direct link to Developer experience" title="Direct link to Developer experience">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="migration-to-the-new-data-processor-api">Migration to the New Data Processor API<a href="#migration-to-the-new-data-processor-api" class="hash-link" aria-label="Direct link to Migration to the New Data Processor API" title="Direct link to Migration to the New Data Processor API">​</a></h3><p>The migration to the <strong>new Data Processor API</strong> continues, improving consistency and performance across pipeline
elements.
As part of this effort:</p><ul><li>The legacy <code>StreamPipesDataProcessor</code> and <code>StreamPipesDataSink</code> APIs are now <strong>deprecated</strong>.</li><li>The Flink-based wrapper has also been deprecated and will be removed in a future release.</li></ul><p>Developers are encouraged to migrate to the new APIs to ensure long-term compatibility.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="custom-theming">Custom theming<a href="#custom-theming" class="hash-link" aria-label="Direct link to Custom theming" title="Direct link to Custom theming">​</a></h3><p>With the upgrade of the design system, we changed the way how the StreamPipes UI can be customized with company-specific
color settings.
Settings that can be used for custom theming have been isolated in two files (<code>_custom-variables.scss</code> and <code>_theme-colors.scss</code>).
We encourage developers to investigate the modified prebuild script and the two scss files to generate individual
theming files.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="breaking-change">Breaking Change<a href="#breaking-change" class="hash-link" aria-label="Direct link to Breaking Change" title="Direct link to Breaking Change">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="default-messaging-system-switched-to-nats-">Default Messaging System Switched to NATS 💣<a href="#default-messaging-system-switched-to-nats-" class="hash-link" aria-label="Direct link to Default Messaging System Switched to NATS 💣" title="Direct link to Default Messaging System Switched to NATS 💣">​</a></h3><p>The default <code>docker-compose</code> setup in the <strong>installer directory</strong> now uses <strong>NATS</strong> instead of Apache Kafka for internal
messaging.</p><p>⚠️ <strong>Important:</strong><br>
<!-- -->This change only affects users who are updating from a previous installation.<br>
<!-- -->If your existing StreamPipes instance uses Kafka, continue using the provided <code>docker-compose.kafka.yml</code> file.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="deprecations-️">Deprecations ⚠️<a href="#deprecations-️" class="hash-link" aria-label="Direct link to Deprecations ⚠️" title="Direct link to Deprecations ⚠️">​</a></h2><p>The following components and features are deprecated and scheduled for removal in future versions:</p><ul><li>Deprecated domain property APIs (use semantic type API)</li><li>Nested rule creation functionality</li><li>Legacy configurable data format APIs</li><li>Flink wrapper</li><li>IO-Link IFM adapter</li><li>NetIO adapter</li></ul><p>Users are encouraged to migrate early to avoid disruption in upcoming releases.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-improvements-1">Other improvements<a href="#other-improvements-1" class="hash-link" aria-label="Direct link to Other improvements" title="Direct link to Other improvements">​</a></h2><p>As usual, StreamPipes 0.98.0 includes a variety of minor improvements, bug fixes and dependency updates. Users are
encouraged to update as soon as possible.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2><p>Apache StreamPipes 0.98.0 delivers major improvements in <strong>dashboarding, OPC UA integration, security, and user
experience</strong>, while continuing the architectural cleanup and modernization started in previous releases.</p><p>We would like to thank all contributors and community members who made this release possible.<br>
<!-- -->As always, we welcome your feedback—join the discussion on <a href="https://github.com/apache/streampipes/discussions" target="_blank" rel="noopener noreferrer">GitHub</a>
or the <a href="mailto:dev@streampipes.apache.org" target="_blank" rel="noopener noreferrer">mailing list</a>, and help shape the future of StreamPipes!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From Sensor to Insight - Rapid IIoT Integration for IO-Link Devices with Apache StreamPipes]]></title>
            <link>https://streampipes.apache.org/blog/2025/06/11/oi4-adapter</link>
            <guid>https://streampipes.apache.org/blog/2025/06/11/oi4-adapter</guid>
            <pubDate>Wed, 11 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Integrating industrial sensors into IIoT architectures often poses significant challenges—especially for IT teams unfamiliar with traditional operational technologies (OT).]]></description>
            <content:encoded><![CDATA[<p>Integrating industrial sensors into IIoT architectures often poses significant challenges—especially for IT teams unfamiliar with traditional operational technologies (OT).
The complexity of fieldbus protocols, bespoke integrations, and vendor lock-in can create significant barriers to digital transformation on the shop floor.</p><p>This blog post introduces an easy, scalable approach to bridging this IT/OT divide using <strong>IO-Link</strong>, a standardized protocol for industrial sensors, and <strong>Apache StreamPipes</strong>.
We'll walk you through a complete setup—from connecting IO-Link sensors to visualizing actionable insights—with a focus on a <strong>vibration sensor</strong> and an <strong>IO-Link Master</strong>.</p><p>Whether you're building condition monitoring systems, predictive maintenance pipelines, or just starting with industrial data analytics, this guide will show how StreamPipes makes it simple to move from raw sensor data to intelligent decisions.</p><img loading="lazy" src="/img/blog/2025-06-11/01-IO-Link-Sensor.png" alt="Image of IO-Link master and VVB001 sensor" style="width:50%;display:block;margin:0 auto" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-choose-io-link-sensors">Why Choose IO-Link Sensors?<a href="#why-choose-io-link-sensors" class="hash-link" aria-label="Direct link to Why Choose IO-Link Sensors?" title="Direct link to Why Choose IO-Link Sensors?">​</a></h2><p>IO-Link is an increasingly popular choice in modern industrial environments—and for good reason.
It enables seamless sensor integration without the headaches of proprietary protocols or specialized wiring.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="benefits-of-io-link-for-iiot">Benefits of IO-Link for IIoT<a href="#benefits-of-io-link-for-iiot" class="hash-link" aria-label="Direct link to Benefits of IO-Link for IIoT" title="Direct link to Benefits of IO-Link for IIoT">​</a></h3><p>IO-Link sensors support a wide range of measurements including vibration, temperature, flow, and pressure.
Thanks to IODD (IO Device Description) files, these sensors are interoperable across manufacturers, making configuration fast and reliable.
With simple three-wire cabling and support for up to eight sensors via a single IO-Link master, IO-Link dramatically reduces the complexity of sensor installations.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-io-link">What is IO-Link?<a href="#what-is-io-link" class="hash-link" aria-label="Direct link to What is IO-Link?" title="Direct link to What is IO-Link?">​</a></h3><p>IO-Link is a globally standardized communication protocol (IEC 61131-9) used to connect industrial sensors and actuators.
Unlike traditional analog or proprietary fieldbus protocols, IO-Link communicates digitally and supports detailed sensor diagnostics, parameterization, and status monitoring.
It also integrates easily into IT environments, helping to close the gap between OT data generation and IT-driven analytics.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="oi4-the-key-to-mqtt-based-io-link-integration">OI4: The Key to MQTT-Based IO-Link Integration<a href="#oi4-the-key-to-mqtt-based-io-link-integration" class="hash-link" aria-label="Direct link to OI4: The Key to MQTT-Based IO-Link Integration" title="Direct link to OI4: The Key to MQTT-Based IO-Link Integration">​</a></h3><p>To simplify integration with modern IoT platforms, the <strong>Open Industry 4.0 Alliance (OI4)</strong> provides a standardized interface specification for IO-Link over MQTT.
This includes well-defined JSON structures, topic hierarchies, and security mechanisms such as TLS encryption and authentication.
OI4-compliant devices ensure that sensor data can be consumed and interpreted reliably—no matter the vendor.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="use-case-multi-sensor-condition-monitoring">Use Case: Multi-Sensor Condition Monitoring<a href="#use-case-multi-sensor-condition-monitoring" class="hash-link" aria-label="Direct link to Use Case: Multi-Sensor Condition Monitoring" title="Direct link to Use Case: Multi-Sensor Condition Monitoring">​</a></h2><p>Let’s consider a typical industrial use case: monitoring the condition of electric motors using vibration, temperature, and pressure sensors.
These sensors are connected to a <strong>Hilscher sensorEDGE FIELD</strong> gateway, which publishes all sensor values over MQTT using the OI4 format.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="real-time-insights-with-streampipes">Real-Time Insights with StreamPipes<a href="#real-time-insights-with-streampipes" class="hash-link" aria-label="Direct link to Real-Time Insights with StreamPipes" title="Direct link to Real-Time Insights with StreamPipes">​</a></h3><p>In Apache StreamPipes, this data can be ingested using the OI4 adapter and routed through various processing pipelines.
For instance, you can configure alerts for high vibration (e.g., <code>aPeak &gt; 8.0 m/s²</code>) and high temperature (<code>&gt; 80°C</code>) to detect early signs of mechanical stress or overheating.
Additionally, a rolling average calculation on pressure data helps identify leaks or irregularities.</p><p>This setup not only enables instant notifications via email but also stores the processed data in a timeseries database for long-term trend analysis—reducing the need for manual inspections and improving asset reliability.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="expanding-beyond-vibration">Expanding Beyond Vibration<a href="#expanding-beyond-vibration" class="hash-link" aria-label="Direct link to Expanding Beyond Vibration" title="Direct link to Expanding Beyond Vibration">​</a></h3><p>IO-Link sensors can be used across many other domains in industrial environments. Here are a few examples:</p><table><thead><tr><th>Sensor Type</th><th>Use Case</th><th>StreamPipes Processor(s)</th></tr></thead><tbody><tr><td>Flow</td><td>Detect pipe blockages in real-time</td><td>Threshold Alert, Rate of Change</td></tr><tr><td>Distance</td><td>Monitor silo fill levels</td><td>Moving Average, Anomaly Detection</td></tr><tr><td>Pressure</td><td>Predict pump failure from pressure spikes</td><td>Pattern Matching</td></tr></tbody></table><h2 class="anchor anchorWithStickyNavbar_LWe7" id="integration-overview-from-hardware-to-streampipes">Integration Overview: From Hardware to StreamPipes<a href="#integration-overview-from-hardware-to-streampipes" class="hash-link" aria-label="Direct link to Integration Overview: From Hardware to StreamPipes" title="Direct link to Integration Overview: From Hardware to StreamPipes">​</a></h2><p>Setting up the hardware and data flow is straightforward—even for teams without OT experience.</p><p>After connecting the <strong>VVB001 vibration sensor</strong> to an IO-Link Master, it is automatically detected and begins sending data.
This gateway then publishes sensor readings to a local or remote MQTT broker in a structured JSON format, following the OI4 specification.</p><p>Apache StreamPipes, with its OI4 adapter, subscribes to these MQTT topics, automatically infers the data schema, and prepares the events for downstream processing—completely eliminating the need for manual parsing or custom integration scripts.</p><img loading="lazy" src="/img/blog/2025-06-11/02-Architecture-Overview.png" alt="Architectural overview" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-configuration-guide">StreamPipes Configuration Guide<a href="#streampipes-configuration-guide" class="hash-link" aria-label="Direct link to StreamPipes Configuration Guide" title="Direct link to StreamPipes Configuration Guide">​</a></h2><p>Setting up the data stream in StreamPipes is quick and intuitive. Here's how it works:</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="adding-the-oi4-adapter">Adding the OI4 Adapter<a href="#adding-the-oi4-adapter" class="hash-link" aria-label="Direct link to Adding the OI4 Adapter" title="Direct link to Adding the OI4 Adapter">​</a></h3><p>Start by opening the <strong>Connect</strong> section in the StreamPipes UI. From the list of available adapters, choose the <strong>OI4 MQTT Adapter</strong>.
This adapter is purpose-built for consuming OI4-compliant MQTT streams, so it comes with built-in support for schema detection and mapping.</p><img loading="lazy" src="/img/blog/2025-06-11/03-Connect.png" alt="OI4 adapter in connect" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="configuring-the-adapter">Configuring the Adapter<a href="#configuring-the-adapter" class="hash-link" aria-label="Direct link to Configuring the Adapter" title="Direct link to Configuring the Adapter">​</a></h3><p>In the configuration screen, specify the connection to your MQTT broker. For this use case, the broker runs at <code>tcp://192.168.188.73:1883</code>, with unauthenticated access. Select the desired sensor type (<code>VVB001</code>) and confirm that all available sensors should be included.</p><p>You’ll also need to enter the App ID that identifies the publishing application—in this case, <code>hilscher.com/.../netfield-app-opc-ua-io-link-adapter-1</code>. Once configured, click <em>Next</em>, and StreamPipes will automatically detect the event schema based on the live payloads from the broker.</p><img loading="lazy" src="/img/blog/2025-06-11/04-Configuration-OI4-adapter.png" alt="Configuration of OI4 adapter" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="deep-dive-vvb001-vibration-sensor-data">Deep Dive: VVB001 Vibration Sensor Data<a href="#deep-dive-vvb001-vibration-sensor-data" class="hash-link" aria-label="Direct link to Deep Dive: VVB001 Vibration Sensor Data" title="Direct link to Deep Dive: VVB001 Vibration Sensor Data">​</a></h2><p>The VVB001 sensor is an IO-Link-enabled device capable of measuring several key vibration and temperature metrics.
These metrics are essential for detecting imbalances, misalignments, and early-stage mechanical wear in rotating equipment.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="key-metrics-explained">Key Metrics Explained<a href="#key-metrics-explained" class="hash-link" aria-label="Direct link to Key Metrics Explained" title="Direct link to Key Metrics Explained">​</a></h3><ul><li><strong><code>vRMS</code> (Velocity RMS)</strong>: Indicates the effective vibration velocity over time. Higher values suggest increasing mechanical stress or imbalance.</li><li><strong><code>aPeak</code> (Acceleration Peak)</strong>: Captures the maximum acceleration value in a sampling window. Sudden spikes may point to impacts or misalignment.</li><li><strong><code>aRMS</code> (Acceleration RMS)</strong>: Reflects consistent vibration intensity. Useful for trend analysis and baseline monitoring.</li><li><strong><code>Crest Factor</code></strong>: Calculated as the ratio between peak and RMS acceleration. A rising Crest Factor often signals early-stage bearing damage.</li><li><strong><code>Temperature</code></strong>: Measures the internal temperature of the sensor or its surroundings—crucial for thermal condition monitoring.</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="sample-json-payload">Sample JSON Payload<a href="#sample-json-payload" class="hash-link" aria-label="Direct link to Sample JSON Payload" title="Direct link to Sample JSON Payload">​</a></h3><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"Temperature"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">37.9</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"sensorId"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"000008740649"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"Crest"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"vRms"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"aRms"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"aPeak"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"timestamp"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1600599689805</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithStickyNavbar_LWe7" id="preprocessing-in-streampipes">Preprocessing in StreamPipes<a href="#preprocessing-in-streampipes" class="hash-link" aria-label="Direct link to Preprocessing in StreamPipes" title="Direct link to Preprocessing in StreamPipes">​</a></h3><p>Before this data can be used for analytics or alerting, it must be scaled and cleaned. For example:</p><ul><li><code>vRMS</code> values need to be multiplied by <strong>0.0001</strong>.</li><li><code>aPeak</code>, <code>aRMS</code>, <code>Temperature</code>, and <code>Crest</code> values are scaled by <strong>0.1</strong>.</li></ul><p>The StreamPipes connect functionality van handle this effortlessly.
You can edit the event schema to apply scaling and remove unused fields.</p><img loading="lazy" src="/img/blog/2025-06-11/05-Event-Schema.png" alt="Configuration of OI4 adapter" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="visual-data-exploration">Visual Data Exploration<a href="#visual-data-exploration" class="hash-link" aria-label="Direct link to Visual Data Exploration" title="Direct link to Visual Data Exploration">​</a></h2><p>Once the data is flowing, you can use the <strong>Data Explorer</strong> in StreamPipes to monitor sensor metrics in real-time. Line charts help you visualize trends, spikes, and anomalies in vibration and temperature levels.</p><p>Whether you’re fine-tuning processing logic or monitoring asset health, StreamPipes visualizations make it easy to detect anomalies and trends in real time.</p><img loading="lazy" src="/img/blog/2025-06-11/06-Linechart.png" alt="Configuration of OI4 adapter" style="width:70%;display:block;margin:0 auto" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="alerting-with-pipelines">Alerting with Pipelines<a href="#alerting-with-pipelines" class="hash-link" aria-label="Direct link to Alerting with Pipelines" title="Direct link to Alerting with Pipelines">​</a></h2><p>With pipelines, you can define rule-based logic to trigger alerts based on sensor values. For example, if the <strong>Crest Factor</strong> exceeds a defined threshold, you can send an email notification to maintenance staff.</p><p>Pipelines are extensible—you can integrate third party tools, store data in databases, or implement predictive analytics using machine learning models.</p><img loading="lazy" src="/img/blog/2025-06-11/07-Notification-Pipeline.png" alt="Configuration of OI4 adapter" style="width:50%;display:block;margin:0 auto" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2><p>Apache StreamPipes and IO-Link together offer a highly accessible yet powerful IIoT solution.
From a simple dashboard setup to complex, multi-sensor condition monitoring pipelines, this integration enables IT teams to drive real-time insights from machine data—without needing a background in industrial automation.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Secure OPC-UA Integration with Apache StreamPipes: A Comprehensive Guide]]></title>
            <link>https://streampipes.apache.org/blog/2025/05/20/opc-ua-certificates</link>
            <guid>https://streampipes.apache.org/blog/2025/05/20/opc-ua-certificates</guid>
            <pubDate>Tue, 20 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[With the release of Apache StreamPipes 0.97.0, the OPC UA adapter now supports encrypted communication using]]></description>
            <content:encoded><![CDATA[<p>With the release of Apache StreamPipes 0.97.0, the OPC UA adapter now supports encrypted communication using
certificates, enhancing security for Industrial IoT applications. This guide walks you through generating certificates,
configuring them in StreamPipes, and setting up your OPC UA server for secure communication.</p><h1>Introduction</h1><p>While an unencrypted security policy is the way most users try when they start testing StreamPipes for their first time,
production-grade scenarios typically require encrypted communication.</p><p>In case you are already using Apache StreamPipes, you might have noticed that the OPC UA adapter now supports encrypted
security policies:</p><img loading="lazy" src="/img/blog/2025-05-20/opc-ua-configuration.png" alt="OPC-UA adapter configuration" class="img_ev3q"><p>In this guide, I'll show how to set up a secure connection between your OPC UA server and Apache StreamPipes. This guide
is intended to be a step-by-step-guide starting from certificate generation to the configuration of the OPC UA adapter
in StreamPipes.</p><p>I'll show a working example on a local installation using Eclipse Milo as the OPC UA server. The same steps can be
applied to production systems by integrating certificates into the volume of the extension service. There are other
ways to configure OPC-UA secure connections, but this guide will focus on a complete approach using self-signed
certificates for beginners.</p><h1>Prerequisites</h1><ul><li>Apache StreamPipes 0.97.0 or newer</li><li>An OPC-UA server supporting security policies <code>Sign</code> and <code>Sign &amp; Encrypt</code></li><li>OpenSSL installed on your system</li></ul><h1>Generate client certificates</h1><p>When creating a new OPC-UA adapter in Apache StreamPipes, the extension service where the adapter is running in serves
as the client.
First, we need to create a client certificate for the client. In this example, we'll create a self-signed certificate.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">default_bits       </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2048</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">prompt             </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> no</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">default_md         </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> sha256</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">req_extensions     </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> req_ext</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">x509_extensions    </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> v3_ca</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">distinguished_name </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> dn</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">dn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">CN </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> stream-pipes-client</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">req_ext</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">subjectAltName </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> @alt_names</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">keyUsage </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">extendedKeyUsage </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> serverAuth, clientAuth</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">v3_ca</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">subjectKeyIdentifier </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">hash</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">basicConstraints </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> CA:false</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">subjectAltName </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> @alt_names</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">keyUsage </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">extendedKeyUsage </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> serverAuth, clientAuth</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">alt_names</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">URI.1 </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> urn:org:apache:streampipes:opcua:client</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>When using a self-signed certificate, it is requried to to provide the CA:false flag under basicConstraints.
In addition, note the subject alternative name that later needs to be matched by the application URI of the OPC-UA
client.</p><p>The next step is to generate the certificate and import it into a PKCS12 keystore. The keystore is used to store the key
pair we are generating in the first step.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">openssl req -x509 -nodes -days </span><span class="token number" style="color:rgb(247, 140, 108)">365</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -newkey rsa:2048 </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -keyout client.key </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -out client.crt </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -config cert.conf </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> openssl pkcs12 -export </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -in client.crt </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -inkey client.key </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -out client.p12 </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  -name streampipes-client</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>When I was asked for a password, I chose <code>streampipes</code>. You can choose any password you like, but make sure to remember
it, as
we will need it in the next step.</p><p>Check that the keystore lists the correct key by executing:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">keytool -list -v -storetype PKCS12 -keystore client.p12</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>You'll see the key you've just generated.</p><h1>Configure StreamPipes to support encrypted connections</h1><p>To enable the OPC UA adapter to use the generated client certificate, we need to provide a few environment variables to
StreamPipes.</p><p>Here is a list of all environment variables that are available:</p><ul><li>SP_OPCUA_SECURITY_DIR (default: /streampipes-security/opcua): This is the directory where the keystore and
trusted/rejected server certificates are stored.</li><li>SP_OPCUA_KEYSTORE_FILE (default: keystore.pfx): This is the keystore file that contains the client certificate.</li><li>SP_OPCUA_KEYSTORE_PASSWORD (default: password): The password for the keystore file.</li><li>SP_OPCUA_KEYSTORE_TYPE (default: PKCS12): The type of the keystore file.</li><li>SP_OPCUA_KEYSTORE_ALIAS (default: apache-streampipes): The alias of the client certificate in the keystore.</li><li>SP_OPCUA_APPLICATION_URI (default: urn:org:apache:streampipes:opcua:client): The application URI of the client
certificate.</li></ul><p>We could have made the previous configuration easier by reusing some of the defaults. For learning purposes, we used
some other names for the alias and keystore filename.</p><p>In my setup, I've started a local StreamPipes instance. When using Docker, you can add the environment variables to the
extensions service (e.g., extensions-all-iiot). In my local instance, I just add the emnvironment variables to my IDE
settings.</p><p>I add the following variables:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token assign-left variable" style="color:rgb(191, 199, 213)">SP_OPCUA_SECURITY_DIR</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">/home/user/streampipes-security/opcua</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">SP_OPCUA_KEYSTORE_FILE</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">client.p12</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">SP_OPCUA_KEYSTORE_PASSWORD</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">streampipes</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">SP_OPCUA_KEYSTORE_ALIAS</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">streampipes-client</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h1>Connecting to an OPC-UA server</h1><p>For this demo, I'm using the Eclipse Milo OPC UA server. You can download it from <a href="https://github.com/digitalpetri/opc-ua-demo-server" target="_blank" rel="noopener noreferrer">here</a>.
Once the server is running, you can connect to it using the following URL:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">opc.tcp://localhost:62541/milo</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Now it's time to switch to StreamPipes!</p><p>Go to <strong>Connect</strong> -&gt; <strong>New adapter</strong> -&gt; <strong>OPC UA</strong> and enter the following configuration:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">Pull interval </span><span class="token number" style="color:rgb(247, 140, 108)">1000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Incomplete Events Ignore</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Security Mode Sign </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;</span><span class="token plain"> Encrypt</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Security Policy Basic256Sha256</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">URL opc.tcp://localhost:62541/milo</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Defocus the URL input field and wait for the OPC-UA server to connect. After a few seconds, you should see an error message appearing:</p><img loading="lazy" src="/img/blog/2025-05-20/opcua-connection-error.png" alt="OPC-UA adapter connection error" class="img_ev3q"><p>This is expected, as we haven't added the client certificate to the trusted certificates of the OPC-UA server yet.
So we have to let Milo know that the client certificate can be trusted. In my local setup, I need to move the client certificate from the <code>rejected</code> to the <code>trusted/certs</code> folder as seen below:</p><img loading="lazy" src="/img/blog/2025-05-20/opcua-server-rejected.png" alt="OPC-UA adapter rejected client certificate" class="img_ev3q"><p>So let's try again by clicking <code>Reload</code> in the <code>Available Nodes</code> section of the adapter configuration page.
We'll get another error saying that the server certificate is not trusted.
This is again expected, as we haven't added the server certificate to the trusted certificates of the OPC-UA client yet.   </p><p>To do that, we can have a look at the folder structure under <code>SP_OPC_UA_SECURITY_DIR</code>:</p><img loading="lazy" src="/img/blog/2025-05-20/opcua-security-dir.png" alt="OPC-UA security directory" class="img_ev3q"><p>Several new folders have been created by the Apache StreamPipes OPC-UA client.
The <code>trusted</code> folder contains the trusted server certificates, while the <code>rejected</code> folder contains the rejected server certificates.
We'll move the server certificate from the <code>rejected</code> folder to the <code>trusted/certs</code> folder.</p><p>No we'll try again - and this time, we should see the available nodes in the adapter configuration page:</p><img loading="lazy" src="/img/blog/2025-05-20/opcua-available-nodes.png" alt="OPC-UA adapter available nodes" class="img_ev3q"><p>You'll see the beautiful tree view where you can navigate through all OPC-UA nodes.</p><p>Now you can select the nodes you want to use in your adapter.</p><p>That's it! You've successfully configured the OPC-UA adapter to use encrypted communication with self-signed certificates.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Usage-Based Maintenance with Apache StreamPipes]]></title>
            <link>https://streampipes.apache.org/blog/2025/04/30/usage-based-maintanence</link>
            <guid>https://streampipes.apache.org/blog/2025/04/30/usage-based-maintanence</guid>
            <pubDate>Wed, 30 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[In many manufacturing settings, maintenance is still scheduled at fixed time intervals — often based on past experience rather than actual machine usage.]]></description>
            <content:encoded><![CDATA[<p>In many manufacturing settings, maintenance is still scheduled at fixed time intervals — often based on past experience rather than actual machine usage.
This approach can lead to unnecessary servicing or, worse, unexpected breakdowns.
A common limitation is that many machines, especially older ones, offer only minimal sensor data, making advanced maintenance strategies seem out of reach.</p><p>However, with Apache StreamPipes, even limited data — such as a simple boolean signal indicating activity — can be leveraged to implement usage-based maintenance.
In this blog post, we demonstrate how this is achieved using a real-world example: a packaging machine that processes goods at high throughput.
You'll learn how to count machine operations, store event data, visualize usage over time, and trigger notifications when maintenance is due — all with just a few clicks in StreamPipes.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-scenario-packaging-machine-monitoring">The Scenario: Packaging Machine Monitoring<a href="#the-scenario-packaging-machine-monitoring" class="hash-link" aria-label="Direct link to The Scenario: Packaging Machine Monitoring" title="Direct link to The Scenario: Packaging Machine Monitoring">​</a></h2><p>Let’s consider a packaging machine that wraps goods into individual packages.
The wear and tear on this machine is directly related to the number of items processed.
However, due to the machine’s age, only minimal data is available.</p><p>Currently:</p><ul><li>Maintenance occurs at fixed intervals.</li><li>These intervals were determined on the basis of the technicians' experience.</li><li>There is suspicion that maintenance is done too frequently, leading to unnecessary costs.</li></ul><p>With Apache StreamPipes, we’ll build a pipeline that:</p><ul><li>Counts packaging operations in real time.</li><li>Stores data for analysis and visualization.</li><li>Sends notifications once a maintenance threshold is reached.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-data-a-simple-boolean-signal">The Data: A Simple Boolean Signal<a href="#the-data-a-simple-boolean-signal" class="hash-link" aria-label="Direct link to The Data: A Simple Boolean Signal" title="Direct link to The Data: A Simple Boolean Signal">​</a></h2><p>The machine provides a boolean flag — <code>active</code> — which is <code>true</code> when a packaging operation occurs.
This flag is streamed using an Apache StreamPipes S7 adapter. The stream also includes a few additional process parameters:</p><table><thead><tr><th>Timestamp</th><th>active</th><th>...</th></tr></thead><tbody><tr><td>1719897720887</td><td>false</td><td>...</td></tr><tr><td>1719897721952</td><td>true</td><td>...</td></tr><tr><td>1719897722952</td><td>true</td><td>...</td></tr><tr><td>...</td><td>...</td><td>...</td></tr></tbody></table><h2 class="anchor anchorWithStickyNavbar_LWe7" id="part-1-absolute-counter-with-notification">Part 1: Absolute Counter with Notification<a href="#part-1-absolute-counter-with-notification" class="hash-link" aria-label="Direct link to Part 1: Absolute Counter with Notification" title="Direct link to Part 1: Absolute Counter with Notification">​</a></h2><p>We’ll begin by building a pipeline that counts how often the machine packages a product and sends an email alert when a predefined threshold is reached.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-overview">Pipeline Overview<a href="#pipeline-overview" class="hash-link" aria-label="Direct link to Pipeline Overview" title="Direct link to Pipeline Overview">​</a></h3><img loading="lazy" src="/img/blog/2025-04-30/maintenance-pipeline-one.png" alt="Counting Operations Pipeline" class="img_ev3q"><p><em>A simple StreamPipes pipeline for monitoring the parts produced at the machine</em></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-by-step-guide">Step-by-Step Guide<a href="#step-by-step-guide" class="hash-link" aria-label="Direct link to Step-by-Step Guide" title="Direct link to Step-by-Step Guide">​</a></h3><ol><li><p><strong>Add the Data Source</strong></p><ul><li>Drag the data stream of the packaging machine into the pipeline editor.</li></ul></li><li><p><strong>Insert the <code>Boolean Counter</code> Processor</strong></p><ul><li>Monitors a boolean field and counts transitions (e.g., <code>false → true</code>).</li><li><strong>Configuration:</strong><ul><li><em>Boolean Field:</em> <code>active</code></li><li><em>Flank Parameter:</em> <code>FALSE → TRUE</code></li></ul></li></ul><blockquote><p>The processor emits a new event each time the machine packages an item, incrementing a <code>counter</code> value.</p></blockquote></li><li><p><strong>Persist the Count</strong></p><ul><li>Add the <strong>Data Lake</strong> sink to store these events for visualization.</li></ul></li><li><p><strong>Add a Threshold Alert</strong></p><ul><li>Insert the <code>Numerical Filter</code> processor.<ul><li><em>Field:</em> <code>counter</code></li><li><em>Filter Operation:</em> <code>&gt;</code></li><li><em>Threshold:</em> <code>100000</code></li></ul></li><li>Connect this to the <strong>Email Notification</strong> sink.<ul><li>Configure recipient, subject, and set the <strong>Silent Period</strong> to avoid spamming the team.</li></ul></li></ul></li><li><p><strong>Visualize in Dashboard</strong></p><ul><li>Start the pipeline.</li><li>In the dashboard, add an <strong>Indicator Widget</strong> displaying the <code>counter</code> value.</li></ul></li></ol><img loading="lazy" src="/img/blog/2025-04-30/maintenance-dashboard.png" alt="Displaying the counting value" class="img_ev3q"><p><em>The live dashboard with an indicator chart showing the current number of goods produced</em></p><p>This setup gives you a live counter of how many products were packaged and notifies the maintenance team when attention is needed.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="part-2-aggregated-counting-over-time">Part 2: Aggregated Counting Over Time<a href="#part-2-aggregated-counting-over-time" class="hash-link" aria-label="Direct link to Part 2: Aggregated Counting Over Time" title="Direct link to Part 2: Aggregated Counting Over Time">​</a></h2><p>While a cumulative counter is useful, often it's more insightful to understand how usage varies over time — for example, how many items are processed each day.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-time-aggregated-approach">A Time-Aggregated Approach<a href="#a-time-aggregated-approach" class="hash-link" aria-label="Direct link to A Time-Aggregated Approach" title="Direct link to A Time-Aggregated Approach">​</a></h3><p>Instead of a total counter, we’ll now generate a single event for each packaging operation and then use the <strong>Data Explorer</strong> to visualize activity per hour or per day.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="alternative-pipeline-using-signal-edge-filter">Alternative Pipeline Using Signal Edge Filter<a href="#alternative-pipeline-using-signal-edge-filter" class="hash-link" aria-label="Direct link to Alternative Pipeline Using Signal Edge Filter" title="Direct link to Alternative Pipeline Using Signal Edge Filter">​</a></h3><img loading="lazy" src="/img/blog/2025-04-30/maintenance-pipeline-two.png" alt="Count per Time Pipeline" class="img_ev3q"><p><em>Pipeline to recognize when a part is being processed</em></p><p><strong>Step-by-Step:</strong></p><ol><li><p>Replace the <code>Boolean Counter</code> with a <strong>Signal Edge Filter</strong> processor.</p><ul><li>Filters events based on signal transitions.</li><li><strong>Configuration:</strong><ul><li><em>Boolean Field:</em> <code>active</code></li><li><em>Signal Edge:</em> <code>FALSE → TRUE</code></li><li><em>Delay:</em> <code>0</code></li><li><em>Output Event Selection:</em> <code>First</code></li></ul></li></ul></li><li><p>Store the filtered stream in the <strong>Data Lake</strong> sink. </p></li></ol><p>This gives one clean event per packaging operation — ideal for aggregation.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="visualization-in-the-data-explorer">Visualization in the Data Explorer<a href="#visualization-in-the-data-explorer" class="hash-link" aria-label="Direct link to Visualization in the Data Explorer" title="Direct link to Visualization in the Data Explorer">​</a></h2><p>Now that we have one event per packaging action, we can analyze the data over time in the Data Explorer.</p><ol><li><strong>Open the Data Explorer</strong></li><li><strong>Table View Configuration:</strong><ul><li><em>Data Source:</em> Select the stream used in the pipeline.</li><li><em>Aggregation:</em> Group by <code>Hour</code> or <code>Day</code>.</li><li><em>Field Aggregation:</em> Use <code>count</code> on any field to count the number of events.</li></ul></li></ol><img loading="lazy" src="/img/blog/2025-04-30/maintenance-count-aggregation-table.png" alt="Count per Time in Data Explorer" class="img_ev3q"><ol start="3"><li><strong>Bar Chart Visualization:</strong><ul><li>Switch to a <strong>Time-Series Chart</strong>.</li><li>Select the counted field.</li><li>Choose <code>bar</code> from the chart type dropdown.</li></ul></li></ol><img loading="lazy" src="/img/blog/2025-04-30/maintenance-count-aggregation-barchart.png" alt="Count per Time in Data Explorer Bar Chart" class="img_ev3q"><p>You now have a clear, time-based view of machine usage. This helps spot trends, detect unusual downtimes, and better plan maintenance.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2><p>In this post, we’ve shown how even limited sensor data — like a simple boolean signal — can be used to build powerful maintenance logic using Apache StreamPipes. With just a few clicks, you can:</p><ul><li>Count operations and trigger maintenance alerts</li><li>Store and visualize historical data</li><li>Understand machine usage over time with time-based aggregations</li></ul><p>By replacing static maintenance intervals with actual usage insights, you can reduce unnecessary work and improve efficiency — all without needing to retrofit expensive new sensors.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bringing LLM Power to Every Pipeline – The Multi-Model Prompt Processor]]></title>
            <link>https://streampipes.apache.org/blog/2025/04/28/prompt-processor</link>
            <guid>https://streampipes.apache.org/blog/2025/04/28/prompt-processor</guid>
            <pubDate>Mon, 28 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Need a quick sentiment check, a rolling summary, or a safety rule that’s just a bit too fuzzy for SQL?]]></description>
            <content:encoded><![CDATA[<img loading="lazy" src="/img/blog/2025-04-28/prompt-processor-pipeline.png" alt="Prompt Processor in Pipeline" class="img_ev3q"><p>Need a quick sentiment check, a rolling summary, or a safety rule that’s just a bit too fuzzy for SQL?<br>
<!-- -->With the <strong>Multi-Model Prompt Processor</strong> you can drop the full might of OpenAI, Anthropic, or your own Llama into any
Apache StreamPipes pipeline—no extra code required.</p><p>Below you’ll find:</p><ul><li>A quick tour of the options</li><li>Five every day use-cases</li><li>A hands-on GIF tutorial</li><li>Tips on writing prompts that return <strong>only</strong> what you need</li><li>A full list of the models that work out of the box</li></ul><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-does-the-processor-do">What does the processor do?<a href="#what-does-the-processor-do" class="hash-link" aria-label="Direct link to What does the processor do?" title="Direct link to What does the processor do?">​</a></h2><table><thead><tr><th>Option</th><th>What it controls</th></tr></thead><tbody><tr><td><strong>Model provider / name</strong></td><td>Choose any OpenAI or Anthropic model, or point to a Llama on Ollama.</td></tr><tr><td><strong>Temperature</strong></td><td>0 = repeatable answers, 1 = creative answers.</td></tr><tr><td><strong>History strategy</strong></td><td><em>Stateless</em>, <em>Windowed (N turns)</em>, or <em>Full</em> history.</td></tr><tr><td><strong>Window size</strong></td><td>How many past turns to keep in <em>Windowed</em> mode.</td></tr><tr><td><strong>Multiple input fields</strong></td><td>Combine several event attributes into one user message.</td></tr></tbody></table><p>The processor sends your prompt + current event data to the model, grabs the reply, and writes it to a new field
<code>llmResponse</code>; ideal when the answer must flow straight into the next processor.</p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="five-ways-to-use-it">Five ways to use it<a href="#five-ways-to-use-it" class="hash-link" aria-label="Direct link to Five ways to use it" title="Direct link to Five ways to use it">​</a></h2><table><thead><tr><th>#</th><th>Scenario</th><th>Prompt idea (few-shot style)</th><th>History</th></tr></thead><tbody><tr><td>1</td><td><strong>Data-quality gate</strong> – flag numbers &gt; 15</td><td>Return WARNING if value &gt; 15 else OK. Example → 12 → OK, 18 → WARNING.</td><td><strong>Stateless</strong></td></tr><tr><td>2</td><td><strong>Rolling minimum</strong> of a sensor</td><td>Pass previousMin + current. “Return the smallest of the two numbers only.”</td><td><strong>Windowed (1)</strong></td></tr><tr><td>3</td><td><strong>Five-tweet sentiment</strong></td><td>Concatenate last 5 tweets. “Return POSITIVE / NEGATIVE / NEUTRAL only.”</td><td><strong>Windowed (5)</strong></td></tr><tr><td>4</td><td><strong>Chat summariser</strong> for support tickets</td><td>System prompt: “Write one-line summary of the whole conversation.”</td><td><strong>Full</strong></td></tr><tr><td>5</td><td><strong>Dynamic threshold helper</strong></td><td>Feed last 10 load values. “Return max(values)*1.1 rounded 0 decimals.”</td><td><strong>Windowed (10)</strong></td></tr></tbody></table><p><em>(Replace the <code>$placeholders$</code> with the actual stream attributes in the mapping dialog.)</em></p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="tutorial--from-stream-to-json-warning">Tutorial – from stream to JSON warning<a href="#tutorial--from-stream-to-json-warning" class="hash-link" aria-label="Direct link to Tutorial – from stream to JSON warning" title="Direct link to Tutorial – from stream to JSON warning">​</a></h2><p>Below is a short clip showing the processor in action in a temperature pipeline.<br>
<!-- -->The prompt forces the model to output a two-field JSON—perfect for machine parsing.</p><img loading="lazy" src="/img/blog/2025-04-28/prompt_processor_demo.gif" alt="Animated demo of the prompt processor" class="img_ev3q"><p><strong>Model:</strong> <code>claude-3-5-sonnet-20241022</code><br>
<strong>Prompt Used:</strong></p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">You are an assistant that ALWAYS replies with a single JSON object</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">containing two string fields: "status" and "message".</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Rules</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1. If the temperature is strictly greater than 45 °C:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">     • "status" must be "WARNING"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">     • "message" must explain that the temperature is above the safe limit</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">2. Otherwise:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">     • "status" must be "OK"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">     • "message" must note that the temperature is within the safe range</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">3. Do not output anything except the JSON object.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">### Examples</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Temperature: 50</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "status": "WARNING",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "message": "Temperature exceeds the 45 °C threshold"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Temperature: 30</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "status": "OK",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "message": "Temperature is within the safe range"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Temperature: 45</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "status": "OK",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "message": "Temperature is within the safe range"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Temperature: 60</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">{</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "status": "WARNING",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  "message": "Temperature exceeds the 45 °C threshold"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The model now returns either:</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"WARNING"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"message"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"Temperature exceeds the 45 °C threshold"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>or</p><div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"status"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"OK"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"message"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"Temperature is within the safe range"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Nothing else—exactly what we want for downstream processors.</p><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="prompt-writing-tips-for-event-streams">Prompt writing tips for event streams<a href="#prompt-writing-tips-for-event-streams" class="hash-link" aria-label="Direct link to Prompt writing tips for event streams" title="Direct link to Prompt writing tips for event streams">​</a></h2><ol><li><strong>State the output format first</strong>: “Reply with OK or WARNING only.”</li><li>Give <strong>one or two concrete examples</strong> – LLMs copy patterns.</li><li><strong>End with a clear cue</strong>: “Answer:” or “Output:”.</li><li>Keep <em>temperature ≤ 0.3</em> when strict structure matters.</li><li>Short replies reduce context size in <em>Windowed</em> / <em>Full</em> modes.</li></ol><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="supported-models">Supported models<a href="#supported-models" class="hash-link" aria-label="Direct link to Supported models" title="Direct link to Supported models">​</a></h2><details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary><strong>Anthropic models</strong></summary><div><div class="collapsibleContent_i85q"><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-3-7-sonnet-20250219</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-3-5-sonnet-20241022</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-3-5-haiku-20241022</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-3-5-sonnet-20240620</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-3-opus-20240229</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-3-sonnet-20240229</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-3-haiku-20240307</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-2.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">claude-2.0</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details><details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary><strong>OpenAI models</strong></summary><div><div class="collapsibleContent_i85q"><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">gpt-3.5-turbo              gpt-3.5-turbo-1106     gpt-3.5-turbo-0125</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">gpt-3.5-turbo-16k          gpt-4                  gpt-4-0613</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">gpt-4-turbo-preview        gpt-4-1106-preview     gpt-4-0125-preview</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">gpt-4-turbo                gpt-4-turbo-2024-04-09 gpt-4-32k</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">gpt-4-32k-0613             gpt-4o                 gpt-4o-2024-05-13</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">gpt-4o-2024-08-06          gpt-4o-2024-11-20      gpt-4o-mini</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">gpt-4o-mini-2024-07-18     o1                     o1-mini</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">o1-2024-12-17              o1-mini-2024-09-12     o1-preview</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">o1-preview-2024-09-12      o3-mini-2025-01-31</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div></div></div></details><details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary><strong>Llama suggestions (Ollama)</strong></summary><div><div class="collapsibleContent_i85q"><p><code>llama3</code>, <code>llama3:8b</code>, <code>llama2</code>, <code>mistral-7b-instruct</code>, or any custom model you have pulled.</p></div></div></details><hr><h2 class="anchor anchorWithStickyNavbar_LWe7" id="final-thoughts">Final thoughts<a href="#final-thoughts" class="hash-link" aria-label="Direct link to Final thoughts" title="Direct link to Final thoughts">​</a></h2><p>Whether you need a lightweight rule engine, live summaries, or just a smarter filter, the Multi-Model Prompt Processor
drops straight into your pipeline and starts working within minutes.</p><p>Give it a try, and let us know what you build!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Use the JavaScript Evaluator Processor]]></title>
            <link>https://streampipes.apache.org/blog/2025/04/09/javascript-processor</link>
            <guid>https://streampipes.apache.org/blog/2025/04/09/javascript-processor</guid>
            <pubDate>Wed, 09 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Have a use case where none of the existing processors fit?]]></description>
            <content:encoded><![CDATA[<p><strong>Have a use case where none of the existing processors fit?</strong><br>
<!-- -->Don’t worry—we’ve got just the thing for you.</p><p>The <strong>JavaScript Evaluator Processor</strong> in Apache StreamPipes allows you to define custom event logic with just a few lines of JavaScript. Whether you want to modify values, filter events, or even add stateful logic, this processor empowers you to do just that—without writing a full processing element in Java.</p><p>Let’s take a closer look at how it works, what the configuration options are, and how you can use it in three different ways.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-javascript-evaluator">What is the JavaScript Evaluator?<a href="#what-is-the-javascript-evaluator" class="hash-link" aria-label="Direct link to What is the JavaScript Evaluator?" title="Direct link to What is the JavaScript Evaluator?">​</a></h2><p>Sometimes you need to apply custom logic to your data stream. Maybe it's a quick transformation or a complex filter that isn’t supported out of the box. The JavaScript Evaluator Processor is designed exactly for these cases.</p><p>With a simple JavaScript function, you can:</p><ul><li>Modify existing fields</li><li>Add new fields</li><li>Filter out unwanted events</li><li>Maintain state across events</li></ul><p>All you need is a little coding and a bit of creativity.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="configuring-the-javascript-processor">Configuring the JavaScript Processor<a href="#configuring-the-javascript-processor" class="hash-link" aria-label="Direct link to Configuring the JavaScript Processor" title="Direct link to Configuring the JavaScript Processor">​</a></h2><p>When adding the JavaScript Evaluator to your pipeline, you’ll notice two key configuration sections:</p><img loading="lazy" src="/img/blog/2025-04-09/javascript-processor-pipeline.png" alt="Javascript Processor in Pipeline" class="img_ev3q"><ol><li><strong>The JavaScript Function</strong><br>This function is triggered once for <em>each incoming event</em>.</li></ol><img loading="lazy" src="/img/blog/2025-04-09/javascript-processor-code.png" alt="Javascript Processor Code Editor" class="img_ev3q"><ol start="2"><li><strong>The Output Schema</strong><br>This defines the structure of your transformed events. It’s important to ensure that the output schema matches what your function returns—otherwise, downstream processors might not be able to validate the events correctly.</li></ol><img loading="lazy" src="/img/blog/2025-04-09/javascript-processor-event-schema.png" alt="Javascript Processor Event Schema Editor" class="img_ev3q"><p>Let’s explore some examples that show different ways to apply custom logic to your event streams using JavaScript.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="example-1-stateless-event-transformation">Example 1: Stateless Event Transformation<a href="#example-1-stateless-event-transformation" class="hash-link" aria-label="Direct link to Example 1: Stateless Event Transformation" title="Direct link to Example 1: Stateless Event Transformation">​</a></h2><p>The simplest use case is when you want to modify values in an event.</p><p><strong>Use case:</strong> You want to halve the <code>temperature</code> value of each incoming event.</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">temperature</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">temperature</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>That’s it! Each event passes through this function, gets modified, and is sent on its way. No extra setup needed.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="example-2-custom-event-filtering">Example 2: Custom Event Filtering<a href="#example-2-custom-event-filtering" class="hash-link" aria-label="Direct link to Example 2: Custom Event Filtering" title="Direct link to Example 2: Custom Event Filtering">​</a></h2><p>You don’t always want to forward every event. The JavaScript Evaluator lets you return <code>null</code> (or just omit <code>return</code>) to drop an event.</p><p><strong>Use case:</strong> Only forward events where the <code>temperature</code> is between 50 and 100.</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">temperature</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">50</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">temperature</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">100</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>With this setup, only "valid" events get through. All others are silently ignored. Perfect for quick, custom filtering logic.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="example-3-stateful-logic">Example 3: Stateful Logic<a href="#example-3-stateful-logic" class="hash-link" aria-label="Direct link to Example 3: Stateful Logic" title="Direct link to Example 3: Stateful Logic">​</a></h2><p>Need to track information across multiple events? You can wrap your function in an <strong>Immediately Invoked Function Expression (IIFE)</strong> to create persistent variables.</p><p><strong>Use case:</strong> Count how many events have passed through the processor and append that number to each event.</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> count </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">process</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        count </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">count</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> count</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This small trick makes it easy to introduce state without needing any external dependencies or full-blown processor development. You can track counts, store intermediate values, or even implement basic alerting.
Just make sure that any new properties you add to the event, like <code>count</code> in the example, are also included in the output event schema during processor configuration, otherwise the pipeline may fail validation.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="wrap-up">Wrap-Up<a href="#wrap-up" class="hash-link" aria-label="Direct link to Wrap-Up" title="Direct link to Wrap-Up">​</a></h2><p>The JavaScript Evaluator is one of the most flexible processors in StreamPipes. Whether you're a beginner or a power user, it lets you:</p><p>✅ Write custom transformations<br>
<!-- -->✅ Implement simple filters<br>
<!-- -->✅ Track state between events<br>
<!-- -->✅ Prototype complex logic—without deploying a new microservice</p><p>So, next time you think <em>"I wish there was a processor that could..."</em>, just try the JavaScript Evaluator. Chances are, it can.</p><p>Got a cool use case using this processor? Let us know or share it with the community—we’d love to see what you’re building with Apache StreamPipes!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Explore StreamPipes with Data Simulators!]]></title>
            <link>https://streampipes.apache.org/blog/2025/03/25/file-stream-adapter</link>
            <guid>https://streampipes.apache.org/blog/2025/03/25/file-stream-adapter</guid>
            <pubDate>Tue, 25 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Introduction]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h3><p>Are you excited to explore Apache StreamPipes but find yourself without any sensors to play with?
Or maybe you're looking to validate StreamPipes for your use case and kick off a Proof of Concept (PoC) but the hardware is not yet available?
No worries—the <strong>File Stream Adapter</strong> is here to save the day!</p><p>With the File Stream Adapter, you can upload a file containing sensor data in various formats (JSON, CSV, XML) and replay this data, giving you a hands-on way to dive into StreamPipes.
It's not meant for production use, but it's perfect for experimenting with StreamPipes using your own data.</p><p>This blog post will take you on a exciting journey through configuring the <strong>File Stream Adapter</strong> and using it to simulate sensor data streams.</p><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_S0QG"><p>The adapter supports any type of data as long as it contains a <strong>valid timestamp</strong> in the form of a <strong>Unix timestamp in milliseconds</strong>.</p></div></div><h3 class="anchor anchorWithStickyNavbar_LWe7" id="adapter-configuration">Adapter Configuration<a href="#adapter-configuration" class="hash-link" aria-label="Direct link to Adapter Configuration" title="Direct link to Adapter Configuration">​</a></h3><p>Let's break down the configuration options for the <strong>File Stream Adapter:</strong></p><img loading="lazy" src="/img/blog/2025-03-25/adapter_configuration.png" alt="Adapter Configuration" class="img_ev3q"><h4 class="anchor anchorWithStickyNavbar_LWe7" id="configuration-options-explained">Configuration Options Explained<a href="#configuration-options-explained" class="hash-link" aria-label="Direct link to Configuration Options Explained" title="Direct link to Configuration Options Explained">​</a></h4><ol><li><strong>File:</strong> Choose an existing file or upload a new one.</li><li><strong>Overwrite file time:</strong> If checked, the current time at which the event is triggered is used for the timestamp of the event, regardless of the timestamp value in the file.</li><li><strong>Replay Once:</strong> Decide if the file should be replayed once or continuously until stopped.<ul><li>Options: <code>yes</code> (file is replayed once), <code>no</code> (file is replayed continuously)</li></ul></li><li><strong>Replay Speed:</strong> Set the frequency of events.<ul><li>Options: <code>Keep original time</code>, <code>Fastest (Ignore original time)</code>, <code>Speed Up Factor</code></li></ul></li><li><strong>Format:</strong> Choose the format to parse the events.<ul><li>Options: <code>JSON</code>, <code>CSV</code>, <code>XML</code>, <code>Image</code> (experimental feature)</li></ul></li></ol><h3 class="anchor anchorWithStickyNavbar_LWe7" id="use-case-create-a-sensor-simulator">Use Case: Create a Sensor Simulator<a href="#use-case-create-a-sensor-simulator" class="hash-link" aria-label="Direct link to Use Case: Create a Sensor Simulator" title="Direct link to Use Case: Create a Sensor Simulator">​</a></h3><p>Let's create a simulation data stream using your own sensor data. First, store the sample CSV data in a local file.</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">timestamp,density,mass_flow,sensorId,sensor_fault_flags,temperature,volume_flow</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1719897720887,41.82,6.306,flowrate01,false,41.9,3.365</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1719897721952,45.09,9.659,flowrate01,false,43.2,4.103</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1719897722958,42.84,9.532,flowrate01,true,42.6,3.110</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1719897723964,49.58,1.929,flowrate01,true,40.3,3.4684</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1719897724970,41.83,4.173,flowrate01,false,40.7,0.246</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1719897725975,48.11,10.90,flowrate01,false,46.4,5.275</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>To set up the adapter, follow these steps:</p><ol><li>Open StreamPipes Connect.</li><li>Click on <code>+ New Adapter</code>.</li><li>Select the <code>File Stream Adapter</code>.</li><li>Enter the following configuration:<ul><li><strong>File:</strong> Upload your sample data file.</li><li><strong>Overwrite file time:</strong> Check this box to use the current timestamp instead of the original time of the event in the file.</li><li><strong>Replay Once:</strong> Choose <code>no</code> to create an ongoing data stream.</li><li><strong>Replay Speed:</strong> Select <code>Keep original time</code> to maintain the original event frequency.</li><li><strong>Format:</strong> Pick <code>CSV</code>, set the delimiter as <code>,</code> and check the <code>Header</code> box.</li></ul></li><li>Click <code>Next</code> once you've added the correct configuration.</li><li>Configure the event schema by editing the <code>timestamp</code> field and selecting <code>Mark as timestamp</code>. Save your changes.</li><li>You can add additional meta information to the event schema, but it's not required for this tutorial. Click <code>Next</code> when done.</li><li>Enter an <code>Adapter Name</code>.</li><li>Check the <code>Persist events</code> box to store the data in the StreamPipes data store.</li><li>Click <code>Start Adapter</code>.</li></ol><p>Once configured, you should see the following preview:</p><img loading="lazy" src="/img/blog/2025-03-25/adapter_started.png" alt="Adapter Preview" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="use-case-persist-csv-file-to-data-lake">Use Case: Persist CSV File to Data Lake<a href="#use-case-persist-csv-file-to-data-lake" class="hash-link" aria-label="Direct link to Use Case: Persist CSV File to Data Lake" title="Direct link to Use Case: Persist CSV File to Data Lake">​</a></h3><p>Now, let's store the entire content of the file in the data lake. Once stored, you can analyze it with the <code>Data Explorer</code>. Here’s how to configure the adapter:</p><ul><li><strong>Overwrite file time:</strong> Leave this unchecked to retain the original timestamps.</li><li><strong>Replay Once:</strong> Choose <code>yes</code> to read the file only once.</li><li><strong>Replay Speed:</strong> Select <code>Fastest (Ignore original time)</code> to write data as fast as possible.</li></ul><div class="theme-admonition theme-admonition-info alert alert--info admonition_LlT9"><div class="admonitionHeading_tbUL"><span class="admonitionIcon_kALy"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_S0QG"><p>Ensure the <code>Persist events</code> checkbox is selected to save the data to the data lake during the <code>Start Adapter</code> configuration.</p></div></div><h3 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h3><p>In this tutorial, we've explored how to use the File Stream Adapter in Apache StreamPipes to create a simulation data stream and persist CSV data into a data lake.
This adapter lets you experiment with StreamPipes' capabilities and explore its functionality using your own data.
Happy streaming!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.97.0]]></title>
            <link>https://streampipes.apache.org/blog/2025/02/15/release-097</link>
            <guid>https://streampipes.apache.org/blog/2025/02/15/release-097</guid>
            <pubDate>Sat, 15 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Introduction]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2><p>Apache StreamPipes 0.97.0 brings exciting new features, enhanced security, and significant UX improvements to streamline your IIoT data processing workflows.
This release introduces <strong>Adapters &amp; Pipelines as Code</strong>, enabling users to define and deploy StreamPipes resources programmatically using YAML or JSON.
Security enhancements, such as <strong>OPC UA certificate support</strong> and <strong>Kafka SSL/SASL authentication</strong>, improve connectivity and data integrity.
Additionally, we have made various <strong>UX improvements</strong>, including an <strong>enhanced Data Explorer</strong> and <strong>asset-based filtering</strong>.</p><p>In total, the new release closes 159 issues including new features, bug fixes and improvements.</p><p>Read on to discover what’s new in StreamPipes 0.97.0!</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="adapters--pipeline-elements">Adapters &amp; Pipeline Elements<a href="#adapters--pipeline-elements" class="hash-link" aria-label="Direct link to Adapters &amp; Pipeline Elements" title="Direct link to Adapters &amp; Pipeline Elements">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="adapter--pipeline-as-code">Adapter &amp; Pipeline as Code<a href="#adapter--pipeline-as-code" class="hash-link" aria-label="Direct link to Adapter &amp; Pipeline as Code" title="Direct link to Adapter &amp; Pipeline as Code">​</a></h3><p>StreamPipes now supports managing adapters and pipelines programmatically using compact Json or YAML definitions.
These features are ideal for automating deployments, integrating with CI/CD pipelines, and applying infrastructure-as-code practices.</p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="adapters-as-code">Adapters as Code<a href="#adapters-as-code" class="hash-link" aria-label="Direct link to Adapters as Code" title="Direct link to Adapters as Code">​</a></h4><p>With Adapters as Code, you can define and deploy adapters via a compact description, streamlining the creation of multiple similar adapters and simplifying automation.
For example, here's a sample YAML snippet to define an OPC-UA adapter:</p><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> My OPC Adapter</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> testadapter</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Test</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">appId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> org.apache.streampipes.connect.iiot.adapters.opcua</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">configuration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">opc_host_or_url</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> OPC_URL</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">opc_server_url</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> opc.tcp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">62541/milo</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">adapter_type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> PULL_MODE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">pulling_interval</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">access_mode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> UNAUTHENTICATED</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">available_nodes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"ns=2;s=Leakage Test Station/temperature"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"ns=2;s=Leakage Test Station/pressure"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">schema</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">temperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">propertyScope</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> measurement</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">label</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Temp</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Temperature value</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">semanticType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">//schema.org/temperature</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">enrich</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">timestamp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> timestamp</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">transform</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">rename</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">pressure</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> pressure3</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">createOptions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">persist</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">start</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This approach considerably simplifies the programmatic creation of adapters <a href="https://streampipes.apache.org/docs/use-programmatically-create-adapters/" target="_blank" rel="noopener noreferrer">Learn more about Adapters as Code</a></p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="pipelines-as-code">Pipelines as Code<a href="#pipelines-as-code" class="hash-link" aria-label="Direct link to Pipelines as Code" title="Direct link to Pipelines as Code">​</a></h4><p>Pipelines as Code lets you define end-to-end data flows—from data sources through processors to sinks.
This function is ideal for the standardization and automation of pipeline deployments.
For example, here’s a sample YAML snippet for a simple pipeline:</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">pipeline</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">pipelineElements</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Define pipeline components here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> stream     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Data source</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">ref</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> &lt;reference</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Unique reference ID</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> &lt;data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ID of the stream</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> processor  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Data transformation</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">ref</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> &lt;reference</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Unique reference ID</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> &lt;processor</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ID of the processor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">connectedTo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Previous pipeline element reference(s)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> &lt;reference</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">configuration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Processor-specific configurations</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> &lt;configuration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">option</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> sink       </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Data sink (output)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">ref</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> &lt;reference</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Unique reference ID</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> &lt;sink</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># ID of the sink</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">connectedTo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Previous pipeline element reference(s)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> &lt;reference</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">configuration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">   </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Sink-specific configurations</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> &lt;configuration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">option</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">createOptions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">start</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> &lt;true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token plain">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># Whether to start the pipeline immediately</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The code preview of a pipeline has also been added to the <code>Start Pipeline</code> dialog, which has been further improved to make the execution status of pipelines more clear.</p><img loading="lazy" src="/img/blog/2025-02-15/pipeline_as_code_ui.png" alt="Pipeline as code in the UI" class="img_ev3q"><p>This method provides a programmatic interface to deploy and manage pipelines quickly and easily.
<a href="https://streampipes.apache.org/docs/use-programmatically-create-pipelines/" target="_blank" rel="noopener noreferrer">Learn more about Pipelines as Code</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="opc-ua-certificates">OPC UA Certificates<a href="#opc-ua-certificates" class="hash-link" aria-label="Direct link to OPC UA Certificates" title="Direct link to OPC UA Certificates">​</a></h3><p>The OPC UA adapter now supports both signed/encrypted and unencrypted communication.
Certificate provisioning is handled externally via environment variables, following a dedicated security directory layout. Refer to the <a href="https://streampipes.apache.org/docs/pe/org.apache.streampipes.connect.iiot.adapters.opcua/" target="_blank" rel="noopener noreferrer">OPC UA adapter documentation</a> for further details.</p><p><a href="https://github.com/apache/streampipes/pull/3354" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/pull/3354</a></p><img loading="lazy" src="/img/blog/2025-02-15/opc_ua_configuration.png" alt="OPC UA adapter configuration" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="kafka-avro--certificates">Kafka Avro &amp; Certificates<a href="#kafka-avro--certificates" class="hash-link" aria-label="Direct link to Kafka Avro &amp; Certificates" title="Direct link to Kafka Avro &amp; Certificates">​</a></h3><p>The Kafka adapter and sink now support SSL and SASL for enhanced security.
Additionally, users can provide custom producer/consumer configurations.
A new Avro parser has been added along with an input field for specifying the consumer group in the Kafka adapter.</p><img loading="lazy" src="/img/blog/2025-02-15/kafka_configuration.png" alt="Kafka adapter configuration" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-features--deprecations">New Features &amp; Deprecations<a href="#new-features--deprecations" class="hash-link" aria-label="Direct link to New Features &amp; Deprecations" title="Direct link to New Features &amp; Deprecations">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="asset-browser">Asset Browser<a href="#asset-browser" class="hash-link" aria-label="Direct link to Asset Browser" title="Direct link to Asset Browser">​</a></h3><p>StreamPipes now allows users to model real-world assets and associate them with StreamPipes resources such as adapters, pipelines, and dashboards.
These asset mappings enable intuitive filtering across different modules, making it easier to navigate and manage related resources.</p><p>The screenshot below illustrates an example where a StreamPipes instance is configured with two machines and various stations.
Clicking on a machine or station dynamically filters the associated resources in the list on the right.
This asset-based filtering is available across all main modules of StreamPipes.</p><img loading="lazy" src="/img/blog/2025-02-15/asset_filter.png" alt="Asset Filtering in StreamPipes" class="img_ev3q"><p>The asset overview panel has been redesigned to provide a more intuitive and user-friendly experience. It is possible to assign labels, locations, and ISA95 types to assets.
For each asset, resources such as pipelines, adapters and dashboards can be assigned. The asset overview contains an intuitive overview of all linked resources.</p><img loading="lazy" src="/img/blog/2025-02-15/asset_view.png" alt="Asset View" class="img_ev3q"><p>To manage locations &amp; sites, we extended the configuration menu with additional options to add a custom map layer provider and to configure the map view.</p><img loading="lazy" src="/img/blog/2025-02-15/asset_site_management.png" alt="Asset View" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="ux-improvements">UX improvements<a href="#ux-improvements" class="hash-link" aria-label="Direct link to UX improvements" title="Direct link to UX improvements">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="file-relocation">File Relocation<a href="#file-relocation" class="hash-link" aria-label="Direct link to File Relocation" title="Direct link to File Relocation">​</a></h3><p>The file upload configuration has been moved from the top-level navigation to the settings menu, improving the overall structure and clarity of the main navigation.</p><p>This change does not affect file uploads required by adapters or pipeline elements—these configurations remain unchanged.
Further, users can still upload files as before via the files configuration section.</p><img loading="lazy" src="/img/blog/2025-02-15/file_upload.png" alt="File upload configuration" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="adapter-data-preview">Adapter Data Preview<a href="#adapter-data-preview" class="hash-link" aria-label="Direct link to Adapter Data Preview" title="Direct link to Adapter Data Preview">​</a></h3><p>Viewing live data streams in the adapter configuration has been improved. By clicking on "details", a full-screen view of the data preview is displayed.
Changing data values are highlighted, so that it is ease to track changes. The Code panel shows the configuration in JSON or YAML format.</p><img loading="lazy" src="/img/blog/2025-02-15/adapter_preview.png" alt="Adapter preview" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="data-explorer-configuration-improvements">Data Explorer Configuration Improvements<a href="#data-explorer-configuration-improvements" class="hash-link" aria-label="Direct link to Data Explorer Configuration Improvements" title="Direct link to Data Explorer Configuration Improvements">​</a></h3><p>Configuring data views in the <strong>Data Explorer</strong> is now more intuitive and user-friendly.
We have enhanced validation, making it easier to select data sources and specify queries while reducing potential misconfigurations.</p><p>Key improvements include:</p><ul><li><strong>Default Table Visualization</strong>: New data views now default to a table view, minimizing setup effort.</li><li><strong>Improved Time Range Picker</strong>: More flexibility in selecting time ranges, including support for different time ranges per widget in Data Lake dashboards.</li><li><strong>Auto-Refresh for Dashboards</strong>: Live updates are now possible with the new auto-refresh functionality.</li><li><strong>Better Error Messages</strong>: Enhanced feedback when configurations are incorrect to improve usability.</li><li><strong>Custom color coding for pie chart</strong>: In the pie chart, custom colors can be mapped to specific data values.</li><li><strong>Traffic light visualization</strong>: A new traffic light visualization has been added to the Data Explorer.</li></ul><img loading="lazy" src="/img/blog/2025-02-15/data_explorer_configuration.png" alt="Improve configuration for data explorer views" class="img_ev3q"><p>Here is a screenshot of the new traffic light visualization:</p><img loading="lazy" src="/img/blog/2025-02-15/data_explorer_traffic_light.png" alt="Traffic Light chart in the data explorer" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-details">Pipeline Details<a href="#pipeline-details" class="hash-link" aria-label="Direct link to Pipeline Details" title="Direct link to Pipeline Details">​</a></h3><p>The pipeline details view has been completely remodeled. It now shows the pipeline in full-screen mode, making it easier to view and edit complex pipelines.
A sidebar contains further information on the pipeline, such as logs, pipeline elements, and execution status.
In addition, execution metrics are now intuitively accessible right in the pipeline details view.</p><img loading="lazy" src="/img/blog/2025-02-15/pipeline_preview.png" alt="Pipeline preview" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="deprecation-notice-dashboard">Deprecation Notice: Dashboard<a href="#deprecation-notice-dashboard" class="hash-link" aria-label="Direct link to Deprecation Notice: Dashboard" title="Direct link to Deprecation Notice: Dashboard">​</a></h3><p>The current live dashboard feature in StreamPipes is being deprecated and will be removed in a future release.
As a replacement, the Data Explorer dashboards has been enhanced with auto-refresh functionality, ensuring a seamless transition for users who rely on real-time data visualization.</p><p>The harmonization of data explorer and live dashboard functionalities will provide a more consistent user experience and will ease the addition of new charts in future version, since all visualizations now rely on a single visualization library.</p><p>We encourage all users to migrate their existing dashboards to the Data Explorer to continue leveraging powerful visualization and analysis capabilities.</p><p>If you think any feature is missing in the data explorer, please let us know!</p><img loading="lazy" src="/img/blog/2025-02-15/deprecated_dashboards.png" alt="Dashboard Deprecation Notice" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2><p>We appreciate the ongoing support and contributions from our community in making StreamPipes better with each release.
Version 0.97.0 brings improvements in usability, security, and automation, helping users to analyze their IIoT data sources.</p><p>As always, we welcome your feedback and suggestions to continue refining and enhancing StreamPipes.
Feel free to share your thoughts or get involved through <strong>GitHub</strong> or <strong>mailing list</strong>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.95.0]]></title>
            <link>https://streampipes.apache.org/blog/2024/06/13/release-095</link>
            <guid>https://streampipes.apache.org/blog/2024/06/13/release-095</guid>
            <pubDate>Thu, 13 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[We're excited to share the release of StreamPipes 0.95.0, bringing with it a range of bug fixes and new features.]]></description>
            <content:encoded><![CDATA[<p>We're excited to share the release of StreamPipes 0.95.0, bringing with it a range of bug fixes and new features.
In total, the newest release closes over 200 issues.
This release doesn't include many large feature drops, we have worked a lot on making small things smoother and improving StreamPipes under the hood.
As we continue to work on the 1.0 release of Apache StreamPipes probably later this year, this release features many improvements to the end-user experience and bug fixes.</p><p>Let's delve into the key updates introduced in this release.</p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="adapters--pipeline-elements">Adapters &amp; Pipeline Elements<a href="#adapters--pipeline-elements" class="hash-link" aria-label="Direct link to Adapters &amp; Pipeline Elements" title="Direct link to Adapters &amp; Pipeline Elements">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="improve-deletion-workflow-of-adapters">Improve deletion workflow of adapters<a href="#improve-deletion-workflow-of-adapters" class="hash-link" aria-label="Direct link to Improve deletion workflow of adapters" title="Direct link to Improve deletion workflow of adapters">​</a></h3><p>Within StreamPipes 0.93.0 we introduced the possibility to <a href="https://streampipes.apache.org/blog/2023/11/28/release-093/#editing-existing-adapters" target="_blank" rel="noopener noreferrer">edit existing adapters</a>.
This release improves adapter management by conveniently allowing to delete existing adapters even if they are used in a pipeline.
When deleting a new adapter, a dialog appears which allows users to delete all pipelines which are using the data stream produced by the adapter.</p><p><a href="https://github.com/apache/streampipes/issues/1936" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/1936</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="enhance-data-lake-schema-management">Enhance data lake schema management<a href="#enhance-data-lake-schema-management" class="hash-link" aria-label="Direct link to Enhance data lake schema management" title="Direct link to Enhance data lake schema management">​</a></h3><p>We've added a new option to the data lake sink which provides users more flexibility when writing data to the internal time-series storage.
Users can choose between the <code>Update Schema</code> and <code>Extend existing schema</code> options.
By choosing <code>Extend schema</code>, it is possible to also see "old" data in the data explorer after the schema has changed.</p><img loading="lazy" src="/img/blog/2024-06-13/data-lake-sink-configuration.png" style="width:70%;margin-left:auto;margin-right:auto" class="img_ev3q"><p><a href="https://github.com/apache/streampipes/issues/2252" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2252</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-adapter-open-industry-40-devices">New Adapter: Open Industry 4.0 devices<a href="#new-adapter-open-industry-40-devices" class="hash-link" aria-label="Direct link to New Adapter: Open Industry 4.0 devices" title="Direct link to New Adapter: Open Industry 4.0 devices">​</a></h3><p>A new adapter in 0.95.0 is support for the <a href="https://openindustry4.com/" target="_blank" rel="noopener noreferrer">Open Industry 4.0</a> specification over MQTT.
The adapter can be used to connect to a variety of devices which support the data format defined in the <a href="https://openindustry4.com/fileadmin/Dateien/Downloads/OEC_Development_Guideline_V1.1.1.pdf" target="_blank" rel="noopener noreferrer">Development Guidelines for Open Edge Computing</a>.</p><p>For instance, the adapter makes it easy to use IO-Link sensors together with an OI4-compatible IO-Link master.</p><p><a href="https://github.com/apache/streampipes/pull/2511" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/pull/2511</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-adapters-all-plc4x-protocols-supported-as-adapters">New Adapter(s): All PLC4X protocols supported as adapters<a href="#new-adapters-all-plc4x-protocols-supported-as-adapters" class="hash-link" aria-label="Direct link to New Adapter(s): All PLC4X protocols supported as adapters" title="Direct link to New Adapter(s): All PLC4X protocols supported as adapters">​</a></h3><p>Since our "sister project" <a href="https://plc4x.apache.org" target="_blank" rel="noopener noreferrer">Apache PLC4X</a> has introduced a new metadata API for gathering available drivers, StreamPipes 0.95.0 now supports a much larger collection of PLC connectors.
The list of newly supported protocols include:</p><ul><li>Allen Bradley ETH</li><li>BACnet/IP</li><li>Beckhoff TwinCat ADS</li><li>EthernetIP</li><li>Modbus ASCII/RTU/TCP</li></ul><p>The already existing S7 adapter is now also available with additional configuration options.</p><img loading="lazy" src="/img/blog/2024-06-13/plc-adapter-overview.png" class="img_ev3q"><p>Configurations on protocol and transport level are dynamically resolved from the PLC4X API. This ensures that users now have much greater flexibility when connecting to industrial protocols.</p><p>The screenshot below shows the advanced options panel for Modbus TCP:</p><img loading="lazy" src="/img/blog/2024-06-13/modbus-configuration.png" class="img_ev3q"><p>The new adapters should be considered a beta feature and we still recommend to use the existing Modbus and S7 adapters until the new adapters have proven their stability.
More information on the usage of these new adapters and supported features can also be found on the PLC4X website. </p><p><a href="https://github.com/apache/streampipes/issues/2632" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2632</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-processor-static-metadata-enrichment">New Processor: Static Metadata enrichment<a href="#new-processor-static-metadata-enrichment" class="hash-link" aria-label="Direct link to New Processor: Static Metadata enrichment" title="Direct link to New Processor: Static Metadata enrichment">​</a></h3><p>We added a new processor to add static metadata (such as sensor ID or location IDs) to any data stream within a pipeline.</p><p><a href="https://github.com/apache/streampipes/issues/2350" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2350</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-processor-datetime-from-string">New Processor: Datetime from String<a href="#new-processor-datetime-from-string" class="hash-link" aria-label="Direct link to New Processor: Datetime from String" title="Direct link to New Processor: Datetime from String">​</a></h3><p>The new <code>Datetime from String</code> processor allows to convert a datetime string to a timestamp value and lets users conveniently choose the desired target time zone.</p><img loading="lazy" src="/img/blog/2024-06-13/datetime-from-string.png" class="img_ev3q"><p><a href="https://github.com/apache/streampipes/issues/1865" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/1865</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-sink-ms-teams">New Sink: MS Teams<a href="#new-sink-ms-teams" class="hash-link" aria-label="Direct link to New Sink: MS Teams" title="Direct link to New Sink: MS Teams">​</a></h3><p>StreamPipes 0.95.0 comes with a new data sink for Microsoft Teams, which allows to publish notifications from a pipeline to a teams channel using Webhooks.</p><img loading="lazy" src="/img/blog/2024-06-13/ms-teams-sink.png" class="img_ev3q"><p><a href="https://github.com/apache/streampipes/pull/2248" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/pull/2248</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="remove-deprecated-adapters">Remove deprecated adapters<a href="#remove-deprecated-adapters" class="hash-link" aria-label="Direct link to Remove deprecated adapters" title="Direct link to Remove deprecated adapters">​</a></h3><p>We removed several outdated adapters that were deprecated in release 0.93.0:</p><ul><li>CoindeskBitcoinAdapter</li><li>GdeltAdapter</li><li>FlicMQTTAdapter</li><li>TISensorTag</li><li>IexCloudAdapter</li><li>OpenSenseMapAdapter</li><li>WikipediaAdapter</li></ul><p><a href="https://github.com/apache/streampipes/issues/2128" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2128</a></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="ux-improvements">UX improvements<a href="#ux-improvements" class="hash-link" aria-label="Direct link to UX improvements" title="Direct link to UX improvements">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="display-file-types-in-different-colors">Display file types in different colors<a href="#display-file-types-in-different-colors" class="hash-link" aria-label="Direct link to Display file types in different colors" title="Direct link to Display file types in different colors">​</a></h3><p>Different file types in the <code>Files</code> overview are now better highlighted by a dedicated color.</p><p><a href="https://github.com/apache/streampipes/issues/2107" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2107</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="download-button-for-asset--files">Download button for asset &amp; files<a href="#download-button-for-asset--files" class="hash-link" aria-label="Direct link to Download button for asset &amp; files" title="Direct link to Download button for asset &amp; files">​</a></h3><p>In the asset and file overview, resources can be now directly downloaded by using a new download button.</p><p><a href="https://github.com/apache/streampipes/issues/2192" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2192</a>
<a href="https://github.com/apache/streampipes/issues/2074" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2074</a></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-python">StreamPipes Python<a href="#streampipes-python" class="hash-link" aria-label="Direct link to StreamPipes Python" title="Direct link to StreamPipes Python">​</a></h2><p>As already mentioned in our <a href="/blog/2024/03/27/anomaly-detection-with-python-functions/">blog post</a>, we added an example to use an existing <a href="https://onnx.ai/" target="_blank" rel="noopener noreferrer">ONNX</a> model as part of a StreamPipes function.</p><p><a href="https://github.com/apache/streampipes/pull/2687" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/pull/2687</a></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="administration--development">Administration &amp; Development<a href="#administration--development" class="hash-link" aria-label="Direct link to Administration &amp; Development" title="Direct link to Administration &amp; Development">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="remove-consul-entirely">Remove Consul entirely<a href="#remove-consul-entirely" class="hash-link" aria-label="Direct link to Remove Consul entirely" title="Direct link to Remove Consul entirely">​</a></h3><p>Following the replacement of Consul with an internal service registration and discovery mechanism, StreamPipes 0.95.0 also removes Consul from all installation files.</p><p><a href="https://github.com/apache/streampipes/issues/2133" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/issues/2133</a></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-apache-streampipes-go-client">New Apache StreamPipes Go-Client<a href="#new-apache-streampipes-go-client" class="hash-link" aria-label="Direct link to New Apache StreamPipes Go-Client" title="Direct link to New Apache StreamPipes Go-Client">​</a></h2><p>Apache StreamPipes now includes a new client library for Golang.
Our first version of the Go client interacts with the StreamPipes API and provides various ways to gather data from StreamPipes.</p><p>Here is an example on the usage of the Go client:</p><div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">package</span><span class="token plain"> main</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"github.com/apache/streampipes/streampipes-client-go/streampipes"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"github.com/apache/streampipes/streampipes-client-go/streampipes/config"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"log"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/*</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">    Here are some examples of using go client, including outputting the data returned by streams.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">    Only supports outputting model data</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">func</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    clientConfig </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> config</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">StreamPipesClientConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        Url</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"http://localhost:8030"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        Credential</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> config</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">StreamPipesApiKeyCredentials</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            UserName</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"&lt;Your-User-Name&gt;"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            ApiKey</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">   </span><span class="token string" style="color:rgb(195, 232, 141)">"&lt;Your-API-Key&gt;"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    streamPipesClient</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> err </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">NewStreamPipesClient</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">clientConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> err </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Fatal</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    dataSeries</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> err </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> streamPipesClient</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">DataLakeMeasures</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">GetSingleDataSeries</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"measureName"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> err </span><span class="token operator" style="color:rgb(137, 221, 255)">!=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Fatal</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    dataSeries</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/*</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            output format:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="display:inline-block;color:rgb(105, 112, 152);font-style:italic"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            There are 2 pieces of DataSerie in the Dataseries</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            The 1 DataSeries</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            time                   msg                   test</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            2024-02-23T13:37:09.052Z   go-client_test   2f4556</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            2024-02-23T13:37:26.044Z   go-client_test   2f4556</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            2024-02-23T13:37:29.007Z   go-client_test   2f4556</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            The 2 DataSeries</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            time                   msg                   test</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            2024-02-23T13:38:06.052Z   go-client_test   2f4556</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            2024-02-23T13:38:35.044Z   go-client_test   2f4556</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">            2024-02-23T13:38:38.007Z   go-client_test   2f4556</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="display:inline-block;color:rgb(105, 112, 152);font-style:italic"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><a href="https://github.com/apache/streampipes/pull/2437" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampipes/pull/2437</a></p><p>First release, are working on more examples and better docs - stay tuned</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="final-remarks">Final Remarks<a href="#final-remarks" class="hash-link" aria-label="Direct link to Final Remarks" title="Direct link to Final Remarks">​</a></h2><p>We highly recommend updating to StreamPipes 0.95.0 to take advantage of these new features, bug fixes, and improvements.
For more detailed information, please refer to
the <a href="https://github.com/apache/incubator-streampipes/blob/release/0.95.0/RELEASE_NOTES.md#0950" target="_blank" rel="noopener noreferrer">release notes</a>.</p><p>We appreciate your continued support and valuable feedback.
StreamPipes is continually evolving, and we are dedicated to providing you with a powerful and reliable platform for
your IIoT streaming data needs.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Anomaly Detection with StreamPipes Functions in Python and ONNX]]></title>
            <link>https://streampipes.apache.org/blog/2024/03/27/anomaly-detection-with-python-functions</link>
            <guid>https://streampipes.apache.org/blog/2024/03/27/anomaly-detection-with-python-functions</guid>
            <pubDate>Wed, 27 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache StreamPipes saves the day when it comes to connecting to data sources in the IIoT world. Want to do more with]]></description>
            <content:encoded><![CDATA[<p>Apache StreamPipes saves the day when it comes to connecting to data sources in the IIoT world. Want to do more with
your IIoT data than just analyze it in a dashboard? If so, this blog post is for you! We'll show you how to extract
historical data from StreamPipes, use it to train a machine learning model, bring the model back to StreamPipes using
ONNX, and apply the model to live data.</p><center><img loading="lazy" class="blog-image" style="max-width:75%" src="/img/blog/2024-03-26/prediction-analysis.png" alt="anomaly-detection"><br></center><h2 class="anchor anchorWithStickyNavbar_LWe7" id="motivation">Motivation<a href="#motivation" class="hash-link" aria-label="Direct link to Motivation" title="Direct link to Motivation">​</a></h2><p>With this blogpost we want to illustrate how one can easily extract historical IIoT data collected with StreamPipes,
train a machine learning model on this data and bringing the model back to StreamPipes with the interoperability
standard <a href="https://onnx.ai" target="_blank" rel="noopener noreferrer">ONNX</a> to make inference in live data.</p><p>A very common use case in the area of IIoT is the detection of anomalies, so we want to tackle this challenge in this
article as well. We will use data generated by
the <a href="https://streampipes.apache.org/docs/pe/org.apache.streampipes.connect.iiot.adapters.simulator.machine/" target="_blank" rel="noopener noreferrer">Machine Data Simulator</a>
adapter. More specifically, we will focus on the <code>flowrate</code> data, which consists of various sensor values coming from a
water pipe system. Our goal is to keep an eye on the parameter <code>volume_flow</code>, which represents the current volume flow
in
cubic meters/second. For this parameter, we want to detect anomalies that could indicate problems such as leaks,
blockages, etc.</p><p>To get the concerned data, we simply need to create an instance of the machine data simulator and persist the data in
the data lake:</p><p><img loading="lazy" src="https://raw.githubusercontent.com/apache/streampipes/dev/streampipes-client-python/docs/img/tutorial-preparation.gif" alt="tutorial-preparation" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="set-up--prepare-python-client">Set Up &amp; Prepare Python Client<a href="#set-up--prepare-python-client" class="hash-link" aria-label="Direct link to Set Up &amp; Prepare Python Client" title="Direct link to Set Up &amp; Prepare Python Client">​</a></h2><p>As a prerequisite, we need to install the StreamPipes Python client and all other dependencies,</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">pip </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> git+https://github.com/apache/streampipes.git</span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">#subdirectory=streampipes-client-python</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">pip </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> scikit-learn</span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token number" style="color:rgb(247, 140, 108)">1.4</span><span class="token plain">.0 </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">skl2onnx</span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token number" style="color:rgb(247, 140, 108)">1.16</span><span class="token plain">.0 </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">onnxruntime</span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token number" style="color:rgb(247, 140, 108)">1.17</span><span class="token plain">.1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The next step is to configure and initialize an instance of the client.</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> os</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">client </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> StreamPipesClient</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">config </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> StreamPipesClientConfig</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">credential_provider </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> StreamPipesApiKeyCredentials</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">os</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">environ</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">"BROKER-HOST"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"localhost"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">os</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">environ</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">"KAFKA-PORT"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"9094"</span><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># When using Kafka as message broker</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">config </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> StreamPipesClientConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    credential_provider</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">StreamPipesApiKeyCredentials</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        username</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"admin@streampipes.apache.org"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        api_key</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"TOKEN"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    host_address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"localhost"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    https_disabled</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token boolean" style="color:rgb(255, 88, 116)">True</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    port</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">client </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> StreamPipesClient</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">client_config</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">config</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>In case you have never worked with the Python client before and have problems to get started,
please have a look at
our <a href="https://streampipes.apache.org/docs/docs/python/latest/tutorials/1-introduction-to-streampipes-python-client/" target="_blank" rel="noopener noreferrer">tutorial</a>.</p><p>If you already have an ONNX model and are only interested in applying it with StreamPipes on a data stream, you can skip
the following section.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="model-training-with-historic-data">Model Training with Historic Data<a href="#model-training-with-historic-data" class="hash-link" aria-label="Direct link to Model Training with Historic Data" title="Direct link to Model Training with Historic Data">​</a></h2><p>As said above, the aim of our model is to detect anomalies of the <code>volume_flow</code> parameter. For this task, we will use
<a href="https://en.wikipedia.org/wiki/Isolation_forest" target="_blank" rel="noopener noreferrer">Isolation Forests</a>. Please note that the focus of the tutorial is not
on training the model, so please be patient even though the training is very simplified and lacks important preparation
steps such as standardization.</p><p>As a first step, lets query the <code>flowrate</code> data from the StreamPipes data lake and extract the values of <code>volume_flow</code>
as a feature:</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">flowrate_df </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">dataLakeMeasureApi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"flow-rate"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">to_pandas</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">X </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> flowrate_df</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">"volume_flow"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">values</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">reshape</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">astype</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"float32"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>As a next step, we can already train our model with the historic data:</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> sklearn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">ensemble </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> IsolationForest</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">model </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> IsolationForest</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">contamination</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0.01</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">model</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">fit</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">X</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The <code>contamination</code> parameter models the proportion of outliers in the data. See
the <a href="https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html" target="_blank" rel="noopener noreferrer">scikit-learn</a>
documentation for more information.</p><p>Here you can see how this simple model performs:</p><img loading="lazy" src="/img/blog/2024-03-26/prediction-analysis.png" class="img_ev3q"><p></p><p>This doesn't look too bad, right? Let's continue by converting our model to the ONNX representation.</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> onnxconverter_common </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> FloatTensorType</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> skl2onnx </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> to_onnx</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">model_onnx </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> to_onnx</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    model</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    initial_types</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'input'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> FloatTensorType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> X</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">shape</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    target_opset</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string" style="color:rgb(195, 232, 141)">'ai.onnx.ml'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'ai.onnx'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">15</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">''</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">15</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">with</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">open</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"isolation_forest.onnx"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"wb"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">write</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">model_onnx</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">SerializeToString</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="model-inference-with-live-data">Model Inference with Live Data<a href="#model-inference-with-live-data" class="hash-link" aria-label="Direct link to Model Inference with Live Data" title="Direct link to Model Inference with Live Data">​</a></h2><p>Utilizing a pre-trained model within StreamPipes becomes seamless with the ONNX interoperability standard, enabling
effortless application of your existing model on live data streams.</p><p>Interacting with live data from StreamPipes is facilitated through StreamPipes functions. Below, we'll create a Python
StreamPipes function that leverages an ONNX model to generate predictions for each incoming event, making the results
accessible as a data stream within StreamPipes for subsequent steps.</p><p>So let's create an <code>ONNXFunction</code> that is capable of applying a model in ONNX representation to a StreamPipes data
stream.
If you'd like to read more details about how functions are defined, refer
to <a href="https://streampipes.apache.org/docs/docs/python/latest/tutorials/3-getting-live-data-from-the-streampipes-data-stream/" target="_blank" rel="noopener noreferrer">our tutorial</a>.</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> numpy </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> np</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> onnxruntime </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> rt</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">functions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">broker</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">broker_handler </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> get_broker_description</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">functions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">streampipes_function </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> StreamPipesFunction</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">functions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">utils</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">data_stream_generator </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> create_data_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> RuntimeType</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">functions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">utils</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">function_context </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> FunctionContext</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">model</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">resource </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> FunctionDefinition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> DataStream</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> typing </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> Dict</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Any</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> List</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ONNXFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">StreamPipesFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">__init__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> feature_names</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">list</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token builtin" style="color:rgb(130, 170, 255)">str</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> input_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> DataStream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        output_stream </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> create_data_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            name</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"flowrate-prediction"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            attributes</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token string" style="color:rgb(195, 232, 141)">"is_anomaly"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> RuntimeType</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">BOOLEAN</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">value</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            broker</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">get_broker_description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">input_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        function_definition </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> FunctionDefinition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            consumed_streams</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">input_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">element_id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">add_output_data_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">output_stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">feature_names </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> feature_names</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">input_name </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">output_name </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">session </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token builtin" style="color:rgb(130, 170, 255)">super</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">__init__</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">function_definition</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">function_definition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>First, we need to take care about the data stream that is required to send the predictions from our function to
StreamPipes. Thus, we create a dedicated output data stream which we need to provide with the attributes our event will
consist of (a timestamp attribute is always added automatically). This output data stream needs to be registered at the
function definition which is to be passed to the parent class. Lastly, we need to define some instance variables that
are mainly required for the ONNX runtime.</p><p>Next, we need to ensure that ONNX runtime session is created on start up. Thus, we need to invoke an InferenceSession
and retrieving the corresponding configuration parameters:</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ONNXFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">StreamPipesFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStarted</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> FunctionContext</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">session </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> rt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">InferenceSession</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            path_or_bytes</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"isolation_forest.onnx"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            providers</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">rt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get_available_providers</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">input_name </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get_inputs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">name</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">output_name </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get_outputs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">name</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Lastly, we need to implement the inference logic that is applied to every event.
If you have brought up your own model, you need to adapt line <code>10-13</code>:</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm"><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ONNXFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">StreamPipesFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onEvent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Dict</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token builtin" style="color:rgb(130, 170, 255)">str</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Any</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> streamId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">str</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        feature_vector </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> feature </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">feature_names</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            feature_vector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">append</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">feature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        prediction </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">output_name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">input_name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> np</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">expand_dims</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">np</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">array</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">feature_vector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> axis</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">astype</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"float32"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        output </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token string" style="color:rgb(195, 232, 141)">"is_anomaly"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">int</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">prediction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">add_output</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            stream_id</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">function_definition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get_output_stream_ids</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            event</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">output</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStopped</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">None</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token keyword" style="font-style:italic">pass</span></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Having the function code in place, we can start the function with the following:</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">functions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">registration </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> Registration</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">functions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">function_handler </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> FunctionHandler</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">stream </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    stream</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> stream</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">dataStreamApi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token builtin" style="color:rgb(130, 170, 255)">all</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> stream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">name </span><span class="token operator" style="color:rgb(137, 221, 255)">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"flow-rate"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">function </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> ONNXFunction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    feature_names</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">"volume_flow"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    input_stream</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">stream</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">registration </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> Registration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">registration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">register</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">function</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">function_handler </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> FunctionHandler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">registration</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">function_handler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">initializeFunctions</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>We can now access the live values of the prediction in the StreamPipes UI, e.g., in the pipeline editor.</p><img loading="lazy" src="/img/blog/2024-03-26/tutorial-prediction-data-stream.png" class="img_ev3q"><p></p><p>From here on you can further work with the prediction events in StreamPipes, e.g., by sending notifications
to <a href="https://streampipes.apache.org/docs/next/pe/org.apache.streampipes.sinks.notifications.jvm.msteams/" target="_blank" rel="noopener noreferrer">MS Teams</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.93.0]]></title>
            <link>https://streampipes.apache.org/blog/2023/11/28/release-093</link>
            <guid>https://streampipes.apache.org/blog/2023/11/28/release-093</guid>
            <pubDate>Tue, 28 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[9 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>9 minutes to read</strong></div><p></p><p>We're excited to share the release of StreamPipes 0.93.0, bringing with it a range of bug fixes and new features.
This release places a strong emphasis on refining the technical foundations of
StreamPipes, featuring significant changes that set the stage for our major 1.0 release.
Nevertheless, we haven't overlooked the end-user experience and have implemented several enhancements.
Let's delve into the key updates introduced in this release.</p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="adapters--pipeline-elements">Adapters &amp; Pipeline Elements<a href="#adapters--pipeline-elements" class="hash-link" aria-label="Direct link to Adapters &amp; Pipeline Elements" title="Direct link to Adapters &amp; Pipeline Elements">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="editing-existing-adapters">Editing existing adapters<a href="#editing-existing-adapters" class="hash-link" aria-label="Direct link to Editing existing adapters" title="Direct link to Editing existing adapters">​</a></h3><p>StreamPipes has streamlined the process of modifying existing adapter instances, eliminating the inconvenience users
previously faced. In prior versions, altering an adapter required a cumbersome sequence of stopping, deleting, and then
recreating the adapter. However, with the introduction of StreamPipes 0.93.0, this arduous process is now a thing of the
past.</p><p>Users can now seamlessly edit running adapters, and the changes will be applied automatically, obviating the need for
the aforementioned manual steps. To guide you through this newfound capability, refer to the below animation,
which demonstrates how to modify an existing adapter.</p><img loading="lazy" src="/img/blog/2023-11-28/edit-adapter-success.gif" alt="animation of editing a running adapter" class="img_ev3q"><br><br><p>While the automatic migration seamlessly handles the majority of cases, there are instances where it may not be
feasible. One such scenario arises when an event property, used by a pipeline element, is removed. In such cases,
StreamPipes proactively alerts users before initiating the adapter update. Following the alert, the system takes
precautionary measures by halting the adapter and marking the associated pipeline for review.</p><img loading="lazy" src="/img/blog/2023-11-28/edit-adapter-fail.gif" alt="animation of editing running adapter where migration cannot be performed" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="opc-ua-allows-detailed--asynchronous-browsing">OPC-UA allows detailed &amp; asynchronous browsing<a href="#opc-ua-allows-detailed--asynchronous-browsing" class="hash-link" aria-label="Direct link to OPC-UA allows detailed &amp; asynchronous browsing" title="Direct link to OPC-UA allows detailed &amp; asynchronous browsing">​</a></h3><p>We have fully reworked the browsing interface of our OPC-UA adapter.</p><img loading="lazy" src="/img/blog/2023-11-28/opc-ua-demo.gif" alt="demonstration of the new OPC UA capabilities described below" class="img_ev3q"><br><br><p>Now, all you need to do is specify the URL where the OPC UA server is accessible, eliminating the need to concern
yourself with namespaces or node ids. Once the URL is provided, the adapter effortlessly presents all top-level nodes
within the user interface. You can then navigate through the node tree interactively by clicking on the desired node.</p><p>For every data node, accessing node information is a breeze – simply click on the eye icon. If you wish to subscribe to
a particular node, a straightforward click on the plus icon is all it takes.</p><p>All the nodes you select become integral to the event structure of this adapter, accessible by clicking on  <code>Next</code>. The
ensuing view not only displays the OPC UA status for each node but also allows for the removal of a node with ease,
especially if its status is not <code>Good</code>.</p><img loading="lazy" src="/img/blog/2023-11-28/opc-ua-status.png" alt="Screenshot of the OPC UA event view that shows the status codes" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="adapter-for-s7-plcs-supports-array-based-data">Adapter for S7 PLCs supports array-based data<a href="#adapter-for-s7-plcs-supports-array-based-data" class="hash-link" aria-label="Direct link to Adapter for S7 PLCs supports array-based data" title="Direct link to Adapter for S7 PLCs supports array-based data">​</a></h3><p>Until now, our S7 PLC adapter lacked the capability to read values structured in arrays. We're pleased to announce that
this limitation has been addressed through the introduction of an <code>Advanced</code> register input mode.</p><img loading="lazy" src="/img/blog/2023-11-28/s7-advanced-mode.png" alt="Screenshot of new advanced register input mode for S7 PLC adapter" class="img_ev3q"><br><br><p>This new mode empowers you to configure the registers to be queried in a manner specific to the requirements of our
underlying dependency, <a href="https://plc4x.apache.org" target="_blank" rel="noopener noreferrer">PLC4X</a>. For detailed insights and guidance on the configuration
process, refer to the <a href="https://plc4x.apache.org/users/protocols/s7.html" target="_blank" rel="noopener noreferrer">PLC4X S7 documentation</a>.</p><p>When dealing with array definitions, the configuration would resemble the following:</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># propertyName=%{Memory-Area}{start-address}:{Data-Type}[{array-size}]</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">temperature=%DB3.DB0.0[BOOL]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-adapter-ifm-iolink">New Adapter: ifm IOLink<a href="#new-adapter-ifm-iolink" class="hash-link" aria-label="Direct link to New Adapter: ifm IOLink" title="Direct link to New Adapter: ifm IOLink">​</a></h3><p>The <a href="https://www.ifm.com/de/en/product/AL1350" target="_blank" rel="noopener noreferrer">IO-Link Master (AL1350)</a> from ifm comes equipped with an IoT interface
designed for transmitting sensor data via MQTT. With the introduction of this adapter, users gain the capability to
effortlessly incorporate IO-Link sensor data into StreamPipes. This experimental integration empowers users to
effortlessly connect to data from the ifm sensor VVB001.</p><p>For more details refer to
the <a href="https://streampipes.apache.org/docs/next/pe/org.apache.streampipes.connect.iiot.adapters.iolink/" target="_blank" rel="noopener noreferrer">adapter documentation</a>.</p><p>For the integration of additional sensors we are thinking about supporting <a href="https://en.wikipedia.org/wiki/IODD" target="_blank" rel="noopener noreferrer">IODD</a>.
Your feedback on these considerations is invaluable to us. If you find the integration of IODD
for supporting more sensors within StreamPipes appealing or have insights to share, we welcome your input. Please let us
know your thoughts on this potential feature enhancement.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-processor-numeric-rounding">New Processor: Numeric Rounding<a href="#new-processor-numeric-rounding" class="hash-link" aria-label="Direct link to New Processor: Numeric Rounding" title="Direct link to New Processor: Numeric Rounding">​</a></h3><p>Introducing our latest data processor, <em>Numeric Rounding</em> , designed to perform rounding operations on numeric values
within an event stream. This processor enables users to select one or more numeric values from their event data,
specifying the desired rounding precision and the rounding mode.</p><p>For more details refer to
the <a href="https://streampipes.apache.org/docs/next/pe/org.apache.streampipes.processors.transformation.jvm.round/" target="_blank" rel="noopener noreferrer">processor documentation</a>.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="ux-improvements">UX improvements<a href="#ux-improvements" class="hash-link" aria-label="Direct link to UX improvements" title="Direct link to UX improvements">​</a></h3><h4 class="anchor anchorWithStickyNavbar_LWe7" id="ordered-measurement-units">Ordered measurement units<a href="#ordered-measurement-units" class="hash-link" aria-label="Direct link to Ordered measurement units" title="Direct link to Ordered measurement units">​</a></h4><p>In the adapter configuration step, when setting up a transformation rule for an event value, the available units of
measurement are now conveniently organized in alphabetical order for improved accessibility and ease of selection.</p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="extended-information-for-existing-adapters">Extended information for existing adapters<a href="#extended-information-for-existing-adapters" class="hash-link" aria-label="Direct link to Extended information for existing adapters" title="Direct link to Extended information for existing adapters">​</a></h4><p>When accessing the <em>Connect</em> module, a comprehensive list of all existing adapters is presented. Within this view, each
adapter now includes details about the timestamp of the last event creation and the total count of elements published
since startup. This enhancement provides a quick and efficient means to evaluate the health of each adapter.</p><img loading="lazy" src="/img/blog/2023-11-28/adapter-information.png" alt="Screenshot that shows the extended information for existing adapters" class="img_ev3q"><h4 class="anchor anchorWithStickyNavbar_LWe7" id="interactive-tutorial-is-back">Interactive tutorial is back<a href="#interactive-tutorial-is-back" class="hash-link" aria-label="Direct link to Interactive tutorial is back" title="Direct link to Interactive tutorial is back">​</a></h4><p>Upon initiating a new StreamPipes instance, a dialog prompts users to embark on an interactive tutorial showcasing the
platform's key features. We're pleased to announce that this tutorial is now operational again. Enjoy exploring and
discovering the most important functionalities in StreamPipes. Happy learning!</p><img loading="lazy" src="/img/blog/2023-11-28/interactive-tutorial.png" alt="Screenshot of the interactive tutorial" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="deployment">Deployment<a href="#deployment" class="hash-link" aria-label="Direct link to Deployment" title="Direct link to Deployment">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="kubernetes-deployment">Kubernetes Deployment<a href="#kubernetes-deployment" class="hash-link" aria-label="Direct link to Kubernetes Deployment" title="Direct link to Kubernetes Deployment">​</a></h3><h4 class="anchor anchorWithStickyNavbar_LWe7" id="add-probes-to-the-helm-chart">Add probes to the Helm chart<a href="#add-probes-to-the-helm-chart" class="hash-link" aria-label="Direct link to Add probes to the Helm chart" title="Direct link to Add probes to the Helm chart">​</a></h4><p>Integrating readiness, liveness, and startup probes into StreamPipes' Kubernetes containers enhances the system's health
monitoring. These probes automatically detect and handle anomalies, significantly improving application availability and
stability. The readiness probe ensures preparedness, the liveness probe validates ongoing functionality, and the startup
probe assesses initialization status, collectively fortifying StreamPipes against potential disruptions.</p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="rework-the-values-file">Rework the values file<a href="#rework-the-values-file" class="hash-link" aria-label="Direct link to Rework the values file" title="Direct link to Rework the values file">​</a></h4><p>We've refined and simplified the values file for our Helm chart, optimizing its structure. Furthermore, we've invested
in comprehensive documentation for all available options. Check out
the <a href="https://github.com/apache/streampipes/blob/dev/installer/k8s/README.md" target="_blank" rel="noopener noreferrer">README file</a> of our Helm chart for detailed
information on configuration and deployment.</p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="add-apache-pulsar-to-helm-file">Add Apache Pulsar to Helm file<a href="#add-apache-pulsar-to-helm-file" class="hash-link" aria-label="Direct link to Add Apache Pulsar to Helm file" title="Direct link to Add Apache Pulsar to Helm file">​</a></h4><p>In our last release, we've expanded StreamPipes' capabilities to include Apache Pulsar as a supported messaging layer.
Alongside this enhancement, our Helm chart has now been updated to seamlessly deploy StreamPipes on Kubernetes with
Pulsar
as the underlying messaging infrastructure.</p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring-integration-grafana--prometheus">Monitoring Integration (Grafana &amp; Prometheus)<a href="#monitoring-integration-grafana--prometheus" class="hash-link" aria-label="Direct link to Monitoring Integration (Grafana &amp; Prometheus)" title="Direct link to Monitoring Integration (Grafana &amp; Prometheus)">​</a></h4><p>We've now integrated monitoring support for StreamPipes through Prometheus and Grafana, making it seamlessly available
in both our Kubernetes and Docker deployments. If you're using Kubernetes, we recommend checking out
our <a href="https://github.com/apache/streampipes/tree/dev/installer/k8s#monitoring-common-parameters" target="_blank" rel="noopener noreferrer">Helm chart</a> for
straightforward setup instructions. For Docker users, stay tuned for an upcoming blog post where we'll provide a
step-by-step guide on configuring Prometheus and Grafana to monitor StreamPipes effectively.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-deployment-mode-for-first-time-users">New Deployment mode for first time users<a href="#new-deployment-mode-for-first-time-users" class="hash-link" aria-label="Direct link to New Deployment mode for first time users" title="Direct link to New Deployment mode for first time users">​</a></h3><p>To simplify onboarding with Apache StreamPipes and demonstrate its capabilities, we've added a quickstart deployment
option. This docker-compose variant provides users with a pre-configured StreamPipes instance and rich examples. Explore
it in our <a href="/blog/2023/11/28/release-093/&quot;https://streampipes.apache.org/docs/user-guide-for-quickstart/&quot;/">user guide</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-python">StreamPipes Python<a href="#streampipes-python" class="hash-link" aria-label="Direct link to StreamPipes Python" title="Direct link to StreamPipes Python">​</a></h2><p>Our official Python support for Apache StreamPipes got some small improvements as well.
Notable among other improvements are especially the following two:</p><ul><li>Support for Python 3.11</li><li>StreamPipes Python does now also support other protocols than Apache Kafka to interact with live data</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="administration--development">Administration &amp; Development<a href="#administration--development" class="hash-link" aria-label="Direct link to Administration &amp; Development" title="Direct link to Administration &amp; Development">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="email-templates-are-configurable">Email Templates are configurable<a href="#email-templates-are-configurable" class="hash-link" aria-label="Direct link to Email Templates are configurable" title="Direct link to Email Templates are configurable">​</a></h3><p>StreamPipes already supported the sending of notifications, such as those for password recovery and account
registration, when properly configured. However, in previous versions, the email content was predefined and couldn't be
adjusted. In this latest release, administrators now have the flexibility to modify the email templates, offering
greater customization options for notifications.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="remove-legacy-resources">Remove legacy resources<a href="#remove-legacy-resources" class="hash-link" aria-label="Direct link to Remove legacy resources" title="Direct link to Remove legacy resources">​</a></h2><p>In this release, we've eliminated legacy resources that were initially employed for demonstration purposes. As these
resources are no longer actively supported, we have decided to completely remove them. The affected components include
the vehicle simulator and watertank simulator.
This removal has led to the discontinuation of the StreamPipes package <code>streampipes-sources</code>.</p><p>Furthermore, we are pleased to announce the forthcoming removal of Consul as an additional dependency required to run
StreamPipes in the upcoming release. Within this release, we have already implemented the fundamental steps to eliminate
the need for Consul. This marks a significant stride towards making StreamPipes a more lightweight platform. It's
crucial to highlight that this modification is purely a technical enhancement and will have no impact on the end user
experience.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="enable-migrations-for-pipeline-elements">Enable migrations for pipeline elements<a href="#enable-migrations-for-pipeline-elements" class="hash-link" aria-label="Direct link to Enable migrations for pipeline elements" title="Direct link to Enable migrations for pipeline elements">​</a></h2><p>We have established a crucial technical foundation to simplify the update process for upcoming versions of StreamPipes.
It is now possible to define migrations for adapters, data processors, and data sinks. For a more in-depth understanding
of how migrations function and how to define them, please refer to
our <a href="https://streampipes.apache.org/docs/extend-sdk-migration/" target="_blank" rel="noopener noreferrer">documentation</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-homepage">New Homepage<a href="#new-homepage" class="hash-link" aria-label="Direct link to New Homepage" title="Direct link to New Homepage">​</a></h2><p>We've undergone a comprehensive redesign of our website, <a href="https://streampipes.apache.org" target="_blank" rel="noopener noreferrer">streampipes.apache.org</a>. Take
a moment to explore the new look,
and we welcome your feedback on your experience. Let us know what you think!</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="security">Security<a href="#security" class="hash-link" aria-label="Direct link to Security" title="Direct link to Security">​</a></h2><p>We've addressed a vulnerability in the default password generation for new users during the self-registration process.
Previously, a cryptographically weak pseudo-random number generator (PRNG) was utilized, but we've now rectified this by
implementing Apache Commons RNG. We extend our sincere thanks to Alessandro Albani from the Digital Security Division
Var
Group for bringing this to our attention.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="final-remarks">Final Remarks<a href="#final-remarks" class="hash-link" aria-label="Direct link to Final Remarks" title="Direct link to Final Remarks">​</a></h2><p>We highly recommend updating to StreamPipes 0.93.0 to take advantage of these new features, bug fixes, and improvements.
For more detailed information, please refer to
the <a href="https://github.com/apache/incubator-streampipes/blob/release/0.92.0/RELEASE_NOTES.md#0920" target="_blank" rel="noopener noreferrer">release notes</a>.</p><p>We appreciate your continued support and valuable feedback.
StreamPipes is continually evolving, and we are dedicated to providing you with a powerful and reliable platform for
your IIoT streaming data needs.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.92.0]]></title>
            <link>https://streampipes.apache.org/blog/2023/06/16/release-092</link>
            <guid>https://streampipes.apache.org/blog/2023/06/16/release-092</guid>
            <pubDate>Fri, 16 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[8 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>8 minutes to read</strong></div><p></p><p>We are pleased to announce the release of StreamPipes 0.92.0, which includes several bug fixes, performance improvements, and new features.
This version focuses on enhancing the technical aspects of StreamPipes.
Let's explore the key updates in this release:</p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="improved-python-support">Improved Python Support:<a href="#improved-python-support" class="hash-link" aria-label="Direct link to Improved Python Support:" title="Direct link to Improved Python Support:">​</a></h2><p>In response to valuable user feedback, we have improved Python support in StreamPipes.
Users can now seamlessly integrate Python-based scripts, libraries, and modules into their functions.
This enhancement enables leveraging the power of machine learning and advanced analytics algorithms for IIoT data sources.
Please refer to the <a href="https://streampipes.apache.org/docs/docs/python/latest/" target="_blank" rel="noopener noreferrer">Python documentation</a> for further details.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-processing-elements-introducing-the-swinging-door-trending-sdt-filter-processor">New Processing Elements: Introducing the Swinging Door Trending (SDT) Filter Processor:<a href="#new-processing-elements-introducing-the-swinging-door-trending-sdt-filter-processor" class="hash-link" aria-label="Direct link to New Processing Elements: Introducing the Swinging Door Trending (SDT) Filter Processor:" title="Direct link to New Processing Elements: Introducing the Swinging Door Trending (SDT) Filter Processor:">​</a></h2><p>To expand the functionality of StreamPipes, we have introduced several new processing elements.
Among them is the <strong>Swinging Door Trending (SDT) Filter Processor</strong>.
This processor provides a linear trend compression algorithm.
Essentially, it replaces a series of continuous points (timestamp, value) with a straight line determined by the start and end points.</p><img loading="lazy" src="/img/blog/2023-06-16/swinging_door_trending.gif" alt="demonstration how to use the swinging door trending processor" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="bug-fixes-and-improvements">Bug Fixes and Improvements:<a href="#bug-fixes-and-improvements" class="hash-link" aria-label="Direct link to Bug Fixes and Improvements:" title="Direct link to Bug Fixes and Improvements:">​</a></h2><p>We have addressed various bugs and issues reported by our users, resulting in a more stable and reliable StreamPipes experience.
We have also made several performance and usability improvements to enhance overall system efficiency.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="deprecation-of-set-adapters">Deprecation of Set Adapters<a href="#deprecation-of-set-adapters" class="hash-link" aria-label="Direct link to Deprecation of Set Adapters" title="Direct link to Deprecation of Set Adapters">​</a></h2><p>In order to streamline the StreamPipes ecosystem, we have deprecated the functionality of Set Adapters.
Going forward, our focus will solely be on streaming event sources.
However, we understand the importance of working with files of sensor data, especially during development.
To accommodate this need, we have extended the <strong>File Stream Adapter</strong>, which now offers the following functionalities:</p><ol><li>Create a live simulation of sensor data based on the file.</li><li>Replay the data in the file once, for example, to store it in the <strong>Data Lake</strong>.</li></ol><p><strong>IMPORTANT: The set adapters will be removed in the next release.</strong></p><p>From this release onwards, we encourage you to utilize the <strong>File Stream Adapter</strong> instead of the <strong>File Set Adapter</strong>.
To simulate a file set using the <strong>File Stream Adapter</strong>, you can configure it with <code>Replay Once: Yes</code> and <code>Replay Speed: Fastest (Ignore original time)</code>.
See the example below:</p><img loading="lazy" src="/img/blog/2023-06-16/file_stream_set.gif" alt="demonstration how to use file sets with the file stream adapter" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="final-remarks">Final Remarks<a href="#final-remarks" class="hash-link" aria-label="Direct link to Final Remarks" title="Direct link to Final Remarks">​</a></h2><p>We highly recommend updating to StreamPipes 0.92.0 to take advantage of these new features, bug fixes, and improvements.
For more detailed information, please refer to the <a href="https://github.com/apache/incubator-streampipes/blob/release/0.92.0/RELEASE_NOTES.md#0920" target="_blank" rel="noopener noreferrer">release notes</a>.</p><p>We appreciate your continued support and valuable feedback.
StreamPipes is continually evolving, and we are dedicated to providing you with a powerful and reliable platform for your IIoT streaming data needs.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.91.0]]></title>
            <link>https://streampipes.apache.org/blog/2023/04/12/release-091</link>
            <guid>https://streampipes.apache.org/blog/2023/04/12/release-091</guid>
            <pubDate>Wed, 12 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[14 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>14 minutes to read</strong></div><p></p><br><p>The Apache StreamPipes community is delighted to announce the release of Apache StreamPipes version 0.91.0!
The biggest highlight of this release is the birth of our official StreamPipes Python library.
Apart from that, we have made a lot of improvements under the hood, especially in terms of improving the development experience (e.g., by introducing and enforcing code style rules).
Nevertheless, our new version includes more than 90 improvements and bug fixes in total.</p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-python">StreamPipes Python<a href="#streampipes-python" class="hash-link" aria-label="Direct link to StreamPipes Python" title="Direct link to StreamPipes Python">​</a></h2><p><a href="https://streampipes.apache.org/" target="_blank" rel="noopener noreferrer">Apache StreamPipes</a> aims to enable non-technical users to connect and analyze IoT data streams.
To this end, it provides an easy-to-use and convenient user interface that allows one to connect to an IoT data source and create some visual
graphs within a few minutes. <br>
Although this is the main use case of Apache StreamPipes, it can also provide great value for people who are eager to work on data analysis or data science with IoT data, but don't want to get in touch with all the hassle associated with extracting data from devices in a suitable format.
In this scenario, StreamPipes helps you connect to your data source and extract the data for you.
You then can make the data available outside StreamPipes by writing it into an external source, such as a database, Kafka, etc.
While this requires another component, you can also extract your data directly from StreamPipes programmatically using the StreamPipes API.
For convenience, we also provide you with a StreamPipes client both available for Java and Python.
Specifically with StreamPipes Python, we want to address the amazing data analytics and data science community in Python and benefit from the great universe of Python libraries out there.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="getting-started">Getting started<a href="#getting-started" class="hash-link" aria-label="Direct link to Getting started" title="Direct link to Getting started">​</a></h3><p>Besides our official version, which you can access <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>,
we provide Apache StreamPipes as a convenient release via PyPI.
Therefore, you can easily install it via the following command</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">pip </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> streampipes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>All documentation related to StreamPipes Python can be found <a href="https://streampipes.apache.org/docs/docs/python/latest/" target="_blank" rel="noopener noreferrer">here</a>.</p><p>But now enough words are written, let's just start with a few examples.
As a first step, we want to establish a connection to a running StreamPipes instance.</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">client </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> StreamPipesClient</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">config </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> StreamPipesClientConfig</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> streampipes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">credential_provider </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> StreamPipesApiKeyCredentials</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">config </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> StreamPipesClientConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    credential_provider </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> StreamPipesApiKeyCredentials</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        username </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"test@streampipes.apache.org"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        api_key </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"DEMO-KEY"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    host_address </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"localhost"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    https_disabled </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">True</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    port </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">client </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> StreamPipesClient</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">client_config</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">config</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><code>client.describe()</code> gives you an overview about what can be discovered via the Python client:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">Hi there</span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">You are connected to a StreamPipes instance running at http://localhost:80.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">The following StreamPipes resources are available with this client:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1x DataLakeMeasures</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">1x DataStreams</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The required API key can be retrieved from StreamPipes via the UI:</p><img loading="lazy" src="/img/blog/2023-04-12/how-to-get-api-key.gif" alt="demonstration how to get an API key in form of a gif" class="img_ev3q"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="query-data-from-streampipes-data-lake">Query Data from StreamPipes data lake<a href="#query-data-from-streampipes-data-lake" class="hash-link" aria-label="Direct link to Query Data from StreamPipes data lake" title="Direct link to Query Data from StreamPipes data lake">​</a></h3><p>As a first step, we can see which data sets are available in the data lake:</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">dataLakeMeasureApi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token builtin" style="color:rgb(130, 170, 255)">all</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">to_pandas</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>To query data for a specific data lake measure, the following command takes you there:</p><div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">dataLakeMeasureApi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">identifier</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"flow-rate"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">to_pandas</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>There are some parameters that allow you to query data more specifically, visit the <a href="https://streampipes.apache.org/docs/docs/python/latest/reference/endpoint/api/data_lake_measure/#streampipes.endpoint.api.data_lake_measure.MeasurementGetQueryConfig" target="_blank" rel="noopener noreferrer">docs</a> for more detailed information.</p><p>If you are curious which features are available for StreamPipes Python, have a look at our <a href="https://streampipes.apache.org/docs/docs/python/latest/tutorials/1-introduction-to-streampipes-python-client/" target="_blank" rel="noopener noreferrer">tutorial section</a>.</p><p>We plan to further extend the Python library in the next releases - we welcome your ideas on any features you'd like to see!</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="create-adapter-without-starting">Create Adapter without starting<a href="#create-adapter-without-starting" class="hash-link" aria-label="Direct link to Create Adapter without starting" title="Direct link to Create Adapter without starting">​</a></h2><p>Until now, when creating an adapter in StreamPipes, the adapter was started immediately after completion.
From now on you can choose via the adapter overview in the last dialog whether the adapter should be started immediately or later (this is then possible in the adapter overview).</p><img loading="lazy" src="/img/blog/2023-04-12/adapter-running.gif" alt="demonstration how to disable automatic start of an adapter in form of a gif" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="redirect-after-login">Redirect after Login<a href="#redirect-after-login" class="hash-link" aria-label="Direct link to Redirect after Login" title="Direct link to Redirect after Login">​</a></h2><p>This is another small user interface improvement: when a user opens a StreamPipes link even though they are not logged in, e.g.,
<a href="http://streampipes.demo/#/connect" target="_blank" rel="noopener noreferrer">http://streampipes.demo/#/connect</a>, StreamPipes displays the login dialog and now redirects the user directly to the target view
(in this case the connection overview).</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="support-output-streams-for-standalone-functions">Support Output Streams for Standalone Functions<a href="#support-output-streams-for-standalone-functions" class="hash-link" aria-label="Direct link to Support Output Streams for Standalone Functions" title="Direct link to Support Output Streams for Standalone Functions">​</a></h2><p>Within the last release, <a href="/blog/2023/01/17/release-090.html/">0.90.0</a>, we introduced StreamPipes Functions as a lightweight alternative to processing elements.<br>
<!-- -->StreamPipes Functions do now support having output streams, which means that they allow not only to consume but to send data to StreamPipes as well.</p><p>Below you can see a simple example function that demonstrates how events can be pushed back to StreamPipes again.</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionPublishExample</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">StreamPipesFunction</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">final</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Logger</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">LOG</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">LoggerFactory</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getLogger</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionPublishExample</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token keyword" style="font-style:italic">class</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">final</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">FUNCTION_ID</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"org.apache.streampipes.example.function.publish"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">final</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">STREAM_APP_ID</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"example-output-stream-1"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">private</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SpOutputCollector</span><span class="token plain"> outputCollector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">List</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generics class-name" style="color:rgb(255, 203, 107)">String</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">requiredStreamIds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">List</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">of</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"urn:streampipes.apache.org:eventstream:EtMUkN"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStarted</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token constant" style="color:rgb(130, 170, 255)">LOG</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">info</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"Service started"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">this</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">outputCollector </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getOutputCollectors</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token constant" style="color:rgb(130, 170, 255)">STREAM_APP_ID</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onEvent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Event</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token plain"> streamId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token constant" style="color:rgb(130, 170, 255)">LOG</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">info</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"on event"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">var</span><span class="token plain"> ev </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    ev</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">addField</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"timestamp"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">System</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">currentTimeMillis</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    ev</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">addField</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"example-property"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"abc"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">this</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">outputCollector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">collect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">ev</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStopped</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token constant" style="color:rgb(130, 170, 255)">LOG</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">info</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"service stopped"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionConfig</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getFunctionConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionConfigBuilder</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">create</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">from</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token constant" style="color:rgb(130, 170, 255)">FUNCTION_ID</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">withOutputStream</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">DataStreamBuilder</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">create</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token constant" style="color:rgb(130, 170, 255)">STREAM_APP_ID</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"My Function Stream"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">""</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">property</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">EpProperties</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">timestampProperty</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"timestamp"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">property</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">EpProperties</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">stringEp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token class-name" style="color:rgb(255, 203, 107)">Labels</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">from</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"my-example-property"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"test"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"test"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token string" style="color:rgb(195, 232, 141)">"example-property"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token constant" style="color:rgb(130, 170, 255)">SO</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token constant" style="color:rgb(130, 170, 255)">TEXT</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">                </span><span class="token class-name" style="color:rgb(255, 203, 107)">PropertyScope</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token constant" style="color:rgb(130, 170, 255)">MEASUREMENT_PROPERTY</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">format</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Formats</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">jsonFormat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">protocol</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Protocols</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">kafka</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"localhost"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">9094</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">STREAM_APP_ID</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">build</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">build</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This functionality is also already supported in StreamPipes Python! 🚀</p><p>This means that you can write a StreamPipes function in Python that allows you to consume streams of data from StreamPipes,
perform any data manipulation in Python, and send the data back to StreamPipes, where it can be further processed.</p><br>To get a comprehensive overview of all changes released within Apache StreamPipes 0.91.0 please visit our [release notes](https://github.com/apache/incubator-streampipes/blob/release/0.91.0/RELEASE_NOTES.md#0910).]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.90.0]]></title>
            <link>https://streampipes.apache.org/blog/2023/01/17/release-090</link>
            <guid>https://streampipes.apache.org/blog/2023/01/17/release-090</guid>
            <pubDate>Tue, 17 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>5 minutes to read</strong></div><p></p><br><p>The Apache StreamPipes community is pleased to announce the immediate availability of Apache StreamPipes version 0.90.0!
In total, this release was focused on stabilization and closes 57 issues with improvements and bug fixes as well as some new features such as adapters and data sinks. </p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="improvements">Improvements<a href="#improvements" class="hash-link" aria-label="Direct link to Improvements" title="Direct link to Improvements">​</a></h2><p>The focus of this release cycle was on general usability improvements and bug fixes. We continued to harmonize the
StreamPipes web interface, so that all views follow a similar navigation. Many improvements were added to the data explorer:</p><ul><li>Incomplete events with missing values are now displayed in the data explorer</li><li>Improvements to the time selector and edit mode</li><li>More configuration options for data download</li><li>Improved overall data explorer performance</li></ul><p>In addition, we improved features to monitor pipelines and extensions services. The pipeline monitoring component has been restructured and now works independent from the underlying message broker.
In addition, we extended the SDK so that runtime errors can be forwarded to the StreamPipes UI.
Further improvements to the monitoring stack will be added in the next versions.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-adapters-and-data-sinks">New Adapters and Data Sinks<a href="#new-adapters-and-data-sinks" class="hash-link" aria-label="Direct link to New Adapters and Data Sinks" title="Direct link to New Adapters and Data Sinks">​</a></h2><p>This version improves support for existing message brokers in form of adapters and sinks:</p><ul><li>Improvements of the <code>Apache Pulsar</code> (which is also available as a data sink)</li><li>A new adapter and data sink for <code>Apache RocketMQ</code></li><li>A new adapter for <code>NATS</code> (also available as a data sink)</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="github-community-features">GitHub Community Features<a href="#github-community-features" class="hash-link" aria-label="Direct link to GitHub Community Features" title="Direct link to GitHub Community Features">​</a></h2><p>Apache StreamPipes is a community effort - everyone is welcome not only to contribute code, but also to provide feedback and other input which helps improving the product.
To improve community interaction, we switched our issue management from Jira to GitHub issues - making it much easier to create issues and to discuss future features.
In addition, we've enabled Github Discussions - feel free to participate in the existing discussions and ask questions if you have problems!</p><ul><li><a href="https://github.com/apache/streampipes/issues" target="_blank" rel="noopener noreferrer">GitHub Issues</a></li><li><a href="https://github.com/apache/streampipes/discussions" target="_blank" rel="noopener noreferrer">GitHub Discussions</a></li></ul><p>And if you prefer the mailing list, subscribe to <a href="mailto:dev-subscribe@streampipes.apache.org" target="_blank" rel="noopener noreferrer">dev@streampipes.apache.org</a> or <a href="mailto:users-subscribe@streampipes.apache.org" target="_blank" rel="noopener noreferrer">users@streampipes.apache.org</a>.
Tech-related and general project discussions as well as release votes will continue to happen on the dev list.</p><img loading="lazy" src="/img/blog/2023-01-17/github-discussions.png" alt="Github Discussions overview" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="preview-of-standalone-functions">Preview of Standalone Functions<a href="#preview-of-standalone-functions" class="hash-link" aria-label="Direct link to Preview of Standalone Functions" title="Direct link to Preview of Standalone Functions">​</a></h2><p>An exciting new feature is available in preview mode: StreamPipes Functions are a new way to interact with connected data streams in StreamPipes.
As an open system, there are already several ways to extend the functionality of StreamPipes: New adapter can be added to connect to non-supported systems.
In addition, the SDK supports building custom data processors and sinks, so that StreamPipes can be easily extended at runtime in case new analytics operators are needed.</p><p>But providing extensions in form of pipeline elements are not always the best choice: E.g., in cases where non-generic algorithms should be executed on a specific data stream,
providing a reusable component for pipeline development is unsuitable.</p><p>This is where Functions come into play! StreamPipes Functions allow to define standalone components, which consume one or more connected data streams from StreamPipes and can be used to add custom processing logic.
E.g., it becomes easy to apply an ML model on continuous data without the need to build a specific data processing pipeline.</p><p>Functions can be registered in an extensions service similar to data processors and sinks by extending a single class:</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">MyFunction</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">StreamPipesFunction</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionId</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getFunctionId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">from</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"my-app-id"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">List</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generics class-name" style="color:rgb(255, 203, 107)">String</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">requiredStreamIds</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">List</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">of</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"my-stream-id"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStarted</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">FunctionContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// called on service startup</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onEvent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Event</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token plain"> streamId</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// called for each incoming event</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onServiceStopped</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// called on service shutdown</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This concept, which will also come for more programming languages besides Java offer new ways for developers to interact with available data in StreamPipes and build custom extensions for IIoT analytics.</p><p>Functions are available in preview mode and their API should therefore be considered unstable.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="future-roadmap">Future Roadmap<a href="#future-roadmap" class="hash-link" aria-label="Direct link to Future Roadmap" title="Direct link to Future Roadmap">​</a></h2><p>After this stabilization release, the next version will most probably bring a major new feature - Python support!
The community is currently working hard to bring the StreamPipes client and functions to the Python world. Stay tuned!</p><br>To get a comprehensive overview of all changes released within Apache StreamPipes 0.90.0 please visit our [release notes](https://github.com/apache/incubator-streampipes/blob/release/0.90.0/RELEASE_NOTES.md#0900).]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.70.0]]></title>
            <link>https://streampipes.apache.org/blog/2022/10/13/release-070</link>
            <guid>https://streampipes.apache.org/blog/2022/10/13/release-070</guid>
            <pubDate>Thu, 13 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[6 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>6 minutes to read</strong></div><p></p><br><p>The Apache StreamPipes (incubating) community is delighted to announce the release of Apache StreamPipes version 0.70.0!
Key highlights of this release include many enhancements to the data explorer for fast exploration of IoT data and
a brand new asset management that allows importing and exporting of StreamPipes resources.
In addition, our new version includes more than 50 improvements and bug fixes.</p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="preview-of-event-schema">Preview of Event Schema<a href="#preview-of-event-schema" class="hash-link" aria-label="Direct link to Preview of Event Schema" title="Direct link to Preview of Event Schema">​</a></h2><p>A very important and inevitable step when connecting to a data source with Apache StreamPipes
is the definition of the event schema. By collecting some sample events, Apache StreamPipes is able to suggest
an event schema that describes the data structure of the incoming events.
Although this works quite well in the vast majority of cases, there is usually a need to modify the proposed
event schema to some degree or add additional fields. So far, a user has gotten little idea of what
the revised data source event schema looks like until the adapter has been created and some data was consumed.
With this release, we have included a before/after comparison of the events while defining the event schema.
This allows to compare the proposed events of Apache StreamPipes (<code>before</code>) with the events after
all the user's changes have been applied (<code>after</code>).
The after view adapts to each interaction of the user.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-10-13/event-schema-preview.png"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="export-and-import-streampipes-resource">Export and Import StreamPipes Resource<a href="#export-and-import-streampipes-resource" class="hash-link" aria-label="Direct link to Export and Import StreamPipes Resource" title="Direct link to Export and Import StreamPipes Resource">​</a></h2><p>With this release we introduce a completely new module called <code>Asset Management</code>.
This can be selected in the menu bar of the modules on the left side as the third last icon and
is marked by a construction icon. This module allows to combine several StreamPipes resources to a so called <code>Asset</code>,
which can be exported and re-imported later. To do this, a new asset must first be created.
Afterwards the asset can be edited and the following detail view allows to link all resources
available in StreamPipes to the asset. After the asset has been finally saved, the asset (inlcuding all resources) can be downloaded
within the configuration module by switching to the <code>Export/Import</code> tab. All existing assets are listed there and
can be selected for download.
The downloaded file can then be re-imported later in the same or another StreamPipes instance at the same place.</p><img loading="lazy" src="/img/blog/2022-10-13/asset-manager.gif" alt="demonstration how to create an asset and download it afterwards in form of a gif" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="download-data-of-configured-query-from-data-lake">Download Data of Configured Query from Data Lake<a href="#download-data-of-configured-query-from-data-lake" class="hash-link" aria-label="Direct link to Download Data of Configured Query from Data Lake" title="Direct link to Download Data of Configured Query from Data Lake">​</a></h2><p>Another new feature is the ability to download or export data from the StreamPipes data lake
defined by a user-defined query. Previously, it was only possible to download all events belonging to a data lake index
from the <code>Data Lake</code> tab of the configuration menu. In addition to this, each widget in the <code>Data Explorer</code>
offers the possibility to download the corresponding data. The underlying query is created from the configuration
of the widget and is also used to create the widget's figure.
The download supports both <code>CSV</code> and <code>JSON</code> format.</p><img loading="lazy" src="/img/blog/2022-10-13/custom-query-download.gif" alt="demonstration how to download the data of a custom data lake query in form of a gif" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="slide-view-in-data-explorer">Slide View in Data Explorer<a href="#slide-view-in-data-explorer" class="hash-link" aria-label="Direct link to Slide View in Data Explorer" title="Direct link to Slide View in Data Explorer">​</a></h2><p>Traditionally, the graphs created in the Data Explorer are displayed in a grid view, where the user can adjust
the arrangement of the figures as well as their height and width.
With this release, another option for displaying the dashboard widgets is available: the slide view.
This view allows to display a single graph in full-screen mode and switch between views using a horizontal menu bar.
When a new <code>Data View</code> is created in the Data Explorer, a choice can be made between <code>grid view</code> and
<code>slide view</code> as the default display mode.
Once a <code>Data View</code> is created, the display mode can be changed by clicking the icon in the upper left corner
right next to the <code>Back</code> button.</p><img loading="lazy" src="/img/blog/2022-10-13/slide-view.gif" alt="demonstration how to use the slide view in the data explorer in form of a gif" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="templates-for-adapter-configuration">Templates for Adapter Configuration<a href="#templates-for-adapter-configuration" class="hash-link" aria-label="Direct link to Templates for Adapter Configuration" title="Direct link to Templates for Adapter Configuration">​</a></h2><p>Similar to the processing elements, it is now possible to create templates for adapter configurations.
This allows you to start from a previously defined set of configuration settings when creating similar adapters.
To create a template for an adapter configuration, start by creating a new adapter and
configuring all the settings that will be part of the template. Before proceeding to the field
configuration (the second step of adapter creation), save the current configuration as a template.
Whenever a new instance of the same adapter is created, the template can be selected from
the drop-down menu that appears. Templates are only available for the same type of adapter (obviously).</p><img loading="lazy" src="/img/blog/2022-10-13/adapter-template.gif" alt="demonstration how to create an adapter template in form of a gif" class="img_ev3q"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="upload-multiple-files-at-once">Upload Multiple Files at Once<a href="#upload-multiple-files-at-once" class="hash-link" aria-label="Direct link to Upload Multiple Files at Once" title="Direct link to Upload Multiple Files at Once">​</a></h2><p>A rather small but very handy improvement is the possibility to upload multiple files at once to StreamPipes.
When you click the <code>UPLOAD NEW FILE</code> button in the <code>File Management</code> module, it is now possible to select
as many files as you want in the file upload dialog.</p><br><p>To get a comprehensive overview of all changes released within Apache StreamPipes 0.70.0
please visit our <a href="https://github.com/apache/incubator-streampipes/blob/release/0.70.0/RELEASE_NOTES.md#0700" target="_blank" rel="noopener noreferrer">release notes</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Factory I/O with StreamPipes]]></title>
            <link>https://streampipes.apache.org/blog/2022/09/05/using-factory.io-with-streampipes</link>
            <guid>https://streampipes.apache.org/blog/2022/09/05/using-factory.io-with-streampipes</guid>
            <pubDate>Mon, 05 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[10 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>10 minutes to read</strong></div><br><p></p><p>This tutorial shows how you can stream sensor data into StreamPipes from a simulation environment (Factory I/O). The
simulation environment is controlled by a "Siemens S7-1200" PLC and shows a conveyor belt which sorts packages by their
height. The tutorial is based on the upcoming version 0.70.0 and teaches you how to load the sensor data, build a
pipeline, preprocess the data and create visualizations.</p><img loading="lazy" class="blog-image" style="max-width:75%" src="/img/blog/2022-09-05/plc.jpg" alt="plc"><br><h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-factory-io">1. Factory I/O<a href="#1-factory-io" class="hash-link" aria-label="Direct link to 1. Factory I/O" title="Direct link to 1. Factory I/O">​</a></h2><a href="https://docs.factoryio.com/" target="_blank" rel="noopener noreferrer">*Factory* I/O</a> is a 3D simulation for virtual factories and is commonly used as a PLC training platform. We will need it to simulate the live data.<ul><li>Set up Factory I/O and make sure that the <a href="https://docs.factoryio.com/tutorials/siemens/sample-s7-1200-1500/" target="_blank" rel="noopener noreferrer"><em>Sorting by Height (Basic)</em></a> simulation works.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/factory.io.png" alt="dataView"><br><h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-adapter">2. Adapter<a href="#2-adapter" class="hash-link" aria-label="Direct link to 2. Adapter" title="Direct link to 2. Adapter">​</a></h2><p>The next step is to connect the PLC to StreamPipes. To achieve this we need to create an adapter.</p><ul><li>Start <a href="https://streampipes.apache.org/docs/docs/user-guide-introduction.html" target="_blank" rel="noopener noreferrer"><em>StreamPipes</em></a>, go to the *
*CONNECT<strong> menu and create a </strong>NEW ADAPTER**.</li><li>Select the <strong>PLC4X S7</strong> adapter, insert the <strong>IP-address</strong> of your PLC and <strong>import the file</strong> with the PLC tags (see
below). Then click <strong>NEXT</strong> on the bottom right.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/adapter1.png" alt="adapter1"><ul><li>If the warning "MISSING TIMESTAMP" appears, press <strong>ADD TIMESTAMP</strong> and then <strong>NEXT</strong>. This warning occurs because
some data sources don't provide a timestamp.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/adapter2.png" alt="adapter2"><ul><li>You can name the adapter "S7_sorting" and select the option <strong>PERSIST EVENTS</strong> to make sure the data is persisted. The
adapter is now ready to <strong>START</strong>. (You can check if the adapter is working by pressing the <strong><code>?</code></strong> symbol in the
connect menu and clicking on <strong>VALUES</strong> to see a live preview).</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/adapter3.png" alt="adapter3"><br><h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-dashboard-for-raw-data">3. Dashboard for raw data<a href="#3-dashboard-for-raw-data" class="hash-link" aria-label="Direct link to 3. Dashboard for raw data" title="Direct link to 3. Dashboard for raw data">​</a></h2><p>A dashboard is used to monitor live data from a data stream. We will use it to make sure that the sensor values are
updated when the simulation runs.</p><ul><li>Go to the <strong>DASHBOARD</strong> menu and create a <strong>NEW DASHBOARD</strong> "Dashboard_sorting". Press the pen symbol to edit the
dashboard.</li><li>Click <strong>ADD VISUALIZATION</strong> and select the automatically created pipeline "Persist S7_sorting". Choose the <strong>TABLE</strong>
widget, configure it by pressing <strong>SELECT ALL</strong> and <strong>CREATE</strong> the widget.</li><li>Change the size of the table as you like and <strong>SAVE</strong> the dashboard.</li><li>The values should now update every 5 seconds. Test it by starting the simulation in Factory I/O.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/dashboard1.png" alt="dashboard1"><br><h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-creating-a-data-view">4. Creating a Data View<a href="#4-creating-a-data-view" class="hash-link" aria-label="Direct link to 4. Creating a Data View" title="Direct link to 4. Creating a Data View">​</a></h2><p>The Data View is used to create visualization for persisted data in a Data Lake. You can choose various visualization to
explore your data. We will create a table to see the stored data and a bar chart to take a closer look at a single
sensor.</p><ul><li>Create a <strong>NEW DATA VIEW</strong> "Sorting" in the <strong>DATA EXPLORER</strong> menu and edit the view.</li><li>Select the "Persist S7_sorting" pipeline at the <strong>NEW WIDGET</strong> menu, <strong>SELECT ALL</strong> fields and press <strong>NEXT</strong>.</li><li>Select the <strong>TABLE</strong> visualization. Click <strong>SELECT ALL</strong> and <strong>CREATE</strong>.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/dataView1.png" alt="dataView1"><ul><li>Now we want to look closer at a single sensor value. Therefore click on the <strong><code>+</code></strong> symbol on the top left to add a
new widget.</li><li>Choose the "Persist S7_sorting" pipeline again, set the <strong>LIMIT</strong> to 1000 and only select the <strong>I_At_right_entry</strong>
field. Now select  <strong>DISTRIBUTION</strong> as visualization and press <strong>CREATE</strong>. This chart shows how often the sensor
returned true or false (package in front of it or not).</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/dataView2.png" alt="dataView2"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="5-modifying-the-pipeline">5. Modifying the Pipeline<a href="#5-modifying-the-pipeline" class="hash-link" aria-label="Direct link to 5. Modifying the Pipeline" title="Direct link to 5. Modifying the Pipeline">​</a></h2><p>The next step is to change the pipeline to add some preproccessing steps. We want to count the number of large packages
which get transported to the right side and we want to measure the time between two arriving packages.</p><ul><li>Therefore <strong>STOP</strong> the running "Persist S7_sorting" pipeline in the <strong>PIPELINE</strong> menu and <strong>MODIFY</strong> the pipeline.</li><li>Add the <strong>BOOLEAN COUNTER</strong> as new pipeline element. Connect the data source to the counter and configure the element.
Select <strong>I_At_right_entry</strong> as boolean field and change the flank parameter to <strong>FALSE -&gt; TRUE</strong>. Then add a <strong>DATA
LAKE</strong> and connect the <strong>BOOLEAN COUNTER</strong> to it. Use "Boolean_Counter" as identifier.</li><li>Add the <strong>BOOLEAN TIMER</strong> to the pipeline and connect the data source to it. Select <strong>I_At_right_entry</strong> as boolean
field too and select <strong>TRUE</strong> and <strong>SECONDS</strong> in the configuration window. Add another <strong>DATA LAKE</strong> and connect the *
*BOOLEAN TIMER** to it. Use "Boolean_Timer" as identifier.</li><li><strong>SAVE</strong> the pipeline and click the checkbox <strong>START PIPELINE IMMEDIATELY</strong>.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/pipeline.png" alt="pipeline"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="6-dashboard-for-preprocessed-data">6. Dashboard for preprocessed data<a href="#6-dashboard-for-preprocessed-data" class="hash-link" aria-label="Direct link to 6. Dashboard for preprocessed data" title="Direct link to 6. Dashboard for preprocessed data">​</a></h2><p>After we created two new data field in the last step, we will monitor them in the dashboard.</p><ul><li>Go to the <strong>DASHBOARD</strong> menu and <strong>EDIT</strong> the dashboard.</li><li>Click <strong>ADD VISUALIZATION</strong> and select "Persist S7_sorting: Boolean_Counter". Create a <strong>TABLE</strong> widget as before and
<strong>SELECT ALL</strong> fields.</li><li>Now add one last table. Choose "Persist S7_sorting: Boolean_Timer" and only select the <strong>measured_time</strong> field</li><li>Test your pipeline by starting the simulation again. The counter should now count up when a package passes the sensor
on the right side and the "measured_time" should show the time since the last package arrived.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/dashboard2.png" alt="dashboard2"><br><h2 class="anchor anchorWithStickyNavbar_LWe7" id="7-final-data-view">7. Final Data View<a href="#7-final-data-view" class="hash-link" aria-label="Direct link to 7. Final Data View" title="Direct link to 7. Final Data View">​</a></h2><p>Finally we want to improve the Data Explorer and create visualizations with the preprocessed data. We will create a time
series to verify when a new package arrived and a heat map to check the time between two packages.</p><ul><li>Go to the <strong>DATA EXPLORER</strong> menu and edit the data view.</li><li>Click <strong>ADD WIDGET</strong> and choose the pipeline "Persist S7_sorting: Boolean_Counter". Select the <strong>counter</strong> field and
choose the <strong>TIME SERIES</strong> visualization.</li><li>Create another widget. Choose the "Persist S7_sorting: BooleanCounter" pipeline and select the <strong>measured_time</strong>
field. Then select the <strong>HEATMAP</strong> and use "measured_time" as <strong>HEAT VALUE</strong></li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-09-05/dataView3.png" alt="dataView3"><br><h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary">​</a></h2><p>In this tutorial we learned how to connect a PLC to StreamPipes, monitor the data stream with a dashboard, create a
pipeline with different preprocessing steps and visualize the data in the Data View. But we just focused on the basics,
so feel free to try out your own ideas and use different preprocessing steps, create new visualizations or try out
another simulation environment.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="csv-file-for-plc-tags">CSV file for PLC tags<a href="#csv-file-for-plc-tags" class="hash-link" aria-label="Direct link to CSV file for PLC tags" title="Direct link to CSV file for PLC tags">​</a></h2><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">Runtime Name,Path,Data Type,Node Name,Comment,Hmi Visible,Hmi Accessible,Hmi Writeable,Typeobject ID,Version ID</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_High_sensor,Tag table_1,Bool,%I0.0,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_Low_sensor,Tag table_1,Bool,%I0.1,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_Pallet_sensor,Tag table_1,Bool,%I0.2,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_Loaded,Tag table_1,Bool,%I0.3,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_At_left_entry,Tag table_1,Bool,%I0.4,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_At_left_exit,Tag table_1,Bool,%I0.5,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_At_right_entry,Tag table_1,Bool,%I0.6,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">I_At_right_exit,Tag table_1,Bool,%I0.7,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">O_Conveyor_entry,Tag table_1,Bool,%Q0.0,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">O_Load,Tag table_1,Bool,%Q0.1,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">O_Unload,Tag table_1,Bool,%Q0.2,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">O_Transf_left,Tag table_1,Bool,%Q0.3,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">O_Tranf_right,Tag table_1,Bool,%Q0.4,,True,True,True,,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">O_Conveyor_left,Tag table_1,Bool,%Q0.5,,True,True,True,,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.69.0]]></title>
            <link>https://streampipes.apache.org/blog/2022/03/21/_release-0690</link>
            <guid>https://streampipes.apache.org/blog/2022/03/21/_release-0690</guid>
            <pubDate>Mon, 21 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>5 minutes to read</strong></div><p></p><br><p>The Apache StreamPipes (incubating) community is pleased to announce Apache StreamPipes version 0.69.0!
The most notable highlights of this release include a completely reworked data explorer for quick exploration of IoT data and advanced user and access rights management.
In addition, our new release includes more than 80 improvements and bug fixes.</p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="data-explorer">Data Explorer<a href="#data-explorer" class="hash-link" aria-label="Direct link to Data Explorer" title="Direct link to Data Explorer">​</a></h2><p>Apache StreamPipes 0.69.0 includes a heavily improved data explorer. The new user interface allows to visually explore data streams within minutes.
Any pipeline which uses the <code>Data Lake</code> sink can be visualized in the data explorer. The completely new query interface allows to easily select date and time ranges and users can choose from either displaying raw data or aggregated time series.
The widget library includes charts to visualize time-series data (e.g., line chart, scatter plots or heatmaps), value distributions (e.g., density or histograms) or single values.
The widget interface is completely customized and users can build rich dashboards.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-03-21/sp-data-explorer-2.png" alt="Data Explorer"><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-03-21/sp-data-explorer-3.png" alt="Data Explorer"><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-03-21/sp-data-explorer-4.png" alt="Data Explorer"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="user-and-access-rights-management">User and access rights management<a href="#user-and-access-rights-management" class="hash-link" aria-label="Direct link to User and access rights management" title="Direct link to User and access rights management">​</a></h2><p>StreamPipes now supports multiple users and roles. The new <code>User management</code> section in the settings page allows to create individual users and groups.
Various roles can be assigned to users and groups to manage permissions and visible views. For instance, you can now create users which only see dashboards, but cannot create pipelines or connect new data streams.
In addition, individual permissions can be assigned to various resource objects such as pipelines, data streams and dashboards. </p><p>Communication between extensions services and the core are now authenticated by default. Service accounts can be created to allow extensions services to access StreamPipes resources.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-03-21/sp-user-management-2.png" alt="User Management"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="improved-pipeline-element-modeling">Improved pipeline element modeling<a href="#improved-pipeline-element-modeling" class="hash-link" aria-label="Direct link to Improved pipeline element modeling" title="Direct link to Improved pipeline element modeling">​</a></h2><p>We've removed one of the major drawbacks of previous StreamPipes versions: Pipelines can now be flexibly reconfigured. In previous versions, due to the validation of pipelines and their configuration, only root elements could be modified.
The new version now gives users full flexibility when modeling pipelines (e.g., by removing or modifying elements from the middle of a pipeline), while pipelines are still continuously validated and modeling errors are shown.
Updating pipelines should now be much less distracting and faster.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-new-features">Other new features<a href="#other-new-features" class="hash-link" aria-label="Direct link to Other new features" title="Direct link to Other new features">​</a></h2><h3 class="anchor anchorWithStickyNavbar_LWe7" id="mail-configuration">Mail configuration<a href="#mail-configuration" class="hash-link" aria-label="Direct link to Mail configuration" title="Direct link to Mail configuration">​</a></h3><p>StreamPipes now includes a configuration interface for mail server settings. These settings are used by the email data sink used to trigger email notifications.
In addition, several system-wide mail services exist, e.g., to restore forgotten passwords.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-03-21/sp-config-mail.png" alt="Mail configuration"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="login-configuration">Login configuration<a href="#login-configuration" class="hash-link" aria-label="Direct link to Login configuration" title="Direct link to Login configuration">​</a></h3><p>The login mechanism can now be configured directly in the user interface. A self-registration can be activated to allow users to create new accounts.
In addition, passwords can be restored by using a two-stage email confirmation process. The profile view allows users to change their passwords individually.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="redesign-of-pipeline-editor">Redesign of pipeline editor<a href="#redesign-of-pipeline-editor" class="hash-link" aria-label="Direct link to Redesign of pipeline editor" title="Direct link to Redesign of pipeline editor">​</a></h3><p>The pipeline editor has a new look: The pipeline element selection bar has been moved from the top to the left side. The icons are smaller and for each pipeline element, the name and description are shown by default.
This makes it easier to find the elements you're looking for.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-03-21/sp-pipeline-editor.png" alt="Dark mode"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="improved-service-discovery">Improved service discovery<a href="#improved-service-discovery" class="hash-link" aria-label="Direct link to Improved service discovery" title="Direct link to Improved service discovery">​</a></h3><p>Under the hood, we've improved the discovery of extensions services. This is part of a larger effort which will be further improved in the next versions.
Extensions services now automatically register within the core depending on the IP address of the service. Pipeline element descriptions are now free of the hostname and can be easily updated.
Several environment variables exist to manually assign the hostname to an extensions service.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="performance">Performance<a href="#performance" class="hash-link" aria-label="Direct link to Performance" title="Direct link to Performance">​</a></h3><p>We've improved the overall system performance by replacing the triple store with a standard NoSQL database. This leads to huge performance improvements in terms of system start time, pipeline element installation and overall loading time.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="dark-mode--">Dark mode ;-)<a href="#dark-mode--" class="hash-link" aria-label="Direct link to Dark mode ;-)" title="Direct link to Dark mode ;-)">​</a></h3><p>We know that you wanted this: An experimental dark mode has been added to StreamPipes. The color scheme can be flexibly changed in the profile view and is stored for each user.
The dark mode should be considered experimental, so please expect some layout flaws.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2022-03-21/sp-dark-mode.png" alt="Dark mode"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="migration">Migration<a href="#migration" class="hash-link" aria-label="Direct link to Migration" title="Direct link to Migration">​</a></h2><p>While we are not yet ready for automatic migration, a migration guide explains several new concepts introduced in this StreamPipes version.
We aim at providing a backwards compatible version with release 1.0, planned for later this year.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.68.0]]></title>
            <link>https://streampipes.apache.org/blog/2021/07/22/_release-0680</link>
            <guid>https://streampipes.apache.org/blog/2021/07/22/_release-0680</guid>
            <pubDate>Thu, 22 Jul 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[8 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>8 minutes to read</strong></div><p></p><br><p>The Apache StreamPipes (incubating) community is pleased to announce Apache StreamPipes version 0.68.0!
The latest release brings many improvements related to health management of pipelines and pipeline monitoring, improved user guidance such as a live preview in the pipeline editor and better handling of pipeline updates as well as several new data processors and sinks such as support for NATS.
In addition, the release contains several bug fixes related to K8s deployment, PLC adapters and pipeline management.</p><p>The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="user-interface">User interface<a href="#user-interface" class="hash-link" aria-label="Direct link to User interface" title="Direct link to User interface">​</a></h2><p>The user interface brings several improvements for users when working with pipelines.
For this release, we focused on providing a better user experience when pipelines and associated dashboard widgets are updated.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-preview">Pipeline preview<a href="#pipeline-preview" class="hash-link" aria-label="Direct link to Pipeline preview" title="Direct link to Pipeline preview">​</a></h3><p>A new pipeline preview allows to quickly inspect the output of data streams and processors during pipeline development.
The preview can be enabled in the pipeline canvas and displays the latest value of each pipeline element every second.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2021-07-22/pipeline-preview.png" alt="Pipeline preview"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="editable-dashboard-widgets">Editable dashboard widgets<a href="#editable-dashboard-widgets" class="hash-link" aria-label="Direct link to Editable dashboard widgets" title="Direct link to Editable dashboard widgets">​</a></h3><p>Apache StreamPipes 0.68.0 improves the modification of existing dashboard widgets. In the live dashboard, the visualization type and the underlying pipeline can now easily be changed without recreating a widget.
In addition, the dashboard shows additional error messages and hints in case pipelines are stopped or have been deleted. In the first case, pipelines can be conveniently started directly from the dashboard.</p><p>Besides that, the dashboard now provides more visualization types (e.g., bar race chart, status light and word cloud) based on <a href="https://echarts.apache.org" target="_blank" rel="noopener noreferrer">Apache ECharts</a>.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2021-07-22/edit-visualizations.png" alt="Modify existing dashboard visualizations"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="monitoring--resilience">Monitoring &amp; Resilience<a href="#monitoring--resilience" class="hash-link" aria-label="Direct link to Monitoring &amp; Resilience" title="Direct link to Monitoring &amp; Resilience">​</a></h2><p>The latest version comes with several improvements related to better monitoring of running pipelines and internal health checking.
To allow users to inspect currently running pipelines, a new pipeline monitoring module has been added to the user interface which shows the current throughput of each pipeline element.
Individual pipeline elements can be selected in the preview panel. For each pipeline element, the number of processed input events, produced output events and the lag is displayed.
The displayed numbers may be slightly inaccurate for higher throughputs, but give an estimate whether the pipeline is running smoothly or lagging behind.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2021-07-22/pipeline-monitoring.png" alt="Pipeline Monitoring"><p>Besides monitoring, StreamPipes 0.68.0 brings many improvements in terms of system resilience. Pipelines are now gracefully stopped once the StreamPipes installation is stopped.
Running pipelines are flagged and restarted at startup time. In addition, StreamPipes checks at every startup for any pipelines that were not properly stopped and restarts these pipelines accordingly.
For all running pipelines, StreamPipes now regularly checks the state of all involved pipeline elements and detects any failures. Problems are displayed in the UI and pipeline elements are automatically re-invoked once they become available after a failure. </p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2021-07-22/pipeline-failed.png" alt="Awareness of pipeline failures in the UI"><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2021-07-22/pipeline-restored.png" alt="Recovery of failed pipeline elements"><p>Altogether, Apache StreamPipes is now able to recover and resume its state even when the power plug is pulled!
Resiliency is part of an ongoing larger community effort and will be further improved with a new service discovery approach that will be part of the upcoming version 0.69.0.</p><p>The Docker Compose-based installation now restarts StreamPipes automatically after a system restart by default.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-client">StreamPipes Client<a href="#streampipes-client" class="hash-link" aria-label="Direct link to StreamPipes Client" title="Direct link to StreamPipes Client">​</a></h2><p>To allow third-party applications to access concepts managed by Apache StreamPipes, version 0.68.0 brings a preview of the StreamPipes client and REST API.
The public REST API and the client expose several features that were previously only internally available to developers, such as reading pipelines, performing operations on pipelines and subscribing to data sources managed by StreamPipes.
An API token can be easily generated in the profile section of the user interface.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2021-07-22/api-key-generation.png" alt="Generating an API key for the StreamPipes client &amp; REST API"><p>Currently provided REST interfaces can be seen in the Swagger documentation, which is linked on the login page.
The client is provided as a Java library, an example of its usage is provided in our <a href="https://github.com/apache/incubator-streampipes-examples/blob/dev/streampipes-pipeline-elements-examples-processors-jvm/src/main/java/org/apache/streampipes/client/example/StreamPipesClientExample.java" target="_blank" rel="noopener noreferrer">Examples Github repository</a></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-extensions">StreamPipes Extensions<a href="#streampipes-extensions" class="hash-link" aria-label="Direct link to StreamPipes Extensions" title="Direct link to StreamPipes Extensions">​</a></h2><p>We also added several new adapters to connect data sources and pipeline elements:</p><ul><li>A new NATS sink allows to forward events to a NATS broker</li><li>The PLC adapter now makes use of the PooledPLCDriverManager</li><li>Improvements to the MQTT sink</li><li>The IoTDB adapter now uses the latest IoTDB version</li><li>All SQL-based sinks now share a common and more stable codebase</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-features-and-improvements">Other features and improvements<a href="#other-features-and-improvements" class="hash-link" aria-label="Direct link to Other features and improvements" title="Direct link to Other features and improvements">​</a></h2><ul><li>The connect-master module has been removed and integrated into the core</li><li>Library upgrades to Angular (11), Spring Boot, and others</li><li>Improvements to the helm chart for K8s deployment</li></ul><p>See the <a href="https://issues.apache.org/jira/projects/STREAMPIPES/versions/12348698" target="_blank" rel="noopener noreferrer">release notes</a> for a complete list of new features and improvements.</p><h1>Upgrading</h1><p>StreamPipes 0.68.0 is an intermediate release towards a stable version 1.0. Under the hood, we are performing several code migrations to further improve the overall stability and performance of StreamPipes.
Therefore, we currently recommend to start with a clean installation when upgrading. We are working towards an auto-update feature which will be available later this year.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:users@streampipes.apache.org" target="_blank" rel="noopener noreferrer">mail</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p><p>And do not forget to subscribe to our new mailing lists: <a href="https://streampipes.apache.org/mailinglists.html" target="_blank" rel="noopener noreferrer">https://streampipes.apache.org/mailinglists.html</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Running StreamPipes the Kubernetes-Way using k3s]]></title>
            <link>https://streampipes.apache.org/blog/2020/05/27/streampipes_on_k3s</link>
            <guid>https://streampipes.apache.org/blog/2020/05/27/streampipes_on_k3s</guid>
            <pubDate>Wed, 27 May 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[15 minutes to read]]></description>
            <content:encoded><![CDATA[<img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-05-27/streampipes_k3s.png" alt="StreamPipes on k3s">**<div style="float:left;padding-right:40px">15 minutes to read</div>**<br><p>This blog post is the second part of a series on how we want to bring StreamPipes closer to the edge. The <a href="/blog/2020/01/23/streampipes_on_rpi/">first part</a> describes how we managed to build and deploy StreamPipes on one Raspberry Pi (Model 4), while the <a href="/blog/2020/05/27/streampipes_on_k3s/">second part</a> further covers how to deploy StreamPipes over a Kubernetes cluster of two Raspberry Pi's via k3s using our StreamPipes helm chart.</p><p><strong>&lt;TL;DR&gt;</strong></p><p><strong>With new advancements that came in the last StreamPipes release, we managed to reduce the required resources (mainly memory) drastically. To this extent, we cross-compiled StreamPipes Docker images for ARM support and deployed our lite version on a Raspberry Pi (Model 4). We showcase, that it is feasible to run analytical pipelines with ease and operate StreamPipes at moderate load. Additionally, we demonstrate how to deploy StreamPipes over a two-node k3s cluster using our StreamPipes helm chart.</strong></p><img loading="lazy" class="blog-image" style="max-width:80%" src="/img/blog/2020-05-27/k3s.png" alt="K3s"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2><p>While it is easy to get started with StreamPipes in no time using our single-node deployment <a href="/docs/docs/user-guide-installation/">instructions</a> using Docker and Docker-Compose, StreamPipes naturally is designed to run in a distributed cluster setup through its microservice architecture.</p><p>This architectural design paired with the advancements of multi-architecture StreamPipes images as described in the previous blog post allows us to run certain analytical pipeline element containers with ease on various target nodes as well as target hardware architecture wether it is X86, ARM32v7, or ARM64v8. This becomes more valuable, as we shift the focus away from centralized cloud or data center only deployments where we generally are provided with a homogenous compute landscape in terms of resources towards edge deployments that oftentimes envolve resource-limited, constrained devices that not only differ in terms of compute but also in terms of their chip architecture.</p><p>Thereby, having multi-architecture images in your repertoire is key to deal with the challenge of heterogeneity in compute resources along the edge-cloud continuum. However, there are other challenges that occur when dealing with distributed container deployments such as automating deployments itself, scaling them, managing the containerized applications, taking care of networking between services, or realizing fault-tolerance by comparing the desired state against the current one. If there wasn't some solution we could leverage that takes care of all of this.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="well-which-k-to-use-kubernetes-k3s">Well, which K to use? Kubernetes, K3s<a href="#well-which-k-to-use-kubernetes-k3s" class="hash-link" aria-label="Direct link to Well, which K to use? Kubernetes, K3s" title="Direct link to Well, which K to use? Kubernetes, K3s">​</a></h2><p>Fortunately, there exists a few solutions in the container ecosystem with the open source container orchestrator <a href="https://kubernetes.io" target="_blank" rel="noopener noreferrer">Kubernetes</a> (K8s) being the defacto standard, thereby incorporating the best ideas of Google's internal large-scale container cluster management system <a href="https://kubernetes.io/blog/2015/04/borg-predecessor-to-kubernetes/" target="_blank" rel="noopener noreferrer">Borg</a> (see academic paper about the details published at <a href="https://research.google/pubs/pub43438/" target="_blank" rel="noopener noreferrer">EuroSys 2015</a>). Since we are not going to write "yet another K8s basics blog post", we refer to their docs or other awesome blog posts such as the <a href="https://medium.com/google-cloud/kubernetes-101-pods-nodes-containers-and-clusters-c1509e409e16" target="_blank" rel="noopener noreferrer">Kubernetes 101</a> to get familiarized with the concepts and terminology. With all the power, concepts and terminology K8s provides, it is oftentimes hard for newcomers to get started. Additionally, not all use cases necessarily need these extra features that K8s adds.</p><p>On the other hand, there exists <a href="https://k3s.io/" target="_blank" rel="noopener noreferrer">K3s</a>, a lightweight Kubernetes distro by Rancher that was introduced early 2019 and has since then gained huge popularity. As it is stated on their website:</p><ul><li><strong>Perfect for Edge</strong>: <em>K3s is a highly available, certified Kubernetes distribution designed for production workloads in unattended, resource-constrained, remote locations or inside IoT appliances</em></li><li><strong>Simplified &amp; Secure</strong>: <em>K3s is packaged as a single &lt;40MB binary that reduces the dependencies and steps needed to install, run and auto-update a production Kubernetes cluster.</em></li><li><strong>Optimized for ARM</strong>: <em>Both ARM64 and ARMv7 are supported with binaries and multiarch images available for both. K3s works great from something as small as a Raspberry Pi to an AWS a1.4xlarge 32GiB server.</em></li></ul><p>Thus, this lead us to the point to say, hey why not use K3s to manage StreamPipes in all its glory. The containerized microservice design in addition to the newly available multiarch images are a great fit.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-helm-chart">StreamPipes Helm Chart<a href="#streampipes-helm-chart" class="hash-link" aria-label="Direct link to StreamPipes Helm Chart" title="Direct link to StreamPipes Helm Chart">​</a></h2><p>While you can easily write an deploy K8s YAML-based manifests for your deployments and services and so on the standard way, it is way more convenient to leverage  <a href="https://helm.sh/" target="_blank" rel="noopener noreferrer">Helm</a>, the package manager for K8s. Helm describes complex, distributed deployments using <strong>charts</strong> in order to provide repeatable application installation, easy updates, rollbacks etc.</p><p>To this extent, we wrote a Helm chart for StreamPipes that can be found on our Github <a href="https://github.com/apache/incubator-streampipes-installer/tree/dev/helm-chart" target="_blank" rel="noopener noreferrer">incubator-streampipes-installer</a> repository. This allows to deploy StreamPipes as one liner as shown later. Helm charts follow a certain directory structure as depicted in the following:</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">helm-chart/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  Chart.yaml</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  values.yaml</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  templates/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  ...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The <code>Chart.yaml</code> file contains a description of the chart, e.g., metadata such as chart name, version, maintainers etc.</p><p>The <code>values.yaml</code> file contains default values for all charts and in our case serves the purpose to provide a central place to store all variable/values, e.g., <code>streampipes.registry: "apachestreampipes"</code>, that replace chart templates such as the registry and version of the StreamPipes backend image:</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> .Values.streampipes.registry </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/backend</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> .Values.streampipes.version </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Lastly, the <code>template/</code> directory is for template files. When Helm evaluates a chart, it sends all of the files in this directory through the template rendering engine before collecting the results and finally forwarding them to K8s. If interested, you can read more on this in the <a href="https://helm.sh/docs/" target="_blank" rel="noopener noreferrer">official Helm documentation</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-almighty-streampi-k3s-cluster">The almighty StreamPi K3s Cluster<a href="#the-almighty-streampi-k3s-cluster" class="hash-link" aria-label="Direct link to The almighty StreamPi K3s Cluster" title="Direct link to The almighty StreamPi K3s Cluster">​</a></h2><p>As pointed out in the first part of the series, we have gained valueable insights on how to run and deploy StreamPipes on a Raspberry Pi. This worked out so greatly, that we thought, why not step up the game, use another Pi and built the <strong>almighty StreamPi cluster</strong> by leveraging K3s for orchestration and management.</p><p><strong>Note</strong>: We are aware that this is far off from a production-grade setup, especially running StreamPipes core services such as the central pipeline management backend, or the UI in a two-node cluster. However, it provides a solid starting point for more elaborate deployments along the edge-cloud continuum.</p><p>As shown in the following figure, starting from the multiarch images hosted on <a href="https://hub.docker.com/search?q=apachestreampipes&amp;type=image" target="_blank" rel="noopener noreferrer">Dockerhub</a>, we first provisioned the two Pi's with Docker, install and setup K3s and finally deploy our StreamPipes helm chart in order for users to connect, analyze and exploit their IIoT data with StreamPipes.</p><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-05-27/deployment.png" alt="Deployment"><p>In the remainder, we cover how we installed Helm and K3s to form our almighty StreamPi K3s cluster. At the time of writing, we tested our deployment using the latest version of the Docker, Helm as well as K3s in the following setup</p><ul><li>2x Raspberry Pi Model 4 (4GiB RAM): <code>streampi-01</code>, <code>streampi-02</code></li><li>Raspbian Buster 10</li><li>Docker 19.03.8</li><li>Helm 3.1.2</li><li>K3s v1.17.4+k3s1</li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-install-docker">1. Install Docker<a href="#1-install-docker" class="hash-link" aria-label="Direct link to 1. Install Docker" title="Direct link to 1. Install Docker">​</a></h3><p>SSH into your Raspberry Pi's and run the following command:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">curl</span><span class="token plain"> -sSL https://get.docker.com </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">sh</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-install-k3s">2. Install K3s<a href="#2-install-k3s" class="hash-link" aria-label="Direct link to 2. Install K3s" title="Direct link to 2. Install K3s">​</a></h3><p>Now that we got Helm installed, we can proceed and install K3s. Thus, we must check wether we fulfill all the requirements. These are mainly network related, such that specific ports (server on <code>6443</code>) are accessible. You should carefully read about this in their <a href="https://rancher.com/docs/k3s/latest/en/installation/installation-requirements/" target="_blank" rel="noopener noreferrer">official documentation</a>.</p><p>Other than that, lean back and enjoy - the installation happens so fast, you might miss it if you get a coffee :)</p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="ssh-into-k3s-server-streampi-01">SSH into K3s server (<code>streampi-01</code>)<a href="#ssh-into-k3s-server-streampi-01" class="hash-link" aria-label="Direct link to ssh-into-k3s-server-streampi-01" title="Direct link to ssh-into-k3s-server-streampi-01">​</a></h4><p>On the server node, run the following command:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">curl</span><span class="token plain"> -sfL https://get.k3s.io </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">sh</span><span class="token plain"> -</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>A kubeconfig file is written to <code>/etc/rancher/k3s/k3s.yaml</code> and the service is automatically started or restarted. The install script will install k3s and additional utilities, such as <code>kubectl</code>, <code>crictl</code>, <code>k3s-killall.sh</code>, and <code>k3s-uninstall.sh</code>.</p><p>The K3s installer creates a systemd service which can be used to <code>stop</code>, <code>start</code>, <code>restart</code> and check the <code>status</code> of the K3s server.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> systemctl status k3s.service</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">● k3s.service - Lightweight Kubernetes</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   Loaded: loaded </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">/etc/systemd/system/k3s.service</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> vendor preset: enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   Active: active </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">running</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> since Sat </span><span class="token number" style="color:rgb(247, 140, 108)">2020</span><span class="token plain">-04-11 </span><span class="token number" style="color:rgb(247, 140, 108)">15</span><span class="token plain">:54:07 BST</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token plain"> days ago</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">     Docs: https://k3s.io</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  Process: </span><span class="token number" style="color:rgb(247, 140, 108)">10193</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">ExecStartPre</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">/sbin/modprobe br_netfilter </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">code</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">exited, </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">status</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain">/SUCCESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  Process: </span><span class="token number" style="color:rgb(247, 140, 108)">10194</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">ExecStartPre</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">/sbin/modprobe overlay </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">code</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">exited, </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">status</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain">/SUCCESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> Main PID: </span><span class="token number" style="color:rgb(247, 140, 108)">10195</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">k3s-server</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Next, copy the server node token in order to connect additional agent nodes to the cluster.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">cat</span><span class="token plain"> /var/lib/rancher/k3s/server/node-token</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h4 class="anchor anchorWithStickyNavbar_LWe7" id="ssh-into-k3s-agent-streampi-02">SSH into K3s agent (<code>streampi-02</code>)<a href="#ssh-into-k3s-agent-streampi-02" class="hash-link" aria-label="Direct link to ssh-into-k3s-agent-streampi-02" title="Direct link to ssh-into-k3s-agent-streampi-02">​</a></h4><p>Now, open a new terminal session and SSH into your agent and run the following command, thereby adding the copied <code>K3S_TOKEN</code> to connect to the server, that is specified using <code>K3S_URL</code>.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">curl</span><span class="token plain"> -sfL https://get.k3s.io </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">K3S_URL</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">https://streampi-01:6443 </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">K3S_TOKEN</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">NODE_TOKEN</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">sh</span><span class="token plain"> -</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The K3s installer creates a systemd service which can be used to <code>stop</code>, <code>start</code>, <code>restart</code> and check the <code>status</code> of the K3s agent.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> systemctl status k3s-agent.service</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">● k3s-agent.service - Lightweight Kubernetes</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   Loaded: loaded </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">/etc/systemd/system/k3s-agent.service</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> vendor preset: enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   Active: active </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">running</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> since Sat </span><span class="token number" style="color:rgb(247, 140, 108)">2020</span><span class="token plain">-04-11 </span><span class="token number" style="color:rgb(247, 140, 108)">16</span><span class="token plain">:05:37 BST</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token plain"> days ago</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">     Docs: https://k3s.io</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  Process: </span><span class="token number" style="color:rgb(247, 140, 108)">24469</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">ExecStartPre</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">/sbin/modprobe br_netfilter </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">code</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">exited, </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">status</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain">/SUCCESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  Process: </span><span class="token number" style="color:rgb(247, 140, 108)">24470</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">ExecStartPre</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">/sbin/modprobe overlay </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">code</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">exited, </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">status</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain">/SUCCESS</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> Main PID: </span><span class="token number" style="color:rgb(247, 140, 108)">24471</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">k3s-agent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>That's it ... that's all!</p><p>When you go back to the terminal session on the K3s server you can list all nodes in the cluster using standard <code>kubectl</code> commands.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl get nodes</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAME              STATUS   ROLES    AGE   VERSION</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">streampi-02   Ready    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">none</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">   3d    v1.17.4+k3s1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">streampi-01   Ready    master   3d    v1.17.4+k3s1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Hmmm - but wait. We did only add one agent node to the cluster right? Well, that's true, however when installing K3s using the script the server automatically installs and runs an agent on the same node.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-install-helm">3. Install Helm<a href="#3-install-helm" class="hash-link" aria-label="Direct link to 3. Install Helm" title="Direct link to 3. Install Helm">​</a></h3><p>SSH into the RPi that should act as the K3s server later on - in our case this is <code>streampi-01</code> and install Helm. Since we are using Helm 3 there is no need to install tiller. Thus, installing helm is as simple as running the following command:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">curl</span><span class="token plain"> -sSL https://get.helm.sh/helm-v3.1.2-linux-arm.tar.gz </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">sudo</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">tar</span><span class="token plain"> -xzf - -C /usr/local/bin/ linux-arm/helm --strip-components</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This command downloads the Helm binary release from Github, extracts only the binary and puts it in <code>/usr/local/bin</code>. Try go check <code>helm version</code> to see if it worked.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">version.BuildInfo</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">Version:</span><span class="token string" style="color:rgb(195, 232, 141)">"v3.1.2"</span><span class="token plain">, GitCommit:</span><span class="token string" style="color:rgb(195, 232, 141)">"d878d4d45863e42fd5cff6743294a11d28a9abce"</span><span class="token plain">, GitTreeState:</span><span class="token string" style="color:rgb(195, 232, 141)">"clean"</span><span class="token plain">, GoVersion:</span><span class="token string" style="color:rgb(195, 232, 141)">"go1.13.8"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>To use Helm, we can set and export <code>KUBECONFIG</code> environment variable to point to the kubeconfig under <code>/etc/rancher/k3s/k3s.yaml</code>.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token builtin class-name" style="color:rgb(255, 203, 107)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(191, 199, 213)">KUBECONFIG</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">/etc/rancher/k3s/k3s.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Alternatively, if you want this permanently you can either add it to your <code>.bashrc</code>/<code>.zshrc</code>, or create a <code>.kube</code> directory in your home directory and symlink the <code>k3s.yaml</code>.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">mkdir</span><span class="token plain"> </span><span class="token environment constant" style="color:rgb(130, 170, 255)">$HOME</span><span class="token plain">/.kube</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">ln</span><span class="token plain"> -s /etc/rancher/k3s/k3s.yaml </span><span class="token environment constant" style="color:rgb(130, 170, 255)">$HOME</span><span class="token plain">/.kube/config</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="deploy-streampipes-on-k3s-using-helm">Deploy StreamPipes on K3s using Helm<a href="#deploy-streampipes-on-k3s-using-helm" class="hash-link" aria-label="Direct link to Deploy StreamPipes on K3s using Helm" title="Direct link to Deploy StreamPipes on K3s using Helm">​</a></h2><p>Now, that we have all set up, we can go ahead and deploy StreamPipes using our Helm chart. Therefore, we go to the server node (<code>streampi-01</code>), where we installed Helm. Next, we clone our StreamPipes installer repository (<code>dev</code> branch) and navigate to the helm-chart directory.</p><p><strong>Note</strong>: At the point of writing, the helm chart is <strong>only</strong> available in the <code>dev</code> branch. This will change in the future as we update the repository.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">git</span><span class="token plain"> clone -b dev --single-branch https://github.com/apache/incubator-streampipes-installer.git</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">cd</span><span class="token plain"> incubator-streampipes-installer</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>At this point, we can leverage Helm's <code>install</code> command in order to install the StreamPipes Helm chart. Since Helm reads the K3s kubeconfig, it forwards the deployment request to K3s. As per default, we deploy StreamPipes <code>lite</code> version, where we only start standalone Java-based pipeline elements and disregard the ones building on top of our Flink wrapper.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">helm </span><span class="token function" style="color:rgb(130, 170, 255)">install</span><span class="token plain"> streampipes helm-chart</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAME: streampipes</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">LAST DEPLOYED: Tue Apr </span><span class="token number" style="color:rgb(247, 140, 108)">14</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">18</span><span class="token plain">:13:19 </span><span class="token number" style="color:rgb(247, 140, 108)">2020</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAMESPACE: default</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">STATUS: deployed</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">REVISION: </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">TEST SUITE: None</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Next, K3s receives this requests and goes ahead and downloads the corresponding Docker images and starts the deployments in the right order according to the specified dependencies, creates services as well as persistent volume claims when needed. This step takes some time depending on your internet connection and the hardware when starting the containers. You can check the status of the StreamPipes Helm installation using <code>kubectl get pods -o wide</code> (when adding <code>-w</code>, you can automatically watch for changes). You can also use the custom command below to only display the pod name, status as well as the node where it was scheduled and deployed to.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl get pods -o</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">custom-columns</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAME                                           STATUS    NODE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">activemq-66d58f47cf-b88nb                      Running   streampi-01</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">zookeeper-5d9947686f-7vpjb                     Running   streampi-02</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">couchdb-77db98cf7b-6nn99                       Running   streampi-02</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">consul-55965f966b-tjcfb                        Running   streampi-02</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">influxdb-b95b6479-mvgbg                        Running   streampi-02</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">backend-6cdfb7bbf9-b4vgh                       Running   streampi-02</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">pipeline-elements-all-jvm-64795974-g2xhv       Running   streampi-02</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">kafka-657b5fb77-xtw8p                          Running   streampi-01</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">connect-master-56f5f947d-n2t5b                 Running   streampi-01</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">sources-watertank-simulator-6958f7844c-2jv78   Running   streampi-01</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">connect-worker-fdbd6f464-m6vm8                 Running   streampi-01</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">nginx-5d4498d4f5-fcccq                         Running   streampi-02</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>As can be seen, a fair amount of StreamPipes containers aka pods were deployed on <code>streampi-01</code> and <code>streampi-02</code>. When everything goes well, you should see all containers in the status <code>RUNNING</code> after a couple of minutes. To access K8s cluster UI pod a <code>NodePort</code> was created. The <code>NodePort</code> publishes the UI (nginx) service on every node using using its public IP and a port. Then you can access the service using any of the cluster IPs and the assigned port.</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token key atrule">apiVersion</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> nginx</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">spec</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">selector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">app</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> nginx</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> NodePort</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> main</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">protocol</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> TCP</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">port</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">80</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># container port</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">targetPort</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">80</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># node port</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>That means, you can go and check the StreamPipes UI either on <code>http://streampi-01/</code> or <code>http://streampi-02/</code> - K8s service handles the routing to the nginx pod containing the UI - just to name one nice feature.</p><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-05-27/streampi_installation.png" alt="Installation"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="sum-up--where-to-go-from-here">Sum up &amp; Where to go from here?<a href="#sum-up--where-to-go-from-here" class="hash-link" aria-label="Direct link to Sum up &amp; Where to go from here?" title="Direct link to Sum up &amp; Where to go from here?">​</a></h2><p>Starting out as a simple hack session on a late afternoon, we build multi-archicture StreamPipes Docker images and deployed them on a Raspberry Pi in the first part of the series. Though, this is was feasible StreamPipes architectural microservice design provides a natural fit for a distributed cluster deployment. To this extent, we provide a StreamPipes Helm chart that lets you easily deploy StreamPipes in a one-liner in a Kubernetes cluster as showcased using a testbed of two Raspberry Pi's and lightweight K3s.</p><p>As of now, we let K8s handle the scheduling of containers for us in a random fashion. From here, we can further explore K8s feature such as <code>nodeSelector</code> or <code>nodeAffinity</code> that helps you use labels (<code>key=value</code> pairs) for pod to node assignment.</p><img loading="lazy" class="blog-image" style="max-width:60%" src="/img/blog/2020-05-27/helm_k3s.png" alt="HelmK3s"><ul><li><a href="/blog/2020/01/23/streampipes_on_rpi/">Part 1: StreamPi(pes) - Running StreamPipes on Raspberry Pi</a></li><li><strong><a href="/blog/2020/05/27/streampipes_on_k3s/">Part 2: Running StreamPipes the Kubernetes-Way using K3s</a></strong></li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="useful-links">Useful links<a href="#useful-links" class="hash-link" aria-label="Direct link to Useful links" title="Direct link to Useful links">​</a></h3><ul><li>[1][K3s - lightweight Kubernetes distro]<!-- -->(<a href="https://k3s.io/" target="_blank" rel="noopener noreferrer">https://k3s.io/</a>)</li><li>[2][Helm - the package manager for Kubernetes]<!-- -->(<a href="https://helm.sh/" target="_blank" rel="noopener noreferrer">https://helm.sh/</a>)</li><li>[3][Github: StreamPipes Helm chart]<!-- -->(<a href="https://github.com/apache/incubator-streampipes-installer/tree/dev/helm-chart" target="_blank" rel="noopener noreferrer">https://github.com/apache/incubator-streampipes-installer/tree/dev/helm-chart</a>)</li></ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache StreamPipes release 0.66.0]]></title>
            <link>https://streampipes.apache.org/blog/2020/05/19/release-0660</link>
            <guid>https://streampipes.apache.org/blog/2020/05/19/release-0660</guid>
            <pubDate>Tue, 19 May 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[6 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>6 minutes to read</strong></div><p></p><br><p>The Apache StreamPipes (incubating) community is proud to announce Apache StreamPipes version 0.66.0! This release is our first official Apache release and brings some very cool features and improvements the community has worked on over the past months.</p><p>The latest release brings major improvements to the live dashboard, the notification system, multiple new pipeline elements and StreamPipes Connect adapters, a simplified installation, more deployment options and a variety of bug fixes and minor improvements.
The current release can be downloaded <a href="https://streampipes.apache.org/download.html" target="_blank" rel="noopener noreferrer">here</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="user-interface">User interface<a href="#user-interface" class="hash-link" aria-label="Direct link to User interface" title="Direct link to User interface">​</a></h2><p>This release introduces a completely redesigned live dashboard. The old dashboard had some issues, most importantly, widgets could not be freely moved on the dashboard panel and the layout of dashboard widget was not persisted.
With the new dashboard, users are able to customize and layout widgets in a much easier and more powerful way. The dashboard brings the following improvements:</p><ul><li>Multiple dashboards can be created and viewed</li><li>Widgets can be flexibly resized on a grid</li><li>More configuration options for widgets, e.g., change the color and appearance of widgets.</li><li>A presentation mode allows to display a live dashboard without the navigation bars.</li></ul><p>The new dashboard has full feature parity with the old dashboard in terms of available widgets. The new architecture allows us to integrate even more visualizations with less effort in the upcoming versions.</p><div class="my-carousel"><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-05-19/dashboard-02.png" alt="New dashboard"><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-05-19/dashboard-01.png" alt="New dashboard"></div><p>In addition, the notification system has been significantly improved. The new notification view now offers a chat-like interface which allows you to select notifications per pipeline. The history of notifications is fully available and can be opened by scrolling to the top - similar to the behaviour of popular messaging services:</p><div class="my-carousel"><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-05-19/notification-01.png" alt="New dashboard"><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-05-19/notification-02.png" alt="New dashboard"></div><p>A technical note:
Both features are part of our current effort to gradually migrate AngularJS components to Angular 9 (2+), now leaving the pipeline editor the only component that is still implemented in AngularJS.
Once the editor has been migrated as well (which is currently targeted for the upcoming release 0.67.0), we'll be able to release global UI features (e.g., better user management) in a much faster way.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="apache-streampipes-extensions">Apache StreamPipes Extensions<a href="#apache-streampipes-extensions" class="hash-link" aria-label="Direct link to Apache StreamPipes Extensions" title="Direct link to Apache StreamPipes Extensions">​</a></h2><p>We also added several new adapters to connect data sources and pipeline elements:</p><ul><li>We added several new processors for handling boolean values, which are targeted towards better processing of PLC data.</li><li>processors-geo-jvm includes more processors for geo operations, e.g., distance calculation, speed calculation and more.</li><li>processors-text-mining includes several processors relevant for text mining (e.g., chunking, language detection)</li><li>New adapters for NETIO power sockets, and several new sinks (e.g., MQTT and Eclipse Ditto) </li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="installation--deployment">Installation &amp; Deployment<a href="#installation--deployment" class="hash-link" aria-label="Direct link to Installation &amp; Deployment" title="Direct link to Installation &amp; Deployment">​</a></h2><p>The community also improved the installation process. Now, the installer offered for download includes all three supported deployment options and tools:</p><ul><li>The installer, targeted at users, with installation scripts for Linux, MacOS and Windows</li><li>The CLI, targeted at developers, for configurable deployment of individual services</li><li>Helm charts for Kubernetes</li></ul><p>A very cool new feature are Docker images for ARM, which allow to run StreamPipes on a Raspberry Pi. This will be part of an upcoming blog post on running Apache StreamPipes at the edge.</p><p>From now on, users are no longer required to enter the server IP upon startup, which should further reduce errors at installation time.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-features-and-improvements">Other features and improvements<a href="#other-features-and-improvements" class="hash-link" aria-label="Direct link to Other features and improvements" title="Direct link to Other features and improvements">​</a></h2><ul><li>Connect adapters expose their own icons and documentation.</li><li>The UI has been upgraded to Angular 9 and the build has more optimizations enabled, leading to significant performance gains.</li><li>Pipelines are now auto-saved, so that you can resume building your pipeline after refreshing the browser.</li></ul><p>See the <a href="https://issues.apache.org/jira/projects/STREAMPIPES/versions/12347025" target="_blank" rel="noopener noreferrer">release notes</a> for a complete list of new features and improvements.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:users@streampipes.apache.org" target="_blank" rel="noopener noreferrer">mail</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p><p>And do not forget to subscribe to our new mailing lists: <a href="https://streampipes.apache.org/mailinglists.html" target="_blank" rel="noopener noreferrer">https://streampipes.apache.org/mailinglists.html</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[StreamPi(pes) - Running StreamPipes on Raspberry Pi]]></title>
            <link>https://streampipes.apache.org/blog/2020/01/23/streampipes_on_rpi</link>
            <guid>https://streampipes.apache.org/blog/2020/01/23/streampipes_on_rpi</guid>
            <pubDate>Thu, 23 Jan 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-01-23/streampipes_raspberrypi.png" alt="StreamPipes on Raspberry Pi">**<div style="float:left;padding-right:40px">5 minutes to read</div>**<br><p>This is the start of a two part series on how we want to bring StreamPipes closer to the edge. The <a href="/docs/blog/2020/01/23/streampipes_on_rpi/">first part</a> describes how we managed to build and deploy StreamPipes on one Raspberry Pi (Model 4), while the <a href="/docs/blog/2020/05/27/streampipes_on_k3s/">second part</a> further covers how to deploy StreamPipes over a Kubernetes cluster of two Raspberry Pi's via K3s using our StreamPipes helm chart.</p><p>&lt;TL;DR&gt;</p><p><em>With new advancements that came in the last StreamPipes release, we managed to reduce the required resources (mainly memory) drastically. To this extent, we cross-compiled StreamPipes Docker images for ARM support and deployed our lite version on a Raspberry Pi (Model 4). We showcase, that it is feasible to run analytical pipelines with ease and operate StreamPipes at moderate load.</em></p><p>Apache StreamPipes (incubating) is a self-service (Industrial) IoT toolbox to enable non-technical users to easily connect, analyze and explore IoT data streams. Users can leverage algorithms from an extensible toolbox to model their analytical pipelines. By building on a microservice architecture, StreamPipes components can be distributed in a cluster (e.g. Kubernetes)  as well as run on a single node for prototypical and development purposes using Docker. With the latest release of StreamPipes (0.65.0), we managed to reduce the memory consumption drastically to use less than 2Gig‘s of RAM for the lite version. Since we had a Raspberry Pi Model 4 laying around, we thought: hey why not just deploy StreamPipes on a Pi - and that’s what we did. Along the way, we learned quite some interesting things, that we want to share in this blog post.</p><p>When users model their analytical pipelines using the graphical pipeline editor, the corresponding pipeline element containers, hosting these algorithms, are invoked by a rest call from the backend to start a new thread with the corresponding algorithm. In typical edge use cases such as in the industrial internet of things (IIoT), it is oftentimes neither feasible nor necessary to simply send all raw data to the cloud to perform analytics. On the contrary, requirements often induce the challenges to either derive decisions in a time-sensitive manner (near realtime), preprocess  data to reduce and harmonize it, or anonymize it by pixeling personal information such as faces in video footages. In these scenarios, StreamPipes can aid by running dedicated pipeline element containers directly on the edge using edge nodes such as Raspberry Pi‘s close to where data origins to address the aforementioned challenges.</p><img loading="lazy" class="blog-image" align="center" style="max-width:80%" src="/img/blog/2020-01-23/00_idea.png" alt="StreamPipes lite on Raspberry Pi"><p>StreamPipes Docker images were only built for x86 based architectures. However, oftentimes edge devices such as Raspberry Pi's or Nvidia Jetson Nano's run ARM based 32 or 64bit architectures. Thus, we could not simply use our existing Docker images to deploy StreamPipes as is. Luckily, Docker offers solutions to cross-compile images. Together with Docker‘s experimental manifest feature, the deployment works like a charms [<a href="https://docs.docker.com/engine/reference/commandline/manifest/" target="_blank" rel="noopener noreferrer">1</a>]. There are awesome blog posts online [<a href="https://ownyourbits.com/2018/06/27/running-and-building-arm-docker-containers-in-x86/" target="_blank" rel="noopener noreferrer">2</a>] that guide you through the process of cross-compilation, so we are not going to cover it in this blog post. With that, we were able to build StreamPipes images for AMD, ARM32v7 and ARM64v8 by just adding a few lines to our Dockerfiles and CI/CD pipelines. After having built and pushed our newly created Docker images, we were able to use our existing installation workflow, e.g. StreamPipes CLI, to start StreamPipes on the Raspberry Pi.</p><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-01-23/01_start.png" alt="StreamPipes CLI starting StreamPipes lite version on Raspberry Pi 4"><p>The figure shows StreamPipes CLI starting our internal <code>0.65.1-SNAPSHOT</code> version, where we tested the multiarch build of our images. As depicted, all StreamPipes lite services are started. Due to the fact, that we created a manifest for all our Docker images, we did not have to change a single image description specified in the various <code>docker-compose.yml</code> files in the service repository. This is pretty cool! The Docker daemon automatically pulls the correct image for the corresponding architecture - in our case ARM32v7. Taking a quick look at <code>htop</code> indicates that we operate on a constant level of consumed memory at around ~1.7GB.</p><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-01-23/02_htop.png" alt="htop showing around 1.7GB memory consumption"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="demo-temperature-monitoring-pipeline">Demo: Temperature Monitoring Pipeline<a href="#demo-temperature-monitoring-pipeline" class="hash-link" aria-label="Direct link to Demo: Temperature Monitoring Pipeline" title="Direct link to Demo: Temperature Monitoring Pipeline">​</a></h3><p>To test our setup, we deployed a simple temperature monitoring pipeline, that throws a notification whenever the temperature value exceeds a certain threshold (in this case: 65°C) and visualizes the results in a basic dashboard (see figure). Therefore, we use existing pipeline elements of the algorithm toolbox provided within the lite version. Thereby, StreamPipes lite already hooks you up with sample data sources - in this case a flow rate sensor - producing temperature, as well as mass flow measurements. So our temperature monitoring pipeline consists of the following pipeline elements:</p><ul><li><strong>Data source:</strong> Flow rate sensor (mock data generating <code>&lt;timestamp;sensorid;massflow;temperature&gt;</code> each second)</li><li><strong>Data processor:</strong> Numerical filter (specified temperature threshold: &gt; 65°C)</li><li><strong>Data sinks:</strong> Dashboard visualization, Notification (internal)</li></ul><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-01-23/03_pipeline.png" alt="Simple pipeline visualizing and notifying about temperature values above threshold (here 65°C)"><p>After saving and starting the pipeline, we built our dashboard based on the results of the pipeline, only showing values above 65°C. Additionally, we receive a notification for every event, that exceeds this temperature threshold.</p><img loading="lazy" class="blog-image" style="max-width:100%" src="/img/blog/2020-01-23/04_dashboard.png" alt="Dashboard"><h3 class="anchor anchorWithStickyNavbar_LWe7" id="so-whats-next">So, what's next?<a href="#so-whats-next" class="hash-link" aria-label="Direct link to So, what's next?" title="Direct link to So, what's next?">​</a></h3><p>Starting out as a simple hack session on a late afternoon, trying to test where we could potentially run StreamPipes on and push it to it's limits, we gained valueable insights on how to build and run it on various architectures. Even though we do not recommend deploying StreamPipes in it's full glory on single low-resourced devices such as Raspberry Pi's, we aim to bring certain algorithms closer to where data is generated - on the edge. Consequently - apart from x86 images - we plan on providing our StreamPipes Docker images for ARM based architectures in the future. As a sneak peak - we also plan on deploying StreamPipes over a K3s [<a href="https://k3s.io/" target="_blank" rel="noopener noreferrer">3</a>] cluster, a lightweight Kubernetes distro especially suited for IoT and edge scenarios.</p><ul><li><strong><a href="/blog/2020/01/23/streampipes_on_rpi/">Part 1: StreamPi(pes) - Running StreamPipes on Raspberry Pi</a></strong></li><li><a href="/blog/2020/05/27/streampipes_on_k3s/">Part 2: Running StreamPipes the Kubernetes-Way using K3s</a></li></ul><h3 class="anchor anchorWithStickyNavbar_LWe7" id="useful-links">Useful links<a href="#useful-links" class="hash-link" aria-label="Direct link to Useful links" title="Direct link to Useful links">​</a></h3><ul><li>[1][Docker manifest docs]<!-- -->(<a href="https://docs.docker.com/engine/reference/commandline/manifest/" target="_blank" rel="noopener noreferrer">https://docs.docker.com/engine/reference/commandline/manifest/</a>)</li><li>[2][Running and Building ARM Docker containers in x86]<!-- -->(<a href="https://ownyourbits.com/2018/06/27/running-and-building-arm-docker-containers-in-x86/" target="_blank" rel="noopener noreferrer">https://ownyourbits.com/2018/06/27/running-and-building-arm-docker-containers-in-x86/</a>)</li><li>[3][K3s - lightweight Kubernetes distro]<!-- -->(<a href="https://k3s.io/" target="_blank" rel="noopener noreferrer">https://k3s.io/</a>)</li></ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Moving to the Apache Incubator]]></title>
            <link>https://streampipes.apache.org/blog/2019/11/25/moving-to-the-apache-incubator</link>
            <guid>https://streampipes.apache.org/blog/2019/11/25/moving-to-the-apache-incubator</guid>
            <pubDate>Mon, 25 Nov 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[8 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>8 minutes to read</strong></div><p></p><br>Great news: StreamPipes is moving to the Apache Incubator!<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-streampipes-journey-so-far">The StreamPipes journey so far<a href="#the-streampipes-journey-so-far" class="hash-link" aria-label="Direct link to The StreamPipes journey so far" title="Direct link to The StreamPipes journey so far">​</a></h2><p>We started to build the early foundations of StreamPipes back in 2014 as part of the EU research project <em>ProaSense</em>.
Our goal was to make event processing accessible to end users with a focus on the Industrial IoT, without the technical
expertise required by stream processing tooling.
After some very early prototypes (see an early screenshot below :-)) demonstrating the usefulness of the pipeline editor
and the underlying semantics-based data model in two manufacturing-related use cases, we open-sourced StreamPipes in
2017 and continued development in various research projects.
Since then, we presented and showcased StreamPipes at various events: fairs, meetups, conference talks and so on. For
instance, in 2019 we attended over 20 events where we gave demos or talked about StreamPipes.
It is great to see that the solution is now steadily getting increased traction in the Industrial IoT space.</p><img loading="lazy" class="blog-image" style="max-width:90%;margin-bottom:20px" src="/img/blog/2019-11-25/2019-11_StreamPipes-v0.png" alt="1st prototype of the StreamPipes UI"><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-11-25/2019-11_StreamPipes-now.png" alt="1st prototype of the StreamPipes UI"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="moving-to-the-apache-incubator">Moving to the Apache Incubator<a href="#moving-to-the-apache-incubator" class="hash-link" aria-label="Direct link to Moving to the Apache Incubator" title="Direct link to Moving to the Apache Incubator">​</a></h2><p>Earlier this year, we discussed how to continue the development of StreamPipes. For the core team at FZI, our main goal
was to widen the developer base, attract external developers and to make StreamPipes a real community-driven open source
project.
We had a look at various open source foundations (namely Apache, CNCF and Eclipse), but from the beginning, there was no
doubt that we wanted to see StreamPipes in the Apache Software Foundation. Using a lot of Apache Big Data projects under
the hood (<a href="https://kafka.apache.org" target="_blank" rel="noopener noreferrer">Apache Kafka</a>, <a href="https://flink.apache.org" target="_blank" rel="noopener noreferrer">Apache Flink</a> and others), an emerging
Apache IoT ecosystem, and the community-driven, open development process of ASF projects, this was an easy decision.
Finally, a few weeks before we went to ApacheCon North America in Las Vegas in September this year to talk about
StreamPipes, we discovered the awesome <a href="https://plc4x.apache.org" target="_blank" rel="noopener noreferrer">Apache PLC4X</a> project, which perfectly aligns with
StreamPipes tackling the hard task to connect proprietary industrial protocols with modern software tooling.
We met Chris Dutz together with other people from PLC4X and other Apache projects in Las Vegas and were overwhelmed by
the <em>Apache Way</em> and the great collaboration between the various projects within the ASF.</p><p>So after coming back home, we immediately started to write the proposal to enter the Apache Incubator, which got
accepted on 2019-11-11.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-project-setup">New project setup<a href="#new-project-setup" class="hash-link" aria-label="Direct link to New project setup" title="Direct link to New project setup">​</a></h2><p>With the great help from our mentors, we already performed some initial steps required to move our infrastructure over
to the ASF, which will continue during the next week:</p><ul><li>The new website will be soon available under <a href="https://streampipes.apache.org" target="_blank" rel="noopener noreferrer">https://streampipes.apache.org</a></li><li>We will move our code repositories over to the ASF on Github. Before that, we'll merge some repos to make future
releases easier: The <strong>backend and user interface</strong> will be merged to the
repository <a href="/blog/2019/11/25/moving-to-the-apache-incubator/[https://www.github.com/apache/incubator-streampipes/">https://www.github.com/apache/incubator-streampipes</a>.
Pipeline elements and StreamPipes Connect adapters will also be merged to a new repo called <strong>streampipes-extensions
</strong>, soon available
at <a href="https://www.github.com/apache/incubator-streampipes-extensions" target="_blank" rel="noopener noreferrer">https://www.github.com/apache/incubator-streampipes-extensions</a>.
Both <strong>website and documentation</strong> will be available
at <a href="https://www.github.com/apache/incubator-streampipes-website" target="_blank" rel="noopener noreferrer">https://www.github.com/apache/incubator-streampipes-website</a>.
Finally, the project <strong>streampipes-installer</strong>
at <a href="https://www.github.com/apache/incubator-streampipes-installer" target="_blank" rel="noopener noreferrer">https://www.github.com/apache/incubator-streampipes-installer</a>
will contain the installer for Windows and OSX/Linux, the developer-oriented CLI tool and helm charts to install
StreamPipes in Kubernetes.</li><li>Apache project communication mainly relies on mailing lists. Subscribe to
the <a href="mailto:users-subscribe@streampipes.apache.org" target="_blank" rel="noopener noreferrer">user list</a>
and <a href="mailto:dev-subscribe@streampipes.apache.org" target="_blank" rel="noopener noreferrer">dev list</a> and help us to improve StreamPipes!</li><li>Issues can be created in the new <a href="https://issues.apache.org/jira/projects/STREAMPIPES" target="_blank" rel="noopener noreferrer">Jira</a>.</li><li>All previous releases will be marked as non-ASF-releases to clearly indicate that previous releases do not follow the
Apache release policy. Yesterday, we released the final pre-Apache
version <a href="/blog/2019/11/23/release-0650/">0.65.0</a>, the next release will be our first Apache release.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="thanks">Thanks<a href="#thanks" class="hash-link" aria-label="Direct link to Thanks" title="Direct link to Thanks">​</a></h2><p>We would like to thank Chris Dutz for his great support in doing the first steps in the Apache Incubator.</p><p>We would also like to thank our employee, <a href="https://www.fzi.de/en" target="_blank" rel="noopener noreferrer">FZI Research Center for Information Technology</a>, for
the continued great support - starting from giving us the opportunity to present StreamPipes at large fairs such as
Hannover Messe, over media support such as creating the great StreamPipes logo, up to the fast legal support we received
when we got accepted by the Apache Incubator.
If you want to build cool stuff in a great applied research institute while pursuing a PhD at KIT, FZI is surely the
best place to be ;-)</p><p>Let's continue development and transform Apache StreamPipes (incubating) into the next Apache community!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[StreamPipes release 0.65.0]]></title>
            <link>https://streampipes.apache.org/blog/2019/11/23/release-0650</link>
            <guid>https://streampipes.apache.org/blog/2019/11/23/release-0650</guid>
            <pubDate>Sat, 23 Nov 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>5 minutes to read</strong></div><p></p><br><p>We are happy to announce StreamPipes version 0.65.0! This release brings performance improvements related to the installation process and further reduces the minimum hardware requirements to run StreamPipes.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="installation">Installation<a href="#installation" class="hash-link" aria-label="Direct link to Installation" title="Direct link to Installation">​</a></h2><p>If you're installing StreamPipes using the provided installer, you might have noticed that the initial setup takes some time: Docker images are downloaded, all dependent microservices are started and the RDF-based database that we use internally to store pipeline elements is initialized.
On less-performant hardware, this process could take a few minutes. For this release, we optimized the installation process:</p><ul><li>You don't need to provide your IP address during the installation process anymore - StreamPipes now runs without manually providing an IP address.</li><li>A new initialization screen is shown in the StreamPipes user interface that automatically disappears and guides you to the setup process once all mandatory services are running.</li><li>The setup process in the user interface should now be much faster due to some changes related to the caching of pipeline elements.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="lite-version">Lite version<a href="#lite-version" class="hash-link" aria-label="Direct link to Lite version" title="Direct link to Lite version">​</a></h2><p>To further reduce the minimum hardware requirements to run StreamPipes, we added a new Docker container to the backend that includes all data processors and sinks that depend on the lightweight JVM wrapper. Flink and other modules are excluded.
This approach allows to test StreamPipes with less memory (e.g., on a laptop) while still having a larger set of pipeline elements installed.<br>
<!-- -->We now recommend a minimum of 4GB RAM for the StreamPipes Lite version (make sure that the RAM is also assigned to Docker Desktop), but our tests have shown that the memory consumption of the StreamPipes lite version is around 2GB.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-elements">Pipeline Elements<a href="#pipeline-elements" class="hash-link" aria-label="Direct link to Pipeline Elements" title="Direct link to Pipeline Elements">​</a></h2><ul><li>0.65.0 includes some new data processors: A CSV enrichment processors that allows to enrich events with metadata from CSV files, an event counter and some processors that perform operations on boolean values, e.g., coming from PLCs.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-features-and-improvements">Other features and improvements<a href="#other-features-and-improvements" class="hash-link" aria-label="Direct link to Other features and improvements" title="Direct link to Other features and improvements">​</a></h2><ul><li>Use the latest Flink version 1.9.1</li><li>We improved the OPC-UA adapter, e.g., you can now directly set the URL of the OPC-UA server.</li><li>Proper error messages are now shown in the pipeline view in case something goes wrong during the start of a pipeline.</li></ul><p>See the <a href="https://github.com/apache/incubator-streampipes/releases/tag/0.65.0" target="_blank" rel="noopener noreferrer">release notes</a> for a complete list of new features and improvements.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:feedback@streampipes.org" target="_blank" rel="noopener noreferrer">mail</a>, <a href="https://slack.streampipes.org" target="_blank" rel="noopener noreferrer">slack</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p><p>And do not forget to subscribe to our new mailing lists: <a href="https://streampipes.apache.org/mailinglists.html" target="_blank" rel="noopener noreferrer">https://streampipes.apache.org/mailinglists.html</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[StreamPipes release 0.64.0]]></title>
            <link>https://streampipes.apache.org/blog/2019/09/19/release-0640</link>
            <guid>https://streampipes.apache.org/blog/2019/09/19/release-0640</guid>
            <pubDate>Thu, 19 Sep 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>5 minutes to read</strong></div><p></p><br><p>Usually, we try to publish a new StreamPipes release every three months. But after attending a very exciting <a href="https://www.apachecon.com/acna19/" target="_blank" rel="noopener noreferrer">ApacheCon</a> last week, where we worked with some Apache communities on a few really cool new features, we decided to release these features as soon as possible.
So here's StreamPipes 0.64.0!</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-connect">StreamPipes Connect<a href="#streampipes-connect" class="hash-link" aria-label="Direct link to StreamPipes Connect" title="Direct link to StreamPipes Connect">​</a></h2><ul><li>StreamPipes Connect now has a new (experimental) connector for <a href="https://plc4x.apache.org/" target="_blank" rel="noopener noreferrer">ApachePLC4X</a>. PLC4X is a (really cool) universal protocol adapter for the Industrial IoT with many adapters for systems like Modbus, Beckhoff, S7 and OPC-UA. The new StreamPipes Connect adapter allows you to easily connect to an S7 device, we will add more integrations in the upcoming releases.</li><li>We added another adapter to retrieve data from the <a href="https://pulsar.apache.org" target="_blank" rel="noopener noreferrer">Apache Pulsar</a> messaging system.</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-09-19/spconnect.png" alt="PLC4X adapter for StreamPipes Connect"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-elements">Pipeline Elements<a href="#pipeline-elements" class="hash-link" aria-label="Direct link to Pipeline Elements" title="Direct link to Pipeline Elements">​</a></h2><ul><li>0.64.0 also includes a new data sink to send data to Apache Pulsar.</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="deployment">Deployment<a href="#deployment" class="hash-link" aria-label="Direct link to Deployment" title="Direct link to Deployment">​</a></h2><p>StreamPipes relies on a microservice-based architecture and therefore requires quite a few services (&gt; 15 for the full version) to be up and running.
This has impact on the memory consumption of the server where StreamPipes is running. On the other hand, we want to make it as easy as possible to try StreamPipes even on laptops with less powerful hardware. </p><p>However, the lite version still required &gt; 8G memory and the full version even more. Additionally, after the last release, we received feedback from the community indicating that the memory consumption has significantly increased.
So we looked deeper into the issue and discovered that the Docker base images we were using to deliver the StreamPipes services caused high memory consumption.</p><p>Before StreamPipes 0.63.0, we used the Alpine Oracle JDK image for most services. In 0.63.0, we switched to an OpenJDK/Alpine distribution. This had an enormous effect on memory, having individual services that reserved more than 1.5GB of memory.</p><p>So in this version, we switched to AdoptOpenJDK along with <a href="https://www.eclipse.org/openj9/" target="_blank" rel="noopener noreferrer">OpenJ9</a>. The results are fantastic: The full version including all pipeline elements now needs only 6GB memory (compared to &gt; 16 in the last version).</p><p>The screenshot below shows that StreamPipes now is much less resource hungry:</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-09-19/memory.png" alt="PLC4X adapter for StreamPipes Connect"><p>In future versions, we will continue our efforts to decrease the memory consumption of StreamPipes.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:feedback@streampipes.org" target="_blank" rel="noopener noreferrer">mail</a>, <a href="https://slack.streampipes.org" target="_blank" rel="noopener noreferrer">slack</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[StreamPipes release 0.63.0]]></title>
            <link>https://streampipes.apache.org/blog/2019/09/05/release-0630</link>
            <guid>https://streampipes.apache.org/blog/2019/09/05/release-0630</guid>
            <pubDate>Thu, 05 Sep 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>5 minutes to read</strong></div><p></p><br><p>StreamPipes version 0.63.0 has been released! Following our release plan to alternate between user-faced and backend-oriented releases, this release contains many (more than 70) features and improvements, mainly on the backend side.
The new version is available on Docker Hub and can be downloaded using our <a href="https://github.com/apache/incubator-streampipes-installer" target="_blank" rel="noopener noreferrer">installer</a>.</p><p>For this release, we focused on improving the stability and resilience of StreamPipes, adding many new features "under the hood".</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="backend--data-model">Backend &amp; Data Model<a href="#backend--data-model" class="hash-link" aria-label="Direct link to Backend &amp; Data Model" title="Direct link to Backend &amp; Data Model">​</a></h2><ul><li>First, v0.63.0 brings <strong>support for binary messaging formats</strong>. Prior to 0.63.0, the only messaging format used at runtime was JSON. Now, several other binary formats are supported: Smile and CBOR as binary JSON representations and FST, a fast Java-based serializer.</li><li>Second, we improved <strong>resilience of pipelines</strong>. Now, when StreamPipes is stopped, all running pipelines are stopped beforehand and can be restarted later on, so that you don't end up with orphaned pipelines anymore. </li></ul><p>We also extended the data model and SDK with new features:</p><ul><li>Pipeline elements can now provide their own assets such as documentation. Simply add an icon and a markdown file containing the documentation of the pipeline element and both will be visible directly in the pipeline editor after the installation of the pipeline element.</li><li>We added several new static properties to define required user input: <strong>SecretStaticProperties</strong> can be used to define secret values (e.g., passwords). In addition, <strong>StaticPropertyAlternatives</strong> were introduced to let users select between multiple combinations of static properties (e.g., a time window and a count window along with window settings).</li></ul><p>In addition, we migrated all pipeline element container and the backend to Spring Boot applications. The triple store used to store pipeline element descriptions has been extracted to an own microservice. Btw, have you seen the new <a href="https://www.github.com/streampipes/streampipes-helm-chart" target="_blank" rel="noopener noreferrer">helm chart</a> that simplifies running StreamPipes on Kubernetes?</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="ui-and-pipeline-editor">UI and Pipeline Editor<a href="#ui-and-pipeline-editor" class="hash-link" aria-label="Direct link to UI and Pipeline Editor" title="Direct link to UI and Pipeline Editor">​</a></h2><p>We improved the <strong>interactive user guide</strong>, so that it now depends on pipeline elements that are also available in the lite version.
Three different interactive guides exist: One that teaches you how to create pipelines, another one that illustrates how to connect data with StreamPipes connect and a third one that shows how to create live visualizations using the built-in dashboard.</p><p>As <strong>user feedback</strong> is absolutely important to help us improving StreamPipes, we added a feature that allows users to directly give feedback from the StreamPipes UI. Simply click the feedback icon in the top navigation bar and submit your anonymous feedback to us! </p><p>Finally, there are also some functional improvements in the pipeline editor: <strong>Pipeline validation</strong> has improved and gives direct feedback. And, finally, you can now also add multiple dashboards sink to a single pipeline :-)</p><p>And a nice feature you can't see but which you'll probably feel: All UI files are now <strong>Gzip compressed</strong> by default, so that StreamPipes will now load much faster. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-elements">Pipeline Elements<a href="#pipeline-elements" class="hash-link" aria-label="Direct link to Pipeline Elements" title="Direct link to Pipeline Elements">​</a></h2><p>StreamPipes 0.63.0 includes several new pipeline elements:</p><ul><li>A sink for Apache IoTDB</li><li>A sink for PostgreSQL</li><li>A processor to convert boolean values</li><li>A processor to extract timestamps</li><li>A processor to compute trigonometric functions</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-connect">StreamPipes Connect<a href="#streampipes-connect" class="hash-link" aria-label="Direct link to StreamPipes Connect" title="Direct link to StreamPipes Connect">​</a></h2><p>We added more adapters and improved some adapters to StreamPipes Connect:</p><ul><li>An improved MQTT adapter that can handle authentication</li><li>A new MySQL adapter</li><li>An improved OPC-UA adapter</li><li>A new random data generator that eases testing of pipeline elements</li></ul><p>In addition, we completely reworked the Connect UI. The schema view now lets you edit events more conveniently and timestamp fields can be directly marked in the UI.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="documentation">Documentation<a href="#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation">​</a></h2><p>We updated and restructured the user guide, which now consists of four parts: <a href="/docs/user-guide-introduction/">Introduction</a>, <a href="/docs/user-guide-tour/">Tour</a>, <a href="/docs/user-guide-installation/">Installation</a> and <a href="/docs/user-guide-first-steps/">First Steps</a>.
We also updated all screenshots to reflect the current look and feel of StreamPipes.</p><p>In addition, the developer guide was further extended (e.g., there is now a new tutorial on creating data sinks). Maven archetypes are now the recommended way to create new pipeline elements.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-features-and-improvements">Other features and improvements<a href="#other-features-and-improvements" class="hash-link" aria-label="Direct link to Other features and improvements" title="Direct link to Other features and improvements">​</a></h2><ul><li>An improved installer that lets you choose between two StreamPipes versions for different hardware setups (full or lite, previously named big data and desktop)</li><li>We updated some core libraries like Apache Flink and Apache Kafka to newer versions.</li><li>Improved support for Firefox and Edge: Besides Chrome, StreamPipes should also behave and look similar in Firefox and Edge browsers.</li></ul><p>See the <a href="https://github.com/apache/incubator-streampipes/releases/tag/0.63.0" target="_blank" rel="noopener noreferrer">release notes</a> for a complete list of new features and improvements.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:feedback@streampipes.org" target="_blank" rel="noopener noreferrer">mail</a>, <a href="https://slack.streampipes.org" target="_blank" rel="noopener noreferrer">slack</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[StreamPipes release 0.62.0]]></title>
            <link>https://streampipes.apache.org/blog/2019/05/23/release-0620</link>
            <guid>https://streampipes.apache.org/blog/2019/05/23/release-0620</guid>
            <pubDate>Thu, 23 May 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[6 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>6 minutes to read</strong></div><p></p><br><p>StreamPipes version 0.62.0 has been released! While the last version brought many features under the hood, this new version totally focuses on features and improvements visible to end users.
The new version is available on Docker Hub and can be downloaded using our <a href="https://github.com/streampipes/streampipes-installer" target="_blank" rel="noopener noreferrer">installer</a>.</p><p>For this release, we focused on improving error handling in the pipeline editor, added more pipeline elements, added more adapters to StreamPipes Connect and, added a documentation on available pipeline elements.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-elements">Pipeline Elements<a href="#pipeline-elements" class="hash-link" aria-label="Direct link to Pipeline Elements" title="Direct link to Pipeline Elements">​</a></h2><p>Pipeline elements are the most important part of the StreamPipes toolbox. Although pipeline elements can be easily developed using our SDK, we aim to provide as many ready-to-use elements as possible to provide you with meaningful data harmonization and analytics features right from the beginning.
StreamPipes v0.62.0 brings many new data processors and data sinks, an overview can be found <a href="/docs/pipeline-elements/">here</a>. </p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-editor">Pipeline Editor<a href="#pipeline-editor" class="hash-link" aria-label="Direct link to Pipeline Editor" title="Direct link to Pipeline Editor">​</a></h2><p>To better support users while developing pipelines, we improved the verification of user input in the pipeline editor.
Users now get hints (directly shown in the pipeline assembly) on missing pipeline elements and error messages are shown if invalid values are entered while configuring pipeline elements (see the screenshot below).
In addition, the editor now disallows adding new pipeline elements until the active pipeline element is fully configured, otherwise, the element is marked with a red alert symbol, which makes it much easier to discover modeling errors.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-05-23/pipeline-editor.png" alt="Pipeline Element Verification"><p>One feature request which was coming from one of our users was to better understand what pipeline elements are doing. For that reason, we now added a feature that allows to see a full documentation of any pipeline element directly in the pipeline editor.
Once users start to configure a new pipeline element, the documentation can be opened:</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-05-23/pipeline-element-documentation.png" alt="Pipeline Element Documentation"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-connect">StreamPipes Connect<a href="#streampipes-connect" class="hash-link" aria-label="Direct link to StreamPipes Connect" title="Direct link to StreamPipes Connect">​</a></h2><p>We added more adapters to StreamPipes Connect.
Besides generic adapters such as frequently used protocols like OPC UA, MQTT and Kafka, Connect now also includes some new open data adapters and adapters for web APIs to make starting with StreamPipes more funny and easier:</p><ul><li>A Slack source to connect Slack channels with StreamPipes</li><li>A Coindesk sources that allows you to get the latest Bitcoin rates</li><li>A Wikipedia sources to get latest edits and created articles from Wikipedia</li><li>IEXCloud adapters to provide access to stock quotes and news from IEXCloud (an API token is required).</li><li>A ROS source to access data from the Robot Operating System (ROS)</li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-05-23/connect.png" alt="StreamPipes Connect"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="documentation">Documentation<a href="#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation">​</a></h2><p>The documentation for pipeline elements that is shown in the pipeline editor is now also available in the online documentation.
Navigate to <a href="/docs/pipeline-elements/">pipeline elements</a> to see an overview of all pipeline elements that are currently provided by StreamPipes.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-features-and-improvements">Other features and improvements<a href="#other-features-and-improvements" class="hash-link" aria-label="Direct link to Other features and improvements" title="Direct link to Other features and improvements">​</a></h2><ul><li>Adapters can be sorted and filtered in StreamPipes Connect.</li><li>Labels and descriptions of pipeline elements can be provided by external resources files as a first step towards internationalization.</li><li>We upgraded the UI to the latest Angular version 7 and drastically reduced the size of the UI source bundle, which reduces loading time.</li><li>Stream requirements are now correctly ordered</li></ul><p>See the <a href="https://github.com/streampipes/streampipes/releases/tag/0.62.0" target="_blank" rel="noopener noreferrer">release notes</a> for more details.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:feedback@streampipes.org" target="_blank" rel="noopener noreferrer">mail</a>, <a href="https://slack.streampipes.org" target="_blank" rel="noopener noreferrer">slack</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[StreamPipes release 0.61.0]]></title>
            <link>https://streampipes.apache.org/blog/2019/04/04/release-0610</link>
            <guid>https://streampipes.apache.org/blog/2019/04/04/release-0610</guid>
            <pubDate>Thu, 04 Apr 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>5 minutes to read</strong></div><p></p><br><p>We are proud to release StreamPipes version 0.61.0, which brings many improvements and some exciting new features that simplify pipeline development!
The new version, which is already available on Docker Hub and can be downloaded using our <a href="https://github.com/streampipes/streampipes-installer" target="_blank" rel="noopener noreferrer">installer</a> brings over 20 improvements. Under the hood, a reworked event model simplifies the development of new pipeline elements using the built-in SDK.</p><p>Our main mission is to make IoT data management &amp; analytics accessible to everyone.
This release focuses on better integrating StreamPipes with other systems and data sources and contains UX improvements to ease the development of pipelines.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-connect">StreamPipes Connect<a href="#streampipes-connect" class="hash-link" aria-label="Direct link to StreamPipes Connect" title="Direct link to StreamPipes Connect">​</a></h2><p>StreamPipes Connect, which aims to easily connect arbitrary data sources with StreamPipes, has been first introduced as a public beta in version 0.60.0.
Version 0.61.0 brings many new features to Connect and also implements many bug fixes that now make Connect the recommended way to connect data sources.</p><p>StreamPipes Connect relies on an extensible architecture to connect either generic protocols or specific adapters.</p><p>In more detail, StreamPipes Connect supports the following protocols, with a completely code-free integration process:</p><ul><li><p>Data Streams</p><ul><li>HTTP/REST</li><li>MQTT</li><li>Apache Kafka</li><li>File</li><li>ROS (preview)</li><li>GDELT</li></ul></li><li><p>Data Sets</p><ul><li>HTTP/REST</li><li>HDFS</li><li>File</li></ul></li></ul><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-04-04/connect.png" alt="StreamPipes Connect"><p>The next version will also include an adapter for OPC UA, which is currently being tested in a real setting.</p><p>For protocols that are not yet supported by StreamPipes Connect, a new Maven archetype for easily connecting data sources using the <a href="/docs/dev-guide-tutorial-sources/">SDK</a> is provided.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="improved-pipeline-modeling">Improved Pipeline Modeling<a href="#improved-pipeline-modeling" class="hash-link" aria-label="Direct link to Improved Pipeline Modeling" title="Direct link to Improved Pipeline Modeling">​</a></h2><p>On the UI side, we try to make the graphical modeling of pipelines as simple as possible. Besides some minor improvements (e.g., case-insensitive search for pipeline elements), pipelines are now constantly validated and users get feedback on steps that are still missing (e.g., missing pipeline elements).
As many other features we are currently implementing, this feature directly comes from a user request - so if you have any suggestions for improvement, let us know!</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2019-04-04/validation.png" alt="Pipeline Validation"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="reworked-event-model">Reworked Event Model<a href="#reworked-event-model" class="hash-link" aria-label="Direct link to Reworked Event Model" title="Direct link to Reworked Event Model">​</a></h2><p>One of the most important features of v0.61.0 is not directly visible to end users, but drastically eases the development of new pipeline elements with the SDK.
From this release on, events at runtime are represented in form of a new <code>Event Object</code> instead of the former <code>Map</code> representation.
This feature allows us for much better support of complex data processors which have more than one input data stream and comes with many convenience methods to better extrat fields from an event for processing.</p><p>For instance, prior to v0.61.0 you had to extract fields from an incoming events as follows:</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token annotation punctuation" style="color:rgb(199, 146, 234)">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onEvent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Map</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generics class-name" style="color:rgb(255, 203, 107)">String</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token generics"> </span><span class="token generics class-name" style="color:rgb(255, 203, 107)">Object</span><span class="token generics punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"> in</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SpOutputCollector</span><span class="token plain"> out</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">       </span><span class="token class-name" style="color:rgb(255, 203, 107)">Integer</span><span class="token plain"> numberValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">Integer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">parseInt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">String</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">valueOf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">in</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token constant" style="color:rgb(130, 170, 255)">MAPPING_PROPERTY_ID</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The new event model is much simpler and less error-prone:</p><div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token keyword" style="font-style:italic">public</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">onEvent</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token class-name" style="color:rgb(255, 203, 107)">Event</span><span class="token plain"> in</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SpOutputCollector</span><span class="token plain"> out</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">throws</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">SpRuntimeException</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token class-name" style="color:rgb(255, 203, 107)">Integer</span><span class="token plain"> numberValue </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> in</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getFieldBySelector</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token constant" style="color:rgb(130, 170, 255)">MAPPING_PROPERTY_SELECTOR</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getAsPrimitive</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getAsInteger</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>The new event model is even more useful in cases where your data streams have a complex nested structure or contain list fields.
If you connect two data streams containing the same fields to a processor, field names are automatically renamed in the background to avoid naming conflicts.
A complete guide can be found in the <a href="/blog/2019/04/04/release-0610/dev-guide-event-model/">developer guide</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="documentation">Documentation<a href="#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation">​</a></h2><p>The developer guide has been extended:
Besides reworked tutorials on developing new data processors and data sources, the new documentation includes instructions on adding <a href="/blog/2019/04/04/release-0610/dev-guide-stream-requirements/">stream requirements</a>, the new <a href="/blog/2019/04/04/release-0610/dev-guide-event-model/">event model</a>, and in-depth guides on defining <a href="/blog/2019/04/04/release-0610/dev-guide-static-properties/">static properties</a> and <a href="/blog/2019/04/04/release-0610/dev-guide-output-strategies/">output strategies</a>.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-features-and-improvements">Other features and improvements<a href="#other-features-and-improvements" class="hash-link" aria-label="Direct link to Other features and improvements" title="Direct link to Other features and improvements">​</a></h2><ul><li>SSL support: The UI can now be configured to support SSL, see the <a href="/docs/dev-guide-ssl/">documentation</a> on required configurations in your docker-compose file.</li><li>A new map visualization to visualize spatial data streams</li><li>The customize dialog is now hidden in case no static properties are present</li><li>Adapter descriptions can be exported and imported</li><li>The UI does no longer load any external sources</li><li>Updated Maven archetypes</li></ul><p>See the <a href="https://github.com/streampipes/streampipes/releases/tag/0.61.0" target="_blank" rel="noopener noreferrer">release notes</a> for more details.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:feedback@streampipes.org" target="_blank" rel="noopener noreferrer">mail</a>, <a href="https://slack.streampipes.org" target="_blank" rel="noopener noreferrer">slack</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ContainerCLI: A CLI tool for your Docker Application]]></title>
            <link>https://streampipes.apache.org/blog/2018/11/24/container-cli</link>
            <guid>https://streampipes.apache.org/blog/2018/11/24/container-cli</guid>
            <pubDate>Sat, 24 Nov 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[6 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>6 minutes to read</strong></div><p></p><br><p>In this blog post, we show how we developed a CLI tool to install and manage StreamPipes.
In addition, we present a template project that enables you to easily create a CLI tool for your own docker application.
All you need is a working docker-compose.yml file.</p><p>StreamPipes has a Microservice architecture and we use Docker and Docker Compose for all of our development, testing, and deployment processes.
In the beginning, we developed the CLI only to ease the installation process (e.g. managing multiple versions), but over time we realized that the tool is much more powerful.
For example, StreamPipes has multiple developer roles: Some developers are working on the frontend, others on the backend, and some are developing new algorithms and data sinks for StreamPipes.
In the figure below, you can see different configurations that are used by different developers.
All services are running in docker, except for the ones the developer is currently working on.
As a result, we had many different docker-compose.yml files and when we made changes, we had to synchronize them all.</p><img loading="lazy" class="blog-image" style="max-width:60%" src="/img/blog/2018-11-24/roles.png" alt="Three different developer roles"><p>Therefore, our goal was to speed up the setup of a development environment, so that developers can focus on their specific programming task.
That’s why we developed a command line tool that automates the setup of different environments.
All what is needed is a docker-compose.yml file that describes all services of the application and the template CLI project from <a href="https://github.com/streampipes/container-cli" target="_blank" rel="noopener noreferrer">GitHub</a>.
Afterwards, you need to split up your compose file and create an individual file for each service. Put those files in individual folders in the services folder.
Each folder should have the same name as the service name in the docker-compose file. That’s it!
Now you can use the CLI.
With the default commands you are able to start, stop, and configure the application. But how is this better than just using docker itself?
The advantage is the flexibility and extensibility of the tool.
You can extend the script with tasks you have to perform regularly, like cleaning up volumes, or setting up testing environments.</p><p>In the following we will describe the tool in more detail.
You can see all files and folders of the CLI Tool in the next listing.
The first file “container-cli.m4” contains the script.
We use <a href="https://argbash.io/" target="_blank" rel="noopener noreferrer">Argbash</a>, which eases the use of bash script parameters and flags.
In this file you can easily add new custom commands, flags or other functionalities.
The next file is the actual bash script. It is generated by argbash.
Since this file is generated automatically, you should not change anything.
The docker-compose.yml file is the main file.
This should contain all services, networks, or volume information that is relevant for all the other services of your application.
All your other services are located in the services folder.
For each service, create a folder with the name of the service and place a docker-compose.yml in the folder configuring the service.
Therefore, you can copy and paste the configuration from your current docker-compose.yml.
The script checks the services folder dynamically, this means you can add services at a later point in time without changing anything else.
In our example, we have four services: Backend, UI, database, and a test database containing data for the end2end tests.
Which services should be started when running the command <strong>"container-cli start"</strong> is defined in the active-service file.
This file contains the names of all services, each in one line, that should be started.
Often it is required to have multiple configurations of your app. You can save them in the templates folder.
By running <strong>“container-cli set-template ui_developer”</strong>, you can select the template ui_developer.
With this command, all services defined in the template are written to the active-services file. (e.g. the ui_developer template contains just the database and backend and the e2e-test template contains the backend, ui, and test-database).</p><img loading="lazy" class="blog-image" style="max-width:30%" src="/img/blog/2018-11-24/files.png" alt="Structure of the containter cli project"><p>The last file is the tmpl_env file.
It contains configuration variables for the individual services.
Those variables can also be changed by the bash script dynamically, because the tmpl_env file is moved to the .env file in the same folder.
We use the configuration for example to dynamically set the IP Address of the host system or set the application version.
To use a variable in a docker-compose file just write it in braces, as shown below.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2018-11-24/variables.png" alt="How to use Environment Variables"><p>We hope this tool is helpful for your use case.
When you have any problems, feedback, or ideas for improvements, contact us or open an issue on <a href="https://github.com/streampipes/container-cli" target="_blank" rel="noopener noreferrer">GitHub</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Preview: StreamPipes release 0.60.0]]></title>
            <link>https://streampipes.apache.org/blog/2018/09/17/preview-060</link>
            <guid>https://streampipes.apache.org/blog/2018/09/17/preview-060</guid>
            <pubDate>Mon, 17 Sep 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[5 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>5 minutes to read</strong></div><p></p><br><p>It's been a while since our last blog post. However, in the background we are working hard to release the next version of StreamPipes which is currently in the final phase.
In this post, we'd like to give you a preview of the upcoming StreamPipes version 0.60.0, which brings many new features and improvements.</p><p>Our first public release is now about 6 months ago. In the meantime, we gathered lots of feedback we got from users concerned with the installation, available pipeline elements and usability.
We learned what users expect from the tool and really tried to implement feature suggestions from the community.</p><p>Here are the major things you'll find in the next version which will be released by the end of September:</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="installation-and-first-time-usage">Installation and first-time usage<a href="#installation-and-first-time-usage" class="hash-link" aria-label="Direct link to Installation and first-time usage" title="Direct link to Installation and first-time usage">​</a></h2><p>We aim to make it as easy as possible for first-time users to try and test StreamPipes. Although we have provided Docker images and a docker-compose file from the beginning, we've learned that our target group looks for an easier way to install the tool, without the need to manually configuring things like ports or hostnames.
For that reason, we have implemented an installer that is already on <a href="https://www.github.com/streampipes/streampipes-installer" target="_blank" rel="noopener noreferrer">Github</a>. With the next release, you'll find an even easier installer along with a dev-installer targeted at more advanced users that allows to configure the services and pipeline element containers you'd like to use in your StreamPipes instance.</p><p>In addition, we wanted to provide better support for users that are trying to build a pipeline for the first time. Although we provide a tour and a user guide, we are aware that nobody likes reading documentations ;-)
Therefore, the next release includes an interactive product tour that guides you through the first steps with StreamPipes and explains how to build pipelines - right in the pipeline editor!</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2018-09-17/streampipes-060-product-tour.png" alt="Product Tour"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="streampipes-connect">StreamPipes Connect<a href="#streampipes-connect" class="hash-link" aria-label="Direct link to StreamPipes Connect" title="Direct link to StreamPipes Connect">​</a></h2><p>Although the SDK provides a developer-oriented way to connect new data sources, many users have asked us to provide an easier way to connect sources and data streams to StreamPipes.
The next release includes a beta release of StreamPipes Connect. Connect is a major effort that integrates work we've done over the past year and provides an easy way to integrate your data streams right from the UI.
A data marketplace contains a list of pre-defined adapters (which can be rather generic by selecting a protocol and a data format or quite specific as, e.g., an openSenseMap source).
These adapters can be configured according to your needs and directly started on a set of worker nodes.</p><p>StreamPipes Connect also lays the foundation for some cool new features that make it even easier to connect sources and will be added over the next months.
In addition, pre-processing features will be integrated that will support edge computing use cases.</p><p>Be aware that StreamPipes Connect will be released in a rather early version, so don't use it for production yet.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:90%" src="/img/blog/2018-09-17/streampipes-060.png" alt="StreamPipes Connect"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="pipeline-elements">Pipeline Elements<a href="#pipeline-elements" class="hash-link" aria-label="Direct link to Pipeline Elements" title="Direct link to Pipeline Elements">​</a></h2><p>Pipeline elements (data processors and sinks) are the part of StreamPipes that generate added-value.
While the first release contained a set of around 10 pipeline elements, the next release will provide many new elements that are already integrated.
New elements will include pattern detection algorithms, geospatial operators, image processing algorithms (e.g., a generic classifier) and even a Slack sink!</p><p>In total, the next version includes more than 40 pipeline elements and we will add many more during the next months.
The new pipeline elements are already available on <a href="https://www.github.com/streampipes/streampipes-pipeline-elements" target="_blank" rel="noopener noreferrer">Github</a> and will be released as Docker images by the end of September.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-features-and-improvements">Other features and improvements<a href="#other-features-and-improvements" class="hash-link" aria-label="Direct link to Other features and improvements" title="Direct link to Other features and improvements">​</a></h2><ul><li>A new wrapper for the <a href="https://github.com/wso2/siddhi" target="_blank" rel="noopener noreferrer">Siddhi</a> CEP engine</li><li>various bug fixes and stability improvements</li><li>many UX improvements</li><li>many more, stay tuned for the next blog post!</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="feedback">Feedback<a href="#feedback" class="hash-link" aria-label="Direct link to Feedback" title="Direct link to Feedback">​</a></h2><p>We are absolutely open to your suggestions for further improvements! Let us know (by <a href="mailto:feedback@streampipes.org" target="_blank" rel="noopener noreferrer">mail</a>, <a href="https://slack.streampipes.org" target="_blank" rel="noopener noreferrer">slack</a> or <a href="https://www.twitter.com/streampipes" target="_blank" rel="noopener noreferrer">twitter</a>) and we'll consider your feature request in the next release!</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to understand your machine data?]]></title>
            <link>https://streampipes.apache.org/blog/2018/06/18/how-to-understand-your-machine-data</link>
            <guid>https://streampipes.apache.org/blog/2018/06/18/how-to-understand-your-machine-data</guid>
            <pubDate>Mon, 18 Jun 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[8 minutes to read]]></description>
            <content:encoded><![CDATA[<p><strong></strong></p><div style="float:left;padding-right:40px"><strong>8 minutes to read</strong></div><p></p><br><p>Data is the new oil. Probably everybody of you has heard or read this sentence before.
It is often stated how important data and data understanding is for companies today.
But what does this actually mean?  How does the data look like that is produced by your machines and systems?
And how can we solve the big challenge to turn this raw data into insights that can be understood by humans?</p><p>When it comes to data analytics people often talk about the big players like Google, Facebook, or Netflix which collect a lot of data about their users and their usage behavior.
The core of their business model is to use data and turn it into profit. Nowadays all companies have the requirement to analyze their data.
But since this was not originally part of their business model it is very challenging for them to catch up.
To gain insights from data, it is often referred to advanced analytics and machine learning. Before such techniques can be used some work must be done.
A first, basic part of that is to understand your data. We do that in four steps, as can be seen in figure below.
First data sources must be accessed, then they can be integrated and for example be stored in a data lake.
After that, we employ rule-based analytics to find patterns and situations.
In the end, machine learning and advanced analytics algorithms can be used to get more out of the data.
The idea behind those steps is to generate value as early as possible by collecting the low-hanging fruits first.
We develop methodologies and tools for the individual steps to also allow domain experts to perform them to bridge the gap between the big tech companies and more traditional industries.</p><img loading="lazy" class="blog-image img_ev3q" style="max-width:50%" src="/img/blog/2018-06-18/01_motivation.png" alt="Motivation Graphic"><p>The questions we try to answer in these blog posts are:</p><ul><li><strong>How does data produced by machines look like?</strong></li><li><strong>How can machines and other data sources be accessed?</strong></li><li><strong>How is it possible to process the continuously produced flow of data?</strong></li></ul><p>We illustrate our ideas with an example which we also use during the whole blog series.
The example is a water circle of a cooling system. You can see such a system in the next image.
It contains multiple water tanks and pipes that connect those tanks.
Within the tanks and the pipes are multiple sensors, which measure for example the water level in the tank, the flow rate in the water pipe, or the temperature of the water.
All those sensors are very simple, they make iterative observations and send the sensed measurements to a computer system.</p><img loading="lazy" class="blog-image" style="max-width:70%" src="/img/blog/2018-06-18/02_anlage.png" alt="Water Circle Image"><p>Before we go into detail, we want to explain the term streaming data, because we focus on machine and sensor data which is continually produced in a streaming fashion.
The opposite of streaming data are fixed sized data sets, called batch data.
Since always new data is produced by sensors, it is not possible to wait till all data is completely produced and then process it.
Different to that is batch data.
The advantage of batch data is, when the processing starts no new data is added anymore.
Streaming data can also be processed with batch processing systems.
Therefore, a data stream must be separated into fixed chunks which are then processed in a batch fashion.
This is possible but the more natural fit is to use streaming systems since they were designed to process streaming data.</p><p>In an environment where we process machine data we have different components.
The individual components exchange information in the form of <strong>events</strong>.
All assets continually producing data are called <strong>data sources</strong> (i.e. a sensor, machine or a software system).
To access these data sources, <strong>adapters</strong> are needed.
Adapters are software components (which can run anywhere, for example directly on the machine or separately on a edge device near the machine) that are able to connect to the data source, extract the sensor information and emit events to the <strong>middleware</strong>.
The middleware is a central component which is an intermediate between the individual components.
Even if the middleware is a central component, it is not a bottleneck and also not a single point of failure since it is often realized in form of a distributed system.
<strong>Processing systems</strong> can access data from the middleware, transform it and apply algorithms.
This is the component where the data is analyzed and higher-level information is generated.
In the end, results can be stored in <strong>data bases</strong>.
From there, other applications like for example dashboards can access the calculated results.
This is the high-level architecture of processing data streams.</p><img loading="lazy" class="blog-image" src="/img/blog/2018-06-18/03_architecture.png" alt="Overall architecture"><p>Once the events are integrated into a middleware, it must be processed to detect situations and generate higher-level events.
This can be done in an <strong>Event Processing Network (EPN)</strong>.
An EPN consists of one or multiple <strong>data sources, event processors</strong> transforming and detecting patterns in the data and finally <strong>data sinks</strong>, which can be data bases, alarms or other systems.
Below such a pipeline is shown where we have two sensors as data sources: A flow rate sensor measuring the flow rate in a water pipe and a water level sensor in a water tank.
It further contains three processing elements, each with a different functionality.
The first one detects increases in the water tank, the second one filters out values under a defined threshold.
The last of the processing elements detects when both situations occur within a defined time window.
In the end, we employ a data sink, which triggers a notification for a service technician once the modeled situation occurs.
We call such instances of EPNs processing <strong>pipelines</strong>.</p><img loading="lazy" class="blog-image" src="/img/blog/2018-06-18/04_pipeline.png" alt="Example Pipeline"><p>The pipeline in the image before contains three different processing elements.
Those elements contain the actual algorithms.
Such algorithms can be as easy as simple filters on a sensor value or can also be more complex, such as patterns that occur over a period of time.
But they can also contain machine learning and advanced analytics algorithms (e.g. neural networks) that perform predictions on data streams.
Event processors are just an abstraction that take a data stream as an input and expose a “new” data stream.
Furthermore, they contain configuration parameters which can be defined by a user.
With this concept, we can create reusable components that can be used in many different pipelines.</p><p>The goal of StreamPipes is to enable domain experts to do their data analysis themselves by providing tooling, where such processing pipelines can be modeled in a graphical user interface and then executed automatically without the need of an IT expert.
Processing engines which are used as the basis of the processing elements in our solution often require a higher technological understanding.
If this understanding is available, they can also be used on their own.
We use such systems, like Apache Flink, Apache Spark or the brand-new KSQL by Confluent, for the processing but provide an abstraction over them to enable domain experts to model pipelines themselves.
This has also the advantages that individual runtime solutions can be exchanged over time.
Furthermore, we provide a semantic layer for all elements, including data sources, processing elements, and data sinks.
With that layer, our system is capable of understanding the meaning and further support the user to ensure that just semantically correct pipelines are created.</p><p>In this first blog post of our series, we gave a first introduction how data produced by machines and systems can be analyzed and value can be generated out of it.
In the following blog posts we explain the individual parts in more detail to provide you with enough knowledge to start analyzing your own data.</p><ul><li><strong><a href="/blog/2018/06/18/how-to-understand-your-machine-data/">Part 1: Overview</a></strong></li><li>Part 2: Data Sources</li><li>Part 3: Data Processing Elements</li><li>Part 4: Data Sinks</li><li>Part 5: Putting it all together (Example Pipeline)</li><li>Part 6: Practical Tips</li></ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Welcome to StreamPipes!]]></title>
            <link>https://streampipes.apache.org/blog/2018/06/14/welcome</link>
            <guid>https://streampipes.apache.org/blog/2018/06/14/welcome</guid>
            <pubDate>Thu, 14 Jun 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to our new blog. StreamPipes is the new, easy-to-use self-service data analytics toolbox for the Industrial IoT. In the coming weeks, we'll publish a series of blog posts that explain some ideas of StreamPipes. You'll read about use cases, best practices as well as technical details.]]></description>
            <content:encoded><![CDATA[<p>Welcome to our new blog. StreamPipes is the new, easy-to-use self-service data analytics toolbox for the Industrial IoT. In the coming weeks, we'll publish a series of blog posts that explain some ideas of StreamPipes. You'll read about use cases, best practices as well as technical details.</p><p>Stay tuned!</p>]]></content:encoded>
        </item>
    </channel>
</rss>