<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://shifu.dev/technical-blogs</id>
    <title>Shifu | Kubernetes native, open-source IoT development framework Blog</title>
    <updated>2022-10-18T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://shifu.dev/technical-blogs"/>
    <subtitle>Shifu | Kubernetes native, open-source IoT development framework Blog</subtitle>
    <icon>https://shifu.dev/img/logo.svg</icon>
    <entry>
        <title type="html"><![CDATA[Shifu Cloud Debut]]></title>
        <id>https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud</id>
        <link href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud"/>
        <updated>2022-10-18T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[On 2022.10.18, Shifu Cloud was officially announced to the public, and users can quickly integrate their devices into Shifu by simply filling in fields in the UI.]]></summary>
        <content type="html"><![CDATA[<p>On 2022.10.18, <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a> was officially announced to the public, and users can quickly integrate their devices into <em><strong>Shifu</strong></em> by simply filling in fields in the UI.</p>
<p>In this day's live online demonstration, Yang Xijie from Edgenesis demonstrated how to use <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a> to access three physical devices and develop applications based on them. Let's review the process together!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="creating-the-cluster--installing-shifu">Creating the cluster &amp; Installing shifu<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#creating-the-cluster--installing-shifu" class="hash-link" aria-label="Direct link to Creating the cluster &amp; Installing shifu" title="Direct link to Creating the cluster &amp; Installing shifu" translate="no">​</a></h2>
<p>Before using <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a>, we need to make sure we have already installed <em><strong>Shifu</strong></em> on our computer.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Start the k8s cluster locally using kind</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind create cluster --image="kindest/node:v1.24.0"</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"># Clone the shifu repository and install it</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ git clone https://github.com/Edgenesis/shifu.git</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ cd shifu</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl apply -f pkg/k8s/crd/install/shifu_install.yml</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-221018/00.png" width="100%">
<img src="https://shifu.dev/blog-221018/01.png" width="100%">
<p>If you would like to know how to install <em><strong>Shifu</strong></em> and test it locally, you may want to check out <a href="https://shifu.dev/zh-Hans/docs/tutorials/demo-install" target="_blank" rel="noopener noreferrer" class="">download and install</a> and <a href="https://shifu.dev/zh-Hans/docs/guides/install-shifu-dev" target="_blank" rel="noopener noreferrer" class="">local installing testing</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="connecting-to-thermometer-and-led">Connecting to thermometer and LED<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#connecting-to-thermometer-and-led" class="hash-link" aria-label="Direct link to Connecting to thermometer and LED" title="Direct link to Connecting to thermometer and LED" translate="no">​</a></h2>
<img src="https://shifu.dev/blog-221018/02.png" width="60%">
<p>The devices we want to connect to are respectively an RS485 thermohygrometer and an RS485 LED display. The thermohygrometer is connected to the host PC (computer) via a serial server, and the LED display is connected to the host PC via an RS485 to USB chip. Here we don't want to bother you with any detail, and after the host computer opens the HTTP service:</p>
<ul>
<li class="">You may visit <code>localhost:23330/temperature</code> to get the temperature from the thermohygrometer</li>
<li class="">You may visit <code>localhost:23330/humidity</code> to get the humidity from the thermohygrometer</li>
<li class="">You may visit <code>localhost:23331/setfloat\?value=123.4</code>, fill <code>value</code> with the number you need to display on the LED</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">curl localhost:23330/temperature</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">curl localhost:23330/humidity</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">curl localhost:23331/setfloat\?value=123.4</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-221018/03.png" width="100%">
<p>Next we're going to integrate the two devices into <em><strong>Shifu</strong></em>, which means that the two pjysical devices (<em><strong>edgeDevice</strong></em>s) are converted to digital twins (<em><strong>deviceShifu</strong></em>s) in the k8s cluster.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="generating-configuration-file-with-one-click">Generating configuration file with one click<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#generating-configuration-file-with-one-click" class="hash-link" aria-label="Direct link to Generating configuration file with one click" title="Direct link to Generating configuration file with one click" translate="no">​</a></h2>
<p><a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a> can easily generate configuration files for <em><strong>deviceShifu</strong></em>.</p>
<p>After logging in, click "All projects" to add devices. Both devices use HTTP protocol, so choose <code>Public Protocol &gt; HTTP</code>. The IP address of the device cannot be written as <code>localhost</code>, you need to find the local IP in the network settings of your computer. For the demonstration, we used <code>192.168.0.123:23330</code> and <code>192.168.0.123:23331</code>.</p>
<img src="https://shifu.dev/blog-221018/04-1.png" width="50%">
<img src="https://shifu.dev/blog-221018/04-2.png" width="50%">
<img src="https://shifu.dev/blog-221018/04-3.png" width="50%">
<img src="https://shifu.dev/blog-221018/04-4.png" width="50%">
<p>Once the information is filled in, a command pops up on the website, click the button on the right to copy it to the terminal and execute it to deploy the device to the local k8s cluster. This saves the time of manually writing YAML configuration files and is more convenient.</p>
<img src="https://shifu.dev/blog-221018/04-5.png" width="70%">
<img src="https://shifu.dev/blog-221018/04-6.png" width="70%">
<img src="https://shifu.dev/blog-221018/04-7.png" width="100%">
<img src="https://shifu.dev/blog-221018/04-8.png" width="70%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="testing-if-the-device-has-been-successfully-integrated">Testing if the device has been successfully integrated<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#testing-if-the-device-has-been-successfully-integrated" class="hash-link" aria-label="Direct link to Testing if the device has been successfully integrated" title="Direct link to Testing if the device has been successfully integrated" translate="no">​</a></h2>
<p>We can go into the cluster to see if we could access the digital twin of both devices using the network address within the cluster:.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">## Run an nginx container</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl run --image=nginx:1.21 nginx</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Enter the nginx container</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl exec -it nginx -- bash</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Interact with the device</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://deviceshifu-mythermometer-service.deviceshifu.svc.cluster.local/humidity</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://deviceshifu-mythermometer-service.deviceshifu.svc.cluster.local/temperature</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://deviceshifu-myled-service.deviceshifu.svc.cluster.local/setfloat?value=321</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>You can see that the thermometer reading and the LED display settings are working properly, which means that devices have been successfully converted to digital twins.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="packaging-the-application-as-an-image">Packaging the application as an image<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#packaging-the-application-as-an-image" class="hash-link" aria-label="Direct link to Packaging the application as an image" title="Direct link to Packaging the application as an image" translate="no">​</a></h2>
<p>We are going to develop the application based on the thermometer and LED, here's the Python program we wrote:</p>
<p><code>main.py</code></p>
<div class="language-py codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-py codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> time</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"> requests</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"> json</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">isLocal </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)">False</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">localIp </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)">"192.168.0.123"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">flag </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><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">while</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">    flag </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" 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"># [get data]</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"> flag </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 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)">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 comment" style="color:rgb(105, 112, 152);font-style:italic"># Get temperature</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> f </span><span class="token string" style="color:rgb(195, 232, 141)">"http://{localIp}:23330/temperature"</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> isLocal </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"http://deviceshifu-mythermometer-service.deviceshifu.svc.cluster.local/temperature"</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">else</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"># Get humidity</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> f </span><span class="token string" style="color:rgb(195, 232, 141)">"http://{localIp}:23330/humidity"</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> isLocal </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"http://deviceshifu-mythermometer-service.deviceshifu.svc.cluster.local/humidity"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    res </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> requests</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">url</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"># [convert data]</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">try</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">        value </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">text</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)">'value'</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">print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"DEBUG"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</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"># [display data]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        led_url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> f </span><span class="token string" style="color:rgb(195, 232, 141)">"http://{localIp}:23331/setfloat?value={value}"</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> isLocal </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> f </span><span class="token string" style="color:rgb(195, 232, 141)">"http://deviceshifu-myled-service.deviceshifu.svc.cluster.local/setfloat?value={value}"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        requests</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">led_url</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">except</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">print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"DEBUG"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">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" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    time</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">sleep</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<p>The program reads the temperature and humidity of the thermohygrometer alternately every 2 seconds and displays the readings on the LED display.</p>
<p>Next we want to package this program as an image, so that we can load the image in the cluster and run:</p>
<p><code>requirements.txt</code></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">requests</span><br></span></code></pre></div></div>
<p><code>Dockerfile</code></p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">FROM python:3.9-slim-bullseye</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">COPY requirements.txt .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">RUN pip install --no-cache-dir -r requirements.txt</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">COPY main.py .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">CMD ["python3", "main.py"]</span><br></span></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Build the image</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker build -t xxx/connection:v0.0.1 .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Make sure the image has been built</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker images | grep connection</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">xxx/connection v0.0.1 a9526147ddad 2 minutes ago 125MB</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Load the image into the cluster</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind load docker-image xxx/connection:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Run the container as an instance of the image</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl run --image=xxx/connection:v0.0.1 connection-name</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-221018/05.png" width="60%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="accessing-the-camera">Accessing the camera<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#accessing-the-camera" class="hash-link" aria-label="Direct link to Accessing the camera" title="Direct link to Accessing the camera" translate="no">​</a></h2>
<p>Next we want to access the Hikvision camera. The camera is not nearby, it is connected wirelessly by Wi-Fi.</p>
<p>You can see that <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a> supports this module of Hikvision, click on it and configure the camera ip address, username and password to access it with one click. The device name in the demo is <code>mycamera</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Enter the nginx container</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl exec -it nginx -- bash</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Check camera information</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://deviceshifu-mycamera-service.deviceshifu.svc.cluster.local/info</span><br></span></code></pre></div></div>
<p>This means that the Hikvision camera is integrated into <em><strong>Shifu</strong></em> and has been converted to a digital twin.</p>
<img src="https://shifu.dev/blog-221018/06-0.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="controlling-the-position-of-a-camera">Controlling the position of a camera<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#controlling-the-position-of-a-camera" class="hash-link" aria-label="Direct link to Controlling the position of a camera" title="Direct link to Controlling the position of a camera" translate="no">​</a></h2>
<p>Immediately after that, we want to adjust the camera's position, and the camera's orientation can be controlled using APIs like <code>move/up</code> <code>move/down</code> <code>move/left</code> <code>move/right</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://deviceshifu-mycamera-service.deviceshifu.svc.cluster.local/move/up</span><br></span></code></pre></div></div>
<p>To check the outcome, we turn on the video player on our computer and open that streaming address: <code>rtsp://&lt;user_name&gt;:&lt;password&gt;@&lt;ip_address&gt;</code>. In <code>macOS</code>, we can open <code>IINA.app</code>, go to menu bar &gt; Open Url... &gt; paste and enter, and we can see the live surveillance video stream.</p>
<p>As you can see, the camera position has changed, and we managed to reorient the camera to the angle we need(the angle of the camera moved from the ceiling to the back the computer screenon the desk).</p>
<img src="https://shifu.dev/blog-221018/06-1.png" width="100%">
<img src="https://shifu.dev/blog-221018/06-2.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://shifu.dev/technical-blogs/2022/10/18/shifu-cloud#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>In this demonstration, we used <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a> to access three devices, and if you compare it to our first Meetup, you will see that we have achieved faster integration and lowered the threshold of integrating a device.</p>
<p><a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a> includes an Aha Moment to help you get familiar with this website.</p>
<img src="https://shifu.dev/blog-221018/07-1.png" width="100%">
<img src="https://shifu.dev/blog-221018/07-2.png" width="100%">
<p>In the future, <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a> will offer:</p>
<ul>
<li class="">More protocol support (both Edgenesis and the open source community will continue to support more protocols to improve the coverage of fast access)</li>
<li class="">Application development support (for now we still need to package applications we developed locally, but in the future, we can develope applications on <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a></li>
<li class="">App store support (which contains apps uploaded by developers or third-party plugins that users can install with one click)</li>
</ul>
<p>Thank you for reading this, let's stay tuned to future progresses of <a href="https://shifu.cloud/" target="_blank" rel="noopener noreferrer" class="">Shifu Cloud</a>!</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Meetup Technical Review]]></title>
        <id>https://shifu.dev/technical-blogs/2022/09/30/meetup</id>
        <link href="https://shifu.dev/technical-blogs/2022/09/30/meetup"/>
        <updated>2022-09-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[In the offline Shifu Meetup event held on 2022.9.29, Yang Xijie from Edgenesis demonstrated how Shifu is integrated into multiple physical IoT devices, proving through this intuitive way that Shifu framework enables fast access to devices, good isolation and easy App development without single-point failure.]]></summary>
        <content type="html"><![CDATA[<p>In the offline <code>Shifu Meetup</code> event held on 2022.9.29, Yang Xijie from Edgenesis demonstrated how <em><strong>Shifu</strong></em> is integrated into multiple physical IoT devices, proving through this intuitive way that <em><strong>Shifu</strong></em> framework enables fast access to devices, good isolation and easy App development without single-point failure.</p>
<p>Five devices were displayed in this activity, namely MQTT server, RS485 temperature and humidity meter and RS485 LED, Siemens S7 PLC, and Hikvision camera - all of which are relatively common IoT devices. Let's review the integration process below.</p>
<img src="https://shifu.dev/blog-220930/device-camera-thermometer.png" width="48%">
<img src="https://shifu.dev/blog-220930/device-plc.png" width="50%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-a-cluster-and-install-shifu">Create a Cluster and Install Shifu<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#create-a-cluster-and-install-shifu" class="hash-link" aria-label="Direct link to Create a Cluster and Install Shifu" title="Direct link to Create a Cluster and Install Shifu" translate="no">​</a></h2>
<p>First we need to start <code>Docker</code> locally. Just open <code>Docker Desktop</code> using <code>Windows</code> or <code>macOS</code> Search and minimize it to the background.</p>
<img src="https://shifu.dev/blog-220930/docker-start.png" width="80%">
<p>After that we need to create a k8s cluster with <code>kind</code>. Later on <em><strong>Shifu</strong></em> and the digital twins of IoT devices will exist in this cluster as <code>Pod</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Create a Cluster</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind create cluster --image="kindest/node:v1.24.0"</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"># Prepare the image in advance for import into the cluster</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull bitnami/kube-rbac-proxy:0.13.1 </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull edgehub/shifu-controller:v0.1.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull nginx:1.21</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind load docker-image bitnami/kube-rbac-proxy:0.13.1 edgehub/shifu-controller:v0.1.1 nginx:1.21</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220930/kind-create-cluster.png" width="60%">
<p><em><strong>Shifu</strong></em> supports one-click installation, just clone <a href="https://github.com/Edgenesis/shifu" target="_blank" rel="noopener noreferrer" class=""><em><strong>Shifu</strong></em> repository</a> first, and deploy it later with one single command:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Install shifu</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ git clone https://github.com/Edgenesis/shifu.git</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ cd shifu</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl apply -f pkg/k8s/crd/install/shifu_install.yml</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"># Run an application that will be used later</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl run --image=nginx:1.21 nginx</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220930/shifu-install.png" width="60%">
<p>You can also check out <a href="https://shifu.dev/docs/guides/install-shifu-dev" target="_blank" rel="noopener noreferrer" class="">a more detailed tutorial on installing Shifu locally</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="device-integration">Device Integration<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#device-integration" class="hash-link" aria-label="Direct link to Device Integration" title="Direct link to Device Integration" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mqtt">MQTT<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#mqtt" class="hash-link" aria-label="Direct link to MQTT" title="Direct link to MQTT" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="test-mqtt-server">Test MQTT Server<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#test-mqtt-server" class="hash-link" aria-label="Direct link to Test MQTT Server" title="Direct link to Test MQTT Server" translate="no">​</a></h4>
<p>We have deployed an MQTT server and can test it by first opening two shells.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># shellA</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ mosquitto_sub -h 82.157.170.202 -t topic0</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"># shellB</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ mosquitto_pub -h 82.157.170.202 -t topic0 -m "lol"</span><br></span></code></pre></div></div>
<p>You can see that the message sent can be received correctly.</p>
<img src="https://shifu.dev/blog-220930/mqtt-test.png" width="80%">
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="integrate-the-device">Integrate the Device<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#integrate-the-device" class="hash-link" aria-label="Direct link to Integrate the Device" title="Direct link to Integrate the Device" translate="no">​</a></h4>
<p>Next we can modify the corresponding configuration, download the corresponding image, and then use the <code>kubectl apply</code> command to integrate the MQTT server into <em><strong>Shifu</strong></em> as a digital twin.</p>
<p>Modify <code>spec.address</code> to <code>82.157.170.202:1883</code> and <code>spec.protocolSettings.MQTTSetting.MQTTTopic</code> to <code>topic0</code> in <code>examples/my_mqtt/mqtt_deploy</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull edgehub/deviceshifu-http-mqtt:v0.1.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind load docker-image edgehub/deviceshifu-http-mqtt:v0.1.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl apply -f examples/my_mqtt/mqtt_deploy</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220930/mqtt-apply.png" width="60%">
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="read-the-data">Read the Data<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#read-the-data" class="hash-link" aria-label="Direct link to Read the Data" title="Direct link to Read the Data" translate="no">​</a></h4>
<p>We can interact with the digital twin by starting an <code>nginx</code> application in the cluster.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl exec -it nginx -- bash</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">$ curl http://deviceshifu-mqtt.deviceshifu.svc.cluster.local/mqtt_data</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220930/mqtt-result.png" width="60%">
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="connect-thermometer-and-led">Connect Thermometer and LED<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#connect-thermometer-and-led" class="hash-link" aria-label="Direct link to Connect Thermometer and LED" title="Direct link to Connect Thermometer and LED" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="connect-device-to-computer">Connect Device to Computer<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#connect-device-to-computer" class="hash-link" aria-label="Direct link to Connect Device to Computer" title="Direct link to Connect Device to Computer" translate="no">​</a></h4>
<ul>
<li class="">The thermometer is connected to the computer using a serial server via a network cable</li>
<li class="">LEDs are connected to the computer using an RS485 to USB chip</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="start-http-service-locally">Start HTTP Service Locally<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#start-http-service-locally" class="hash-link" aria-label="Direct link to Start HTTP Service Locally" title="Direct link to Start HTTP Service Locally" translate="no">​</a></h4>
<p>Since <em><strong>Shifu</strong></em> does not support <code>Modbus</code> protocol right now, we need to convert the data read by <code>Modbus</code> to HTTP data.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ cd api_thermometer</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ uvicorn --host 0.0.0.0 --port 23330 main:app</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">$ cd api_led</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ uvicorn --host 0.0.0.0 --port 23331 main:app</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="contents-in-api_thermometer">contents in api_thermometer<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#contents-in-api_thermometer" class="hash-link" aria-label="Direct link to contents in api_thermometer" title="Direct link to contents in api_thermometer" translate="no">​</a></h5>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> main.py </summary><div><div class="collapsibleContent_i85q"><div class="language-py codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-py codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> fastapi </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> FastAPI</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"> List</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"> pymodbus</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">sync </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> ModbusTcpClient</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">app </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> FastAPI</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)">getHumidityAndTemperature</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 operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> List</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token builtin" style="color:rgb(130, 170, 255)">float</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 triple-quoted-string string" style="color:rgb(195, 232, 141)">"""</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">    return temperature and humidity datas retrieved from TAS-LAN-460</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token triple-quoted-string 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">    client </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> ModbusTcpClient</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">host</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'192.168.0.80'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><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)">10123</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"># the port of TAS-LAN-460</span><span class="token plain"></span><br></span><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">connect</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">    SLAVE </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)">0x01</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    r </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">read_holding_registers</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0x0000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> count</span><span class="token operator" style="color:rgb(137, 221, 255)">=</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"> unit</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">SLAVE</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">print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"collected data"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">registers</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">    client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">close</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">    result </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">r</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">registers</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 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)">10</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">registers</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 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)">10</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"> result</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 decorator annotation punctuation" style="color:rgb(199, 146, 234)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</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 keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">root</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 keyword" style="font-style:italic">return</span><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)">"message"</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)">"Hello World"</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 decorator annotation punctuation" style="color:rgb(199, 146, 234)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"/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 keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getTemperature</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">    temperature </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> getHumidityAndTemperature</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)">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">return</span><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)">"value"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string-interpolation interpolation">temperature</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">"</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 decorator annotation punctuation" style="color:rgb(199, 146, 234)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"/humidity"</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">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getHumidity</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">    humidity </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> getHumidityAndTemperature</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 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 punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"value"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string-interpolation interpolation">humidity</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> requirements.txt </summary><div><div class="collapsibleContent_i85q"><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">fastapi</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">pymodbus</span><br></span></code></pre></div></div></div></div></details>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="contents-in-api_led">contents in api_led<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#contents-in-api_led" class="hash-link" aria-label="Direct link to contents in api_led" title="Direct link to contents in api_led" translate="no">​</a></h5>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> main.py </summary><div><div class="collapsibleContent_i85q"><div class="language-py codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-py codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> fastapi </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> FastAPI</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"> pymodbus</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">sync </span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> ModbusSerialClient</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"> List</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> Dict</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">app </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> FastAPI</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">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">ZhongshengLed</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 triple-quoted-string string" style="color:rgb(195, 232, 141)">"""</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">    DEVICE_NAME = "ZhongshengLed"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token triple-quoted-string 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" 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"> device_address</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 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)">0x01</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> port</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 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)">'/dev/tty.usbserial-14120'</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">device_address </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> device_address</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">client </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> ModbusSerialClient</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">method</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'rtu'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> port</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">port</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain">  stopbits</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"> bytesize</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> parity</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'N'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> baudrate</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">9600</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> timeout</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">2.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><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)">setLedCharacter</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"> position</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"> character</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 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">setLedAscii</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">position</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">position</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> ascii_value</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">ZhongshengLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">character2ascii</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">character</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)">setLedAscii</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"> position</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"> ascii_value</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 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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">connect</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">        self</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">write_register</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">position</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">ascii_value</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> unit</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">device_address</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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">close</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)">setFourLedsString</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"> string</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 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">setFourLedsAsciis</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">ascii_values</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">ZhongshengLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">character2ascii</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">string</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 punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> ZhongshengLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">character2ascii</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">string</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 plain"> ZhongshengLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">character2ascii</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</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 punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> ZhongshengLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">character2ascii</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</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 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><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)">setFourLedsAsciis</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"> ascii_values</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> List</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</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 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">        self</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">connect</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">        self</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">write_registers</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">ZhongshengLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">LedPosition</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">one</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> values</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">ascii_values</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> unit</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">device_address</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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">close</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">class</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">LedPosition</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">        one </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 plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        two </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">        three </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 plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        four </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)">3</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">    character2ascii</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"> </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"> </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">        </span><span class="token string" style="color:rgb(195, 232, 141)">"0"</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)">0x30</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)">"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)">0x31</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)">"2"</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)">0x32</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)">"3"</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)">0x33</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)">"4"</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)">0x34</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)">"5"</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)">0x35</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)">"6"</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)">0x36</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)">"7"</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)">0x37</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)">"8"</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)">0x38</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)">"9"</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)">0x39</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)">"."</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)">0x2e</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)">0x2d</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)">0x20</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" 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)">setDot</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"> count</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 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 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">        self</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">connect</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">        self</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">write_register</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">16</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</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"> unit</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">device_address</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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">close</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)">setNegative</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"> isNegative</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)">bool</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 boolean" style="color:rgb(255, 88, 116)">False</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">        self</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">connect</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">        self</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">write_register</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">17</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</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 class="token keyword" style="font-style:italic">if</span><span class="token plain"> isNegative </span><span class="token keyword" style="font-style:italic">else</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"> unit</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">device_address</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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">close</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)">setFloat</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"> value</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)">float</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 triple-quoted-string string" style="color:rgb(195, 232, 141)">"""</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token triple-quoted-string string" style="color:rgb(195, 232, 141)">        display one decimal place</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token triple-quoted-string 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">        self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">setDot</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">count</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><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"> value </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)">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">            self</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">setNegative</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</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">        </span><span class="token keyword" style="font-style:italic">else</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">setNegative</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token boolean" style="color:rgb(255, 88, 116)">False</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">        data </span><span class="token operator" style="color:rgb(137, 221, 255)">=</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 builtin" style="color:rgb(130, 170, 255)">abs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value</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)">10</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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">connect</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">        self</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">write_register</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">7</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> unit</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">device_address</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"># self.client.write_register(address=16, value=value, unit=self.device_address)</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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">close</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)">setBrightness</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"> brightness</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 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)">7</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">        self</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">connect</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">        self</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">write_register</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">address</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token number" style="color:rgb(247, 140, 108)">14</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">brightness</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> unit</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">device_address</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">client</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">close</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">device </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> ZhongshengLed</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 decorator annotation punctuation" style="color:rgb(199, 146, 234)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</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 keyword" style="font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">root</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 keyword" style="font-style:italic">return</span><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)">"message"</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)">"Hello World"</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 decorator annotation punctuation" style="color:rgb(199, 146, 234)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"/setfloat/{value}"</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">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">setTemperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value</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)">float</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">    device</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">setFloat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">value</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 punctuation" style="color:rgb(199, 146, 234)">{</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><span class="token string" style="color:rgb(195, 232, 141)">"OK"</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 decorator annotation punctuation" style="color:rgb(199, 146, 234)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"/setfloat/{value}"</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">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">setTemperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value</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)">float</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">    device</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">setFloat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">value</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 punctuation" style="color:rgb(199, 146, 234)">{</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><span class="token string" style="color:rgb(195, 232, 141)">"OK"</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 decorator annotation punctuation" style="color:rgb(199, 146, 234)">@app</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token decorator annotation punctuation" style="color:rgb(199, 146, 234)">get</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"/setfloat"</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">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">setTemperature</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value</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)">float</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)">0.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><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    device</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">setFloat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">value</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">value</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 punctuation" style="color:rgb(199, 146, 234)">{</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><span class="token string" style="color:rgb(195, 232, 141)">"OK"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> requirements.txt </summary><div><div class="collapsibleContent_i85q"><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">fastapi</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">pymodbus</span><br></span></code></pre></div></div></div></div></details>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-verification">Local Verification<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#local-verification" class="hash-link" aria-label="Direct link to Local Verification" title="Direct link to Local Verification" translate="no">​</a></h4>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://localhost:23330/temperature</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://localhost:23330/humidity</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://localhost:23331/setfloat\?value\=123.4</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220930/http-test.png" width="100%">
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="device-integration-1">Device Integration<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#device-integration-1" class="hash-link" aria-label="Direct link to Device Integration" title="Direct link to Device Integration" translate="no">​</a></h4>
<ul>
<li class="">Modify the IP address in<code>http_thermometer/deployment/http_edgedevice.yaml</code>.</li>
<li class="">Modify the IP address in<code>http_led/deployment/http_edgedevice.yaml</code>。</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull edgehub/deviceshifu-http-http:v0.1.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind load docker-image edgehub/deviceshifu-http-http:v0.1.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl apply -f examples/my_http_led/deployment</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl apply -f examples/my_http_thermometer/deployment</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="interact-with-devices">Interact with Devices<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#interact-with-devices" class="hash-link" aria-label="Direct link to Interact with Devices" title="Direct link to Interact with Devices" translate="no">​</a></h4>
<p>Start <code>nginx</code> to interact with the thermohygrometer：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl exec -it nginx -- bash</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">$ curl http://my-thermometer.deviceshifu.svc.cluster.local/temperature</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://my-thermometer.deviceshifu.svc.cluster.local/humidity</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl http://my-led.deviceshifu.svc.cluster.local/setfloat?value=23.4</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="application-development">Application Development<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#application-development" class="hash-link" aria-label="Direct link to Application Development" title="Direct link to Application Development" translate="no">​</a></h4>
<p>Read the temperature and humidity and then display it alternately on the LED.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker build -t yangxijie/connection:v0.0.1 .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker images | grep connection</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">yangxijie/connection  v0.0.1  a9526147ddad  2 minutes ago  125MB</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind load docker-image yangxijie/connection:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl run --image=yangxijie/connection:v0.0.1 connection-name</span><br></span></code></pre></div></div>
<p>The illustration of this application is as follows：</p>
<img src="https://shifu.dev/blog-220930/application-illustration.png" width="60%">
<p>You can see the temperature and humidity are displayed alternely on the LED once the application is running.</p>
<img src="https://shifu.dev/blog-220930/application-flash.png" width="100%">
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="files-in-current-folder">files in current folder<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#files-in-current-folder" class="hash-link" aria-label="Direct link to files in current folder" title="Direct link to files in current folder" translate="no">​</a></h5>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> main.py </summary><div><div class="collapsibleContent_i85q"><div class="language-py codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-py codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> time</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"> requests</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"> json</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">isLocal </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)">False</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">localIp </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)">"192.168.31.138"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">flag </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><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">while</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">    flag </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" 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"># [get data]</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"> flag </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 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)">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 comment" style="color:rgb(105, 112, 152);font-style:italic"># get temperature</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">f"http://</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string-interpolation interpolation">localIp</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">:23330/temperature"</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> isLocal </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"http://my-thermometer.deviceshifu.svc.cluster.local/temperature"</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">else</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"># get humidity</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">f"http://</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string-interpolation interpolation">localIp</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">:23330/humidity"</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> isLocal </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"http://my-thermometer.deviceshifu.svc.cluster.local/humidity"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    res </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> requests</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">url</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"># [converse data]</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">try</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">        value </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> json</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">text</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)">'value'</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">print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"DEBUG"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> value</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"># [display data]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        led_url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">f"http://</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string-interpolation interpolation">localIp</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">:23331/setfloat?value=</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string-interpolation interpolation">value</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">"</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> isLocal </span><span class="token keyword" style="font-style:italic">else</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(195, 232, 141)">f"http://my-led.deviceshifu.svc.cluster.local/setfloat?value=</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string-interpolation interpolation">value</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token string-interpolation 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">        requests</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">led_url</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">except</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">print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"DEBUG"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">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" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    time</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">sleep</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> requirements.txt </summary><div><div class="collapsibleContent_i85q"><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">requests</span><br></span></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>Dockerfile </summary><div><div class="collapsibleContent_i85q"><div class="language-Dockerfile language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">FROM python:3.9-slim-bullseye</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">COPY requirements.txt .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">RUN pip install --no-cache-dir -r requirements.txt</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">COPY main.py .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">CMD ["python3", "main.py"]</span><br></span></code></pre></div></div></div></div></details>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="simons-plc">Simons PLC<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#simons-plc" class="hash-link" aria-label="Direct link to Simons PLC" title="Direct link to Simons PLC" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="device-integration-2">Device Integration<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#device-integration-2" class="hash-link" aria-label="Direct link to Device Integration" title="Direct link to Device Integration" translate="no">​</a></h4>
<p>First change the IP address to that of the PLC.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull edgehub/deviceshifu-http-http:v0.1.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull edgehub/plc-device:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind load docker-image edgehub/deviceshifu-http-http:v0.1.1 edgehub/plc-device:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl apply -f examples/my_plc/plc-deployment</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="interact-with-the-device">Interact with the Device<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#interact-with-the-device" class="hash-link" aria-label="Direct link to Interact with the Device" title="Direct link to Interact with the Device" translate="no">​</a></h4>
<p>Here we modify one bit on the PLC and you can see the indicator light on the PLC turns on. In actual scenarios, the PLC will control large equipments such as an robotic arm.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl run nginx --image=nginx:1.21 -n deviceshifu </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl exec -it nginx -n deviceshifu -- bash</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">$ curl "deviceshifu-plc/sendsinglebit?rootaddress=Q&amp;address=0&amp;start=0&amp;digit=1&amp;value=1"; echo</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220930/plc-light.png" width="100%">
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="hikivision-camera">Hikivision Camera<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#hikivision-camera" class="hash-link" aria-label="Direct link to Hikivision Camera" title="Direct link to Hikivision Camera" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="device-integration-3">Device Integration<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#device-integration-3" class="hash-link" aria-label="Direct link to Device Integration" title="Direct link to Device Integration" translate="no">​</a></h4>
<p>Get the IP address of the camera and then replace the IP address in <code>rtsp/camera-deployment/deviceshifu-camera-deployment.yaml</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull edgehub/deviceshifu-http-http:v0.1.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo docker pull edgehub/camera-python:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kind load docker-image edgehub/deviceshifu-http-http:v0.1.1 edgehub/camera-python:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl apply -f examples/my_rtsp/camera-deployment</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="interact-with-device">Interact with Device<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#interact-with-device" class="hash-link" aria-label="Direct link to Interact with Device" title="Direct link to Interact with Device" translate="no">​</a></h4>
<p>Check device information in cluster using <code>nginx</code>:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Interact through `curl` in cluster</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl exec -it nginx -- bash</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">$ curl http://deviceshifu-camera.deviceshifu.svc.cluster.local/info</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220930/camera-info.png" width="60%">
<p>The command that the digital twin of the camera supports is:</p>
<img src="https://shifu.dev/blog-220930/camera-instructions.png" width="70%">
<p>To view the images captured by the camera, we need to forward the port to the local machine and access it on the browser.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Local browser access</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo kubectl port-forward svc/deviceshifu-camera -n deviceshifu 8080:80</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Enter`localhost:8080/info`check information</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Enter`localhost:8080/capture`access pictures</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Enter`localhost:8080/move/{up|down|left|right}`move the camera</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># Enter`localhost:8080/stream?timeout=0`access real-time streamline</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://shifu.dev/technical-blogs/2022/09/30/meetup#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>The <code>Shifu Meetup</code> event was a huge success. As you can see <em><strong>Shifu</strong></em> enables developers to quickly access devices, unify various protocols to HTTP for easy management and subsequent application development. <em><strong>Shifu</strong></em> also has many advantages including running with no single point failure and good isolation.</p>
<p>If you are interested in <em><strong>Shifu</strong></em>, please visit <a href="https://shifu.dev/" target="_blank" rel="noopener noreferrer" class=""><em><strong>Shifu</strong></em> official website</a> to learn more. You are also welcome to give the project a star at <a href="https://github.com/Edgenesis/shifu" target="_blank" rel="noopener noreferrer" class=""><em><strong>Shifu</strong></em>'s GitHub repository</a>!</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Integrate WasmEdge in Shifu to Cleanse Data]]></title>
        <id>https://shifu.dev/technical-blogs/2022/09/15/wasmedge</id>
        <link href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge"/>
        <updated>2022-09-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This article will briefly describe how to integrate WasmEdge into Shifu to cleanse data collected from IoT devices.]]></summary>
        <content type="html"><![CDATA[<p>This article will briefly describe how to integrate <code>WasmEdge</code> into <em><strong>Shifu</strong></em> to cleanse data collected from IoT devices.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="background-">Background 🌇<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#background-" class="hash-link" aria-label="Direct link to Background 🌇" title="Direct link to Background 🌇" translate="no">​</a></h2>
<p>When we use <em><strong>Shifu</strong></em> to collect data, it usually happens that the data collected from the device is in a different format from the data we need. To solve this problem, we can use <em><strong>Shifu</strong></em> + <code>WasmEdge</code> to process the data collected by <em><strong>Shifu</strong></em> through <code>WasmEdge</code> and then return it to our application.</p>
<p>The following is the simple logic.</p>
<!-- -->
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span><code>WasmEdge</code> Introduction 🏬</div><div class="admonitionContent_BuS1"><p><code>WasmEdge</code> is a lightweight, high-performance <code>WebAssembly(WASM)</code> virtual machine optimized for the edge. <code>WasmEdge</code> can be used in a variety of scenarios such as severless cloud functions, SaaS, blockchain smart contracts, IoT, automotive real-time software applications, etc.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="prepare-">Prepare 🗂<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#prepare-" class="hash-link" aria-label="Direct link to Prepare 🗂" title="Direct link to Prepare 🗂" translate="no">​</a></h2>
<ol>
<li class=""><code>kubectl</code> v1.24.2</li>
<li class=""><code>docker</code> 20.10.16</li>
<li class=""><code>kind</code> v0.14.0</li>
<li class=""><code>git</code> 2.36.1</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deployment-">Deployment 🔨<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#deployment-" class="hash-link" aria-label="Direct link to Deployment 🔨" title="Direct link to Deployment 🔨" translate="no">​</a></h2>
<p>To make this article faster for you, you can download the program from Github with the following command. 🚀</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">git clone https://github.com/Edgenesis/wasm-shifu-demo.git</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cd wasm-shifu-demo</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-a-k8s-cluster-">Create a K8s Cluster 🐝<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#create-a-k8s-cluster-" class="hash-link" aria-label="Direct link to Create a K8s Cluster 🐝" title="Direct link to Create a K8s Cluster 🐝" translate="no">​</a></h3>
<p>Use the following command to create a <code>k8s</code> cluster.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kind delete cluster &amp;&amp; kind create cluster</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Creating cluster "kind" ...</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> ✓ Ensuring node image (kindest/node:v1.24.0) 🖼</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> ✓ Preparing nodes 📦  </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> ✓ Writing configuration 📜 </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> ✓ Starting control-plane 🕹️ </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> ✓ Installing CNI 🔌 </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> ✓ Installing StorageClass 💾 </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Set kubectl context to "kind-kind"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">You can now use your cluster with:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl cluster-info --context kind-kind</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="build-shifu-image-">Build Shifu image 🪞<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#build-shifu-image-" class="hash-link" aria-label="Direct link to Build Shifu image 🪞" title="Direct link to Build Shifu image 🪞" translate="no">​</a></h3>
<p>Use the following command to build a <em><strong>Shifu</strong></em> image.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ make -f shifu/Makefile build-image-deviceshifu</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kind load docker-image edgehub/deviceshifu-http-http:v0.0.6</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ docker images | grep edgehub/deviceshifu-http-http </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">edgehub/deviceshifu-http-http v0.0.6 1d6b3544b8ad 54 minutes ago 36.1MB</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="run-virtual-devices-">Run Virtual Devices 🔌<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#run-virtual-devices-" class="hash-link" aria-label="Direct link to Run Virtual Devices 🔌" title="Direct link to Run Virtual Devices 🔌" translate="no">​</a></h3>
<p>To make your experience easier, here we use a virtual appliance for simulation.</p>
<p>Install and run the virtual appliance with port number <code>8099</code>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ docker build -f mockDevice/dockerfile -t mockdevice:v0.0.1 .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ docker run -p 8099:8099 -itd mockdevice:v0.0.1 </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">bdfd2b1323be mockdevice:v0.0.1 ". /mockDevice" 19 seconds ago Up 18 seconds 0.0.0.0:8099-&gt;8099/tcp admiring_feistel</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="write-rules--compile-wasm">Write Rules &amp; Compile Wasm<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#write-rules--compile-wasm" class="hash-link" aria-label="Direct link to Write Rules &amp; Compile Wasm" title="Direct link to Write Rules &amp; Compile Wasm" translate="no">​</a></h3>
<p>You can write rules by using <code>JavaScript</code>. If you are not familiar with <code>JavaScript</code>, you can just use the default rules. 🥮</p>
<p>Rule file path: <code>wasmEdge/js-func/src/js/run.js</code> You can achieve different functions by modifying the rule.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ docker build -t wasm:v0.0.1 -f wasmEdge/js.dockerfile .</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kind load docker-image wasm:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl apply -f wasmEdge/k8s</span><br></span></code></pre></div></div>
<p>You can check the <code>pod</code> operation of <code>WasmEdge</code> with the following command.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl get pod -n wasmedge</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAME READY STATUS RESTARTS AGE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">wasm-deployment-fbc9564d8-td428 1/1 Running 0 1s</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="install-and-run-shifu">Install and Run Shifu<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#install-and-run-shifu" class="hash-link" aria-label="Direct link to Install and Run Shifu" title="Direct link to Install and Run Shifu" translate="no">​</a></h2>
<p>Install <em><strong>Shifu</strong></em>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl apply -f shifuConfig/shifu_install.yml</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl get pod -n shifu-crd-system</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAME READY STATUS RESTARTS AGE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">shifu-crd-controller-manager-5bbdb4d786-s6h4m 2/2 Running 0 1s</span><br></span></code></pre></div></div>
<p>Install <em><strong>deviceShifu</strong></em> to connect with <em><strong>mockDeivce</strong></em>. Before doing so, please change the <code>address</code> in the <code>shifuConfig/task3/task3.yaml</code> file to the IP of your computer.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><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">sku</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)">"E93"</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">connection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Ethernet</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">address</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)">"192.168.14.163:8099"</span><br></span></code></pre></div></div>
<p>Deploy and run <em><strong>deviceShifu</strong></em> with the following command. 🏖</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl apply -f shifuConfig/task3</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl get pod -n deviceshifu</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAME READY STATUS RESTARTS AGE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">deviceshifu-demodevice-deployment-5589b55569-l5nb2 1/1 Running 0 4s</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="experience-">Experience 🕹<a href="https://shifu.dev/technical-blogs/2022/09/15/wasmedge#experience-" class="hash-link" aria-label="Direct link to Experience 🕹" title="Direct link to Experience 🕹" translate="no">​</a></h2>
<p>You can start a <code>nginx</code> to communicate with <em><strong>deviceShifu</strong></em>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl run nginx --image=nginx:1.21</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl get pod </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">NAME READY STATUS RESTARTS AGE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">nginx 1/1 Running 0 3s</span><br></span></code></pre></div></div>
<p>With the following command, you can interact with <em><strong>Shifu</strong></em> to clean the data collected from IoT devices. 🛁</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ kubectl exec -it nginx -- curl -v http://deviceshifu-demodevice-service.deviceshifu.svc.cluster.local/get_info;echo</span><br></span></code></pre></div></div>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><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><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "code":375287,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "name": "atmospheric temperature",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "val": "24.56",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "unit":"°C",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "exception": "Temperature is too high"</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><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "code":375287,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "name": "Atmospheric Humidity",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "val": "81.63",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "unit":"%RH",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      "exception": "Humidity too high"</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></div>
<p>Also we can use the following command to check the data generated by the IoT device.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl localhost:8099/getInfo</span><br></span></code></pre></div></div>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><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">   "statusCode": "200",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   "message": "success",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   "entity":[</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">         "dateTime": "2022-09-09 09:46:45",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eUnit":"℃",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eValue": "23.87",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eKey": "e1",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eName": "Atmospheric temperature",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eNum": "101"</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><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "dateTime": "2022-09-09 09:46:45",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eUnit":"%RH",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eValue": "80.62",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eKey": "e2",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eName": "Atmospheric Humidity",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">         "eNum": "102"</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><span class="token-line" style="color:#bfc7d5"><span class="token plain">   "deviceId":950920,</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   "deviceName": "950920",</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   "deviceRemark": "2022-09-09 09:46:45"</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>Comparing the two outputs, we can see that we have successfully collected and cleaned the data to get the data we want. The comparison chart is as follows :</p>
<p><img decoding="async" loading="lazy" alt="comparison chart" src="https://shifu.dev/assets/images/data-zh-41bebe80d47ed9f3ebfe5019805b0c49.png" width="2457" height="1367" class="img_ev3q"></p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Shifu in OpenYurt Cluster]]></title>
        <id>https://shifu.dev/technical-blogs/2022/06/17/openyurt</id>
        <link href="https://shifu.dev/technical-blogs/2022/06/17/openyurt"/>
        <updated>2022-06-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[OpenYurt is a cloud-side computing platform, it converts existing Kubernetes clusters into OpenYurt clusters with OpenYurt, extends the capabilities of Kubernetes to the edge side. OpenYurt provides diverse features for collaborative development on the cloud-side, such as YurtTunnel to bridge cloud-side communication, Yurt-App-Manager for easy management of node-unit application deployment/operation and maintenance, and YurtHub to provide edge autonomy.]]></summary>
        <content type="html"><![CDATA[<p><code>OpenYurt</code> is a cloud-side computing platform, it converts existing <code>Kubernetes</code> clusters into <code>OpenYurt</code> clusters with <code>OpenYurt</code>, extends the capabilities of <code>Kubernetes</code> to the edge side. <code>OpenYurt</code> provides diverse features for collaborative development on the cloud-side, such as <code>YurtTunnel</code> to bridge cloud-side communication, <code>Yurt-App-Manager</code> for easy management of node-unit application deployment/operation and maintenance, and <code>YurtHub</code> to provide edge autonomy.</p>
<p>Developers can focus on application development on cloud-edge products without worrying about the operation and maintenance of the underlying architecture. As <code>Kubernetes</code> native open source IoT development framework, <em><strong>Shifu</strong></em> can be compatible with various IoT device protocols and abstract them into a microservice software object. The two complement each other very well. In particular, <em><strong>Shifu</strong></em> can abstract devices in a way that is native to <code>OpenYurt</code>, greatly improving the efficiency for IoT developers when we add <code>YurtDeviceController</code> to <code>OpenYurt</code>, .</p>
<p>With <code>OpenYurt</code> and <em><strong>Shifu</strong></em>, we can transform the complex <code>IoT</code>, cloud-side collaborative development into simple Web development.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="introduction">Introduction<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" translate="no">​</a></h2>
<p>This article is a guide to use <em><strong>Shifu</strong></em> to integrate <code>RTSP</code> protocol cameras into <code>OpenYurt</code> clusters , which contains the basic operations of <em><strong>Shifu</strong></em>, <code>Docker</code>, <code>Linux</code>, <code>Kubernetes</code>, <code>OpenYurt</code>. Any developer can learn how to develop <em><strong>Shifu</strong></em> through this article.</p>
<p>The <em><strong>Shifu</strong></em> architecture in this article is as follows</p>
<img src="https://shifu.dev/blog-220617/1.png" width="100%">
<p>The northbound opens up the <code>HTTP API</code> interface via <code>deviceshifu-http-http</code> and the southbound interacts with the actual device via <code>rtsp-driver</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="objectives">Objectives<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#objectives" class="hash-link" aria-label="Direct link to Objectives" title="Direct link to Objectives" translate="no">​</a></h2>
<ol>
<li class="">deploy <code>OpenYurt</code> on Server side and Edge side via <code>yurtctl</code>, and add Edge side to Server side cluster</li>
<li class="">deploy the digital twin of webcam on Edge side</li>
<li class="">realize remote automation control of webcam via HTTP</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="required-devices">Required devices<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#required-devices" class="hash-link" aria-label="Direct link to Required devices" title="Direct link to Required devices" translate="no">​</a></h2>
<ol>
<li class="">two virtual machines running <code>Linux</code>, the configuration of Server and Edge should be 4 cores with 16G RAM and 2 cores with 8G RAM respectively</li>
<li class="">a webcam with <code>RTSP</code> protocol, the camera model used in this article is Hikvision <code>DS-2DE3Q140CN-W</code>.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="software-environment">Software environment<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#software-environment" class="hash-link" aria-label="Direct link to Software environment" title="Direct link to Software environment" translate="no">​</a></h2>
<ul>
<li class=""><code>CentOS</code> 7.9.2009</li>
<li class=""><code>Go</code> v1.17.1</li>
<li class=""><code>yurtctl</code> v0.6.1</li>
<li class=""><code>kubectl</code>: v1.19.8 (installed by <code>yurtctl</code>)</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-install-and-deploy-the-openyurt-cluster">Step 1 Install and deploy the OpenYurt cluster<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#step-1-install-and-deploy-the-openyurt-cluster" class="hash-link" aria-label="Direct link to Step 1 Install and deploy the OpenYurt cluster" title="Direct link to Step 1 Install and deploy the OpenYurt cluster" translate="no">​</a></h2>
<blockquote>
<p>This article refers to the <a href="https://openyurt.io/docs/v0.6.0/installation/yurtctl-init-join" target="_blank" rel="noopener noreferrer" class="">official tutorial for <code>OpenYurt</code></a></p>
</blockquote>
<p>First let's download <code>OpenYurt</code> and clone the project directly from the official GitHub:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">git clone https://github.com/openyurtio/openyurt.git</span><br></span></code></pre></div></div>
<p>Next, let's download the v0.6.1 version of <code>yurtctl</code>:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">curl -LO https://github.com/openyurtio/openyurt/releases/download/v0.6.1/yurtctl </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">chmod +x yurtctl</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="server-side-deployment">Server-side deployment<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#server-side-deployment" class="hash-link" aria-label="Direct link to Server-side deployment" title="Direct link to Server-side deployment" translate="no">​</a></h3>
<p>Create the <code>OpenYurt</code> cluster on the Server side:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">./yurtctl init --apiserver-advertise-address &lt;SERVER_IP&gt; --openyurt-version latest --passwd 123 </span><br></span></code></pre></div></div>
<p>The cluster is successfully created when you see the following message, and use <code>--token</code> to mark that the Edge node is added to the cluster</p>
<img src="https://shifu.dev/blog-220617/2.png" width="100%">
<p>Next, take a look at the status of each <code>Pod</code> by running <code>kubectl get pods -A</code>:</p>
<img src="https://shifu.dev/blog-220617/3.png" width="100%">
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="problems">problems<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#problems" class="hash-link" aria-label="Direct link to problems" title="Direct link to problems" translate="no">​</a></h4>
<p>If you encounter in <code>kubectl logs yurt-hub-server -n kube-system</code>:</p>
<img src="https://shifu.dev/blog-220617/4.png" width="100%">
<p>Please try <code>kubectl apply -f config/setup/yurt-controller-manager.yaml</code> (method from <a href="https://github.com/openyurtio/openyurt/issues/872#issuecomment-" target="_blank" rel="noopener noreferrer" class="">https://github.com/openyurtio/openyurt/issues/872#issuecomment-</a> 1148167419 )</p>
<p>In addition, if you encounter the following output in <code>kubectl logs yurt-hub-server -n kube-system</code>.</p>
<img src="https://shifu.dev/blog-220617/5.png" width="100%">
<p>Please try <code>kubectl apply -f config/setup/ yurthub-cfg.yaml</code></p>
<img src="https://shifu.dev/blog-220617/6.png" width="100%">
<p>If similar logs are encountered in <code>yurt-tunnel-server</code> and <code>yurt-tunnel-agent</code>, fix the <code>RBAC</code> issue in <code>yurt-tunnel</code> with the following command.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f config/setup/yurt-tunnel-agent.yaml </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f config/setup/yurt-tunnel-server.yaml</span><br></span></code></pre></div></div>
<p>Use <code>untaint</code> master node to run <em><strong>Shifu</strong></em> <code>controller</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl taint nodes server node-role.kubernetes.io/master-</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/7.png" width="100%">
<p>At this point, the Server side deployment is succeed.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="deploy-the-edge-side">Deploy the Edge side<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#deploy-the-edge-side" class="hash-link" aria-label="Direct link to Deploy the Edge side" title="Direct link to Deploy the Edge side" translate="no">​</a></h3>
<p>First, run with the <code>token</code> you just initialized on the Server side.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">./yurtctl join &lt;MASTER_IP&gt;:6443 --token &lt;MASTER_INIT_TOKEN&gt; --node-type=edge --discovery-token-unsafe-skip-ca-verification --v=5 </span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/8.png" width="100%">
<p>Verify Node status by <code>kubectl get nodes</code>.</p>
<img src="https://shifu.dev/blog-220617/9.png" width="100%">
<p>At this point, a Server-side + an Edge-side cluster is created.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-deploy-shifu-in-the-cluster">Step 2 Deploy Shifu in the cluster<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#step-2-deploy-shifu-in-the-cluster" class="hash-link" aria-label="Direct link to Step 2 Deploy Shifu in the cluster" title="Direct link to Step 2 Deploy Shifu in the cluster" translate="no">​</a></h2>
<p>Next, let's deploy <em><strong>Shifu</strong></em> to the <code>OpenYurt</code> cluster</p>
<p>On the Server side, clone the <code>Shifu</code> project locally.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">git clone https://github.com/Edgenesis/shifu.git </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cd shifu/</span><br></span></code></pre></div></div>
<p>Next, install <code>Shifu</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f pkg/k8s/crd/install/shifu_install.yml</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/10.png" width="100%">
<p>Check the Pod status with <code>kubectl get pods -A</code>.</p>
<img src="https://shifu.dev/blog-220617/11.png" width="100%">
<p>Just see the Pod running in the <code>shifu-crd-system</code> namespace.</p>
<p>At this point, <em><strong>Shifu</strong></em> is successfully installed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-deploy-the-cameras-digital-twin-deviceshifu">Step 3 Deploy the camera's digital twin deviceShifu<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#step-3-deploy-the-cameras-digital-twin-deviceshifu" class="hash-link" aria-label="Direct link to Step 3 Deploy the camera's digital twin deviceShifu" title="Direct link to Step 3 Deploy the camera's digital twin deviceShifu" translate="no">​</a></h2>
<p><em><strong>OpenYurt</strong></em> provides a very convenient node pool (<code>NodePool</code>) feature that allows us to manage clusters of nodes and deploy them.</p>
<p>To create a <code>beijing</code> node pool.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">export WORKER_NODEPOOL="beijing" </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">export EDGE_NODE="edge" </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cat &lt;&lt;EOF | kubectl apply -f - </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">apiVersion: apps.openyurt.io/v1alpha1 </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">kind: NodePool </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">metadata: </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  name: $WORKER_NODEPOOL </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">spec: </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  type: Edge </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">EOF</span><br></span></code></pre></div></div>
<p>The output is as follows.</p>
<img src="https://shifu.dev/blog-220617/12.png" width="100%">
<p>Next, take the Edge server <code>label</code> to <code>beijing</code>'s <code>NodePool</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl label node $EDGE_NODE apps.openyurt.io/desired-nodepool=beijing</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/13.png" width="100%">
<p>Check the status of <code>NodePool</code>, there should be a <code>READYNODES</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl get nodepool</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/14.png" width="100%">
<p>Since IoT edge nodes are usually distributed within the same scenario, here you can use <code>OpenYurt</code>'s <code>UnitedDeployment</code> feature to automate the deployment based on the <code>NodePool</code> .</p>
<p>Install <code>Yurt-app-manager</code>:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">git clone https://github.com/openyurtio/yurt-app-manager.git</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">cd yurt-app-manager</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f config/setup/all_in_one.yaml</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/15.png" width="100%">
<p>Use <code>UnitedDeployment</code> to deploy a virtual Haikon camera with the following YAML file.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> deviceshifu-camera-unitedDeployment.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> apps.openyurt.io/v1alpha1</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"> UnitedDeployment</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">labels</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">controller-tools.k8s.io</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)">"1.0"</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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">matchLabels</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">workloadTemplate</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">deploymentTemplate</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">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">labels</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> default</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">matchLabels</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">template</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">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">labels</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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">containers</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">image</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> edgehub/deviceshifu</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">http</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">v0.0.1</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">http</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">containerPort</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)">8080</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">volumeMounts</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">mountPath</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)">"/etc/edgedevice/config"</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">readOnly</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">env</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"> EDGEDEVICE_NAME</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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)">"deviceshifu-hikvision-camera"</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"> EDGEDEVICE_NAMESPACE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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)">"devices"</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">image</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> edgenesis/camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">python</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">v0.0.1</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"> camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">python</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">containerPort</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)">11112</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">volumeMounts</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">mountPath</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)">"/etc/edgedevice/config"</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">readOnly</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">env</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"> EDGEDEVICE_NAME</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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)">"deviceshifu-hikvision-camera"</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"> EDGEDEVICE_NAMESPACE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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)">"devices"</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"> IP_CAMERA_ADDRESS</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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;CAMERA_IP&gt;"</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"> IP_CAMERA_USERNAME</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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;CAMERA_USERNAME&gt;"</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"> IP_CAMERA_PASSWORD</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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;CAMERA_PASSWORD&gt;"</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"> IP_CAMERA_CONTAINER_PORT</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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)">"11112"</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"> PYTHONUNBUFFERED</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token key atrule">value</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)">"1"</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">volumes</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token key atrule">configMap</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">configmap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">serviceAccountName</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">sa</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">topology</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">pools</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"> beijing</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">nodeSelectorTerm</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">matchExpressions</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">key</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> apps.openyurt.io/nodepool</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">operator</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> In</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">values</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"> beijing</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token key atrule">replicas</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 plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">revisionHistoryLimit</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)">5</span><br></span></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> deviceshifu-camera-service.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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">labels</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> default</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">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">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><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">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)">8080</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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"> LoadBalancer</span><br></span></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> deviceshifu-camera-unitedDeployment.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> shifu.edgenesis.io/v1alpha1</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"> EdgeDevice</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> devices</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">sku</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)">"HikVision Camera"</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">connection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Ethernet</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> 0.0.0.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token number" style="color:rgb(247, 140, 108)">11112</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">protocol</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> HTTP</span><br></span></code></pre></div></div></div></div></details>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> deviceshifu-camera-configmap.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> ConfigMap</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">hikvision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">camera</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">configmap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> default</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">data</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">driverProperties</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 scalar string" style="color:rgb(195, 232, 141)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  driverSku: HikVision</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  driverImage: edgenesis/camera-python:v0.0.1</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">instructions</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 scalar string" style="color:rgb(195, 232, 141)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  capture:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  info:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  stream:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  move/up:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  move/down:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  move/left:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  move/right:</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">telemetries</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 scalar string" style="color:rgb(195, 232, 141)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">  device_health:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    properties:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">      instruction: info</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">      initialDelayMs: 1000</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">      intervalMs: 1000</span><br></span></code></pre></div></div></div></div></details>
<p>Put the four files into a directory as follows.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">camera-unitedDeployment/ </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├── camera-edgedevice.yaml </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├── deviceshifu-camera-configmap.yaml </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├─ deviceshifu-camera-service.yaml </span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">└── deviceshifu-camera-unitedDeployment.yaml</span><br></span></code></pre></div></div>
<p>Next, deploy:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f camera-unitedDeployment/</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/16.png" width="100%">
<p>Check the <code>UnitedDeployment</code> status via <code>kubectl get ud</code>.</p>
<img src="https://shifu.dev/blog-220617/17.png" width="100%">
<p>Confirm that <code>Pod</code> is deployed in the Edge server in <code>beijing</code> <code>NodePool</code> with <code>kubectl get pods -owide</code>.</p>
<img src="https://shifu.dev/blog-220617/18.png" width="100%">
<p>We can check <em><strong>Shifu</strong></em>'s virtual devices in the cluster via <code>kubectl get edgedevices -n devices</code> at</p>
<img src="https://shifu.dev/blog-220617/19.png" width="100%">
<p>Then use <code>kubectl describe edgedevices -n devices</code> to see the details of the devices such as configuration, status, etc.</p>
<img src="https://shifu.dev/blog-220617/20.png" width="100%">
<p>At this point, the digital twin of the camera is deployed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="running-results">Running results<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#running-results" class="hash-link" aria-label="Direct link to Running results" title="Direct link to Running results" translate="no">​</a></h2>
<p>Next we control the camera, here we use a <code>Pod</code> of <code>nginx</code> to represent the application.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl run nginx --image=nginx</span><br></span></code></pre></div></div>
<p>When <code>nginx</code> is running, go to the <code>nginx</code> command line with <code>kubectl exec -it nginx -- bash</code>.</p>
<img src="https://shifu.dev/blog-220617/21.png" width="100%">
<p>The camera can be controlled directly with the following command.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">curl deviceshifu-hikvision-camera/move/{up/down/left/right}</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/22.gif" width="100%">
<p>If we want to see what the current photo and video stream, we need to proxy the camera's service locally via <code>kubectl port-forward service/deviceshifu-hikvision-camera 30080:80 --address='0.0.0.0'</code>.</p>
<p>You can view the image/video stream directly by entering the server's IP plus the port number in the browser at</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">&lt;SERVER_IP&gt;:30080/capture</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">&lt;SERVER_IP&gt;:30080/stream</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220617/23.gif" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://shifu.dev/technical-blogs/2022/06/17/openyurt#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>In this article, we showed you how to deploy <em><strong>Shifu</strong></em> in an <code>OpenYurt</code> cluster to support <code>RTSP</code> camera.</p>
<p>In the future, we will also try to integrate <em><strong>Shifu</strong></em> with <code>OpenYurt</code>  <a href="https://openyurt.io/zh/docs/core-concepts/yurt-device-controller" target="_blank" rel="noopener noreferrer" class="">YurtDeviceController</a> We will also try to extend the capabilities of <code>OpenYurt</code> to manage more IoT devices in a way that is native to <code>OpenYurt</code>.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Shifu with EMQX]]></title>
        <id>https://shifu.dev/technical-blogs/2022/06/10/emqx</id>
        <link href="https://shifu.dev/technical-blogs/2022/06/10/emqx"/>
        <updated>2022-06-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[EMQX is a popular MQTT Broker in the world. It has a cloud-native architecture based on Kubernetes, making it extremely suitable for the increasingly complex IoT scenarios and making the transmission of device messages more efficient. Shifu, as a Kubernetes native framework, can be perfectly combined with EMQX to provide EMQX with intelligent multi-protocol device linkage capabilities.]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><code>EMQX</code> is a popular <code>MQTT Broker</code> in the world. It has a cloud-native architecture based on <code>Kubernetes</code>, making it extremely suitable for the increasingly complex IoT scenarios and making the transmission of device messages more efficient. <em><strong>Shifu</strong></em>, as a <code>Kubernetes</code> native framework, can be perfectly combined with <code>EMQX</code> to provide <code>EMQX</code> with intelligent multi-protocol device linkage capabilities.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="introduction">Introduction<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" translate="no">​</a></h2>
<p>This article will show you how to deploy <code>EMQX</code> and <em><strong>Shifu</strong></em> in a cluster, integrate a thermometer with <code>MQTT</code> as the communication method and a Hikvision camera with <code>RTSP</code> as the transmission protocol, and add an application to interact with <em><strong>Shifu</strong></em> so that every time the thermometer detects a body temperature above 37 degrees it will ask the camera to take a photo.</p>
<p>The simple architecture used in this article is as follows.</p>
<img src="https://shifu.dev/blog-220610/0.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="preparation">Preparation<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#preparation" class="hash-link" aria-label="Direct link to Preparation" title="Direct link to Preparation" translate="no">​</a></h2>
<p>The following services and tools are used in this article.</p>
<ol>
<li class=""><code>Kubernetes</code>: 1.20.10<!-- -->
<ul>
<li class=""><code>kubectl</code></li>
<li class=""><code>kubeadm</code></li>
<li class=""><code>kubelet</code></li>
</ul>
</li>
<li class=""><code>Golang</code>: 1.16.10</li>
<li class=""><code>Docker</code>: 19.03.9</li>
<li class=""><code>EMQX</code>: 4.1-rc1</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-deploy-kubernetes">Step 1 Deploy Kubernetes<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#step-1-deploy-kubernetes" class="hash-link" aria-label="Direct link to Step 1 Deploy Kubernetes" title="Direct link to Step 1 Deploy Kubernetes" translate="no">​</a></h2>
<p>For this step, you can refer to the official <code>Kubernetes</code> tutorial for deployment: <code>Kubernetes</code>.</p>
<p><a href="https://kubernetes.io/docs/setup/" target="_blank" rel="noopener noreferrer" class="">https://kubernetes.io/docs/setup/</a></p>
<p>After the deployment is complete we should see the following message printed on the terminal.</p>
<img src="https://shifu.dev/blog-220610/1.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-deploy-shifu">Step 2 Deploy Shifu<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#step-2-deploy-shifu" class="hash-link" aria-label="Direct link to Step 2 Deploy Shifu" title="Direct link to Step 2 Deploy Shifu" translate="no">​</a></h2>
<p>Clone the GitHub repository for <em><strong>Shifu</strong></em> locally to.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">git clone https://github.com/Edgenesis/shifu.git</span><br></span></code></pre></div></div>
<p>You can then deploy <em><strong>Shifu</strong></em> with the following command.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f shifu/pkg/k8s/crd/install/shifu_install.yml</span><br></span></code></pre></div></div>
<p>Once deployed we should see that the <code>CRD controller</code> for <em><strong>Shifu</strong></em> has been deployed.</p>
<img src="https://shifu.dev/blog-220610/2.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-deploy-emqx">Step 3 Deploy EMQX<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#step-3-deploy-emqx" class="hash-link" aria-label="Direct link to Step 3 Deploy EMQX" title="Direct link to Step 3 Deploy EMQX" translate="no">​</a></h2>
<p>First you need to install <code>EMQX</code> <code>Operator Controller</code>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ curl -f -L "https://github.com/emqx/emqx-operator/releases/download/1.1.6/emqx-operator-controller.yaml" | kubectl apply -f -</span><br></span></code></pre></div></div>
<p>Then we write the simplest <code>deployment.yaml</code>:</p>
<img src="https://shifu.dev/blog-220610/3.png" width="100%">
<p>Then it's time to deploy an EMQX:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f deployment.yaml</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220610/4.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4-integrate-into-the-device">Step 4 Integrate into the device<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#step-4-integrate-into-the-device" class="hash-link" aria-label="Direct link to Step 4 Integrate into the device" title="Direct link to Step 4 Integrate into the device" translate="no">​</a></h2>
<p>For the thermometer, we just need to adjust its <code>MQTT</code> settings so that it can post <code>MQTT</code> messages to <code>EMQX</code>.</p>
<p>(For thermometers outside the cluster, we can open up <code>External IP</code> for access via <code>Kubernetes Service</code>)</p>
<img src="https://shifu.dev/blog-220610/5.png" width="100%">
<p>In terms of cameras, <em><strong>Shifu</strong></em>'s repository already includes a <a href="https://github.com/Edgenesis/shifu/tree/main/examples/rtspDeviceShifu/" target="_blank" rel="noopener noreferrer" class="">configuration file for Hikvision cameras using <code>RTSP</code></a> that we can simply change IP, username, password in the config file to integrate the camera into <em><strong>Shifu</strong></em>.</p>
<img src="https://shifu.dev/blog-220610/6.png" width="100%">
<img src="https://shifu.dev/blog-220610/7.png" width="100%">
<p>At this point, our device is connected and we are ready to start linking below.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="linking-applications">Linking Applications<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#linking-applications" class="hash-link" aria-label="Direct link to Linking Applications" title="Direct link to Linking Applications" translate="no">​</a></h2>
<p>We can write a <code>Python</code> application to implement the following logic.</p>
<p>The app subscribes to <code>EMQX</code>  <code>temperature-shifu-mqtt</code> messages, each message includes only a number refering the current temperature; if the current temperature is higher than 37 degrees, the camera is asked take a picture and save it locally.</p>
<p>The application code is as follows.</p>
<img src="https://shifu.dev/blog-220610/8.png" width="100%">
<p>Add a <code>capture function</code> to encapsulate all camera actions. Then we can deploy it to the cluster and start monitoring.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">python3 app.py 10.244.0.33</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220610/9.gif" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://shifu.dev/technical-blogs/2022/06/10/emqx#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>This article shows how to get <code>EMQX</code> to empower <em><strong>Shifu</strong></em> with more efficient <code>MQTT Broker</code> capabilities, and make <em><strong>Shifu</strong></em> to work with <code>MQTT</code> to provide linkage capabilities to devices. In a real-world application scenario, we can use a cheap combination of IR thermometer and camera to replace thousands of dollars of unstable temperature cameras, saving huge costs in a large-scale deployment scenario.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Deploy Shifu on KubeEdge]]></title>
        <id>https://shifu.dev/technical-blogs/2022/06/08/kubeedge</id>
        <link href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge"/>
        <updated>2022-06-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[The popular open source project KubeEdge provides developers with a cloud-edge collaboration solution based on Kubernetes. It successfully integrates the cluster orchestration capabilities of Kubernetes into the IoT edge scenario, making the scheduling and management of edge computing power lighter and more efficient.]]></summary>
        <content type="html"><![CDATA[<p>The popular open source project <code>KubeEdge</code> provides developers with a cloud-edge collaboration solution based on <code>Kubernetes</code>. It successfully integrates the cluster orchestration capabilities of <code>Kubernetes</code> into the IoT edge scenario, making the scheduling and management of edge computing power lighter and more efficient.</p>
<p>As an open source IoT development framework, <em><strong>Shifu</strong></em> is also based on <code>Kubernetes</code>, its compatibility with multiple devices and virtualization will help <code>KubeEdge</code> to be applied at the edge. In fact, the two complement each other very well in terms of capabilities. Not only compatible to multiple devices, <code>Shifu</code> running on <code>KubeEdge</code> can easily manage lightweight <code>Pod</code> running on the edge.</p>
<p>With the powerful combination of <code>KubeEdge</code> + <em><strong>Shifu</strong></em>, we can abstract IoT devices into <code>API</code> and turn the traditional complex IoT development model into a simple web development model!</p>
<p>Let's see how to make <em><strong>Shifu</strong></em> run on <code>KubeEdge</code> and provide value for developers!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="introduction">Introduction<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" translate="no">​</a></h2>
<p>This article will briefly describe the steps to deploy <em><strong>Shifu</strong></em> on <code>KubeEdge</code> and integrate into Hikvision camera (using <code>RTSP</code> for video streaming), so that <code>KubeEdge</code> architecture can support Hikvision camera.</p>
<p>The architecture used in this article is as follows.</p>
<img src="https://shifu.dev/blog-220608/1.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="preparation">Preparation<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#preparation" class="hash-link" aria-label="Direct link to Preparation" title="Direct link to Preparation" translate="no">​</a></h2>
<p>The following services and tools are used in this article.</p>
<ol>
<li class=""><code>Kubernetes</code>: 1.21.5<!-- -->
<ul>
<li class=""><code>kubectl</code></li>
<li class=""><code>kubeadm</code></li>
<li class=""><code>kubelet</code></li>
</ul>
</li>
<li class=""><code>Golang</code>: 1.16.10</li>
<li class=""><code>Docker</code>: 19.03.9</li>
<li class=""><code>KubeEdge</code>: 1.7.2</li>
</ol>
<p>Meanwhile, the <code>Cloud side</code> and <code>Edge side</code> of <code>KubeEdge</code> are running on separate <code>Linux</code> instances, but both on <code>Ubuntu Server 20.04</code> environment.</p>
<p>You need to install all the above mentioned services and tools on the <code>Cloud side</code> , but only <code>Docker</code> and <code>KubeEdge</code> on the <code>Edge side</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-deploy-kubernetes-on-the-cloud-side">Step 1 Deploy Kubernetes on the Cloud side<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#step-1-deploy-kubernetes-on-the-cloud-side" class="hash-link" aria-label="Direct link to Step 1 Deploy Kubernetes on the Cloud side" title="Direct link to Step 1 Deploy Kubernetes on the Cloud side" translate="no">​</a></h2>
<p>You can check <a href="https://kubernetes.io/docs/setup/" target="_blank" rel="noopener noreferrer" class="">official tutorial on Kubernetes</a> to finish the deployment.</p>
<p>After the deployment is complete we should see the terminal print out the following message.</p>
<img src="https://shifu.dev/blog-220608/2.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-deploy-shifu-on-cloud-side">Step 2 Deploy Shifu on Cloud side<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#step-2-deploy-shifu-on-cloud-side" class="hash-link" aria-label="Direct link to Step 2 Deploy Shifu on Cloud side" title="Direct link to Step 2 Deploy Shifu on Cloud side" translate="no">​</a></h2>
<p>Clone the <code>Github</code> repository of <em><strong>Shifu</strong></em> to your computer.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">git clone https://github.com/Edgenesis/shifu.git</span><br></span></code></pre></div></div>
<p>Then you can deploy <em><strong>Shifu</strong></em> with the following command:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f shifu/pkg/k8s/crd/install/shifu_install.yml</span><br></span></code></pre></div></div>
<p>Once deployed we should see that the <code>CRD controller</code> for <em><strong>Shifu</strong></em> has been deployed.</p>
<img src="https://shifu.dev/blog-220608/3.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-deploy-kubeedge-on-cloud-side">Step 3 Deploy KubeEdge on Cloud side<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#step-3-deploy-kubeedge-on-cloud-side" class="hash-link" aria-label="Direct link to Step 3 Deploy KubeEdge on Cloud side" title="Direct link to Step 3 Deploy KubeEdge on Cloud side" translate="no">​</a></h2>
<p>For this step, you can refer to <a href="https://kubeedge.io/zh/docs/setup/keadm/" target="_blank" rel="noopener noreferrer" class=""><code>KubeEdge</code>'s official tutorial</a> and use <code>keadm</code> for deployment.</p>
<p>After the deployment, we should see the following message printed on the terminal.</p>
<img src="https://shifu.dev/blog-220608/4.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4-get-the-token-on-the-cloud-side">Step 4 Get the token on the Cloud side<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#step-4-get-the-token-on-the-cloud-side" class="hash-link" aria-label="Direct link to Step 4 Get the token on the Cloud side" title="Direct link to Step 4 Get the token on the Cloud side" translate="no">​</a></h2>
<p>Run the following command.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">keadm gettoken</span><br></span></code></pre></div></div>
<p>Please save the <code>token</code> you got for the Edge side.</p>
<p>Now that the Cloud side configuration is completed, we switch to the Edge side machine and add it to the cluster.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-5-join-the-cluster-on-the-edge-side">Step 5 Join the cluster on the Edge side<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#step-5-join-the-cluster-on-the-edge-side" class="hash-link" aria-label="Direct link to Step 5 Join the cluster on the Edge side" title="Direct link to Step 5 Join the cluster on the Edge side" translate="no">​</a></h2>
<p>Run the following command on the Edge side.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">keadm join --cloudcore-ipport="&lt;Cloud-side advertise-address&gt;:10000" --token=&lt;token obtained in step 4&gt;</span><br></span></code></pre></div></div>
<p>After the deployment is complete we should see the terminal print out the following message.</p>
<img src="https://shifu.dev/blog-220608/5.png" width="100%">
<p>At this point switch back to the Cloud side and look at the nodes.</p>
<img src="https://shifu.dev/blog-220608/6.png" width="100%">
<p>We can see that both the Cloud side and the Edge side have been deployed.</p>
<p>Now we can start deploying the device.</p>
<p>With <code>KubeEdge</code>, we can perform <code>Kubernetes</code> operations only on the Cloud side and deploy it to the Edge side, while keeping the Edge side free of <code>Kubernetes</code> components to keep lightweight.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-6-modify-the-hikvision-camera-configuration-file-on-the-cloud-side">Step 6 Modify the Hikvision camera configuration file on the Cloud side<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#step-6-modify-the-hikvision-camera-configuration-file-on-the-cloud-side" class="hash-link" aria-label="Direct link to Step 6 Modify the Hikvision camera configuration file on the Cloud side" title="Direct link to Step 6 Modify the Hikvision camera configuration file on the Cloud side" translate="no">​</a></h2>
<p><em><strong>Shifu</strong></em> needs a simple configuration file to generate digital twin. In <em><strong>Shifu</strong></em>, the digital twin is called <em><strong>deviceShifu</strong></em> and runs in a cluster as <code>Pod</code>.</p>
<p><em><strong>Shifu</strong></em> provides configuration file  to access to Hikvision cameras, here's the path <code>https://github.com/Edgenesis/shifu/tree/main/examples/rtspDeviceShifu/</code>.</p>
<p><em><strong>Shifu</strong></em> deploys <em><strong>deviceShifu</strong></em> on a machine with a full <code>Kubernetes</code> instance by default. In a <code>KubeEdge</code> environment, there is no need to run full <code>Kubernetes</code> on the edge, so <em><strong>Shifu</strong></em> also has a lightweight <em><strong>deviceShifu</strong></em> for cloud-edge collaboration. We can change <code>deviceshifu-camera-deployment.yaml</code> to use the edge-side <em><strong>deviceShifu</strong></em> and add <code>nodeName</code> to deploy it to the <code>edge node</code>:</p>
<img src="https://shifu.dev/blog-220608/7.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-7-deploy-the-hikvision-camera-pod">Step 7 Deploy the Hikvision Camera Pod<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#step-7-deploy-the-hikvision-camera-pod" class="hash-link" aria-label="Direct link to Step 7 Deploy the Hikvision Camera Pod" title="Direct link to Step 7 Deploy the Hikvision Camera Pod" translate="no">​</a></h2>
<p>On the Cloud side, run the following command.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl apply -f shifu/examples/rtspDeviceShifu/camera-deployment</span><br></span></code></pre></div></div>
<p>At this point, we can look at the <code>Pod</code> associated with the camera.</p>
<img src="https://shifu.dev/blog-220608/8.png" width="100%">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="final-step-confirmation-on-the-edge-side">Final step Confirmation on the Edge side<a href="https://shifu.dev/technical-blogs/2022/06/08/kubeedge#final-step-confirmation-on-the-edge-side" class="hash-link" aria-label="Direct link to Final step Confirmation on the Edge side" title="Direct link to Final step Confirmation on the Edge side" translate="no">​</a></h2>
<p>On the Edge side, we can see that the camera-related Docker container is already running:</p>
<img src="https://shifu.dev/blog-220608/9.png" width="100%">
<p>We can simply call the <code>capture</code>/<code>stream</code>/<code>info</code>/<code>move</code> and a host of other <code>HTTP API</code>s provided by <em><strong>deviceShifu</strong></em> to perform operations on the camera, such as the following motion picture.</p>
<p>Related commands.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">curl edgedevice-camera/move</span><br></span></code></pre></div></div>
<img src="https://shifu.dev/blog-220608/10.gif" width="100%">
<p>This completes all the steps we need to run <em><strong>Shifu</strong></em> on <code>KubeEdge</code>.</p>]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Integrate a Private Driver]]></title>
        <id>https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver</id>
        <link href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver"/>
        <updated>2022-05-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[In this article, we will first write a GPIO driver to control LED using Python, and then connect it to Shifu for interaction and management.]]></summary>
        <content type="html"><![CDATA[<p>In this article, we will first write a <code>GPIO</code> driver to control <code>LED</code> using <code>Python</code>, and then connect it to <em><strong>Shifu</strong></em> for interaction and management.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-the-driver">Create the driver<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#create-the-driver" class="hash-link" aria-label="Direct link to Create the driver" title="Direct link to Create the driver" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="objective">Objective<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#objective" class="hash-link" aria-label="Direct link to Objective" title="Direct link to Objective" translate="no">​</a></h3>
<ul>
<li class="">Complete simple LED circuit connection</li>
<li class="">Basic Raspberry Pi/SSH configuration</li>
<li class="">Basic Python syntax and knowledge of GPIO libraries</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="devices">Devices<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#devices" class="hash-link" aria-label="Direct link to Devices" title="Direct link to Devices" translate="no">​</a></h3>
<ul>
<li class="">Raspberry Pi <code>Raspberry Pi 3B+</code> running 64-bit <code>Raspberry Pi OS</code></li>
<li class="">1 breadboard</li>
<li class="">3 LED bulbs (red, yellow, green)</li>
<li class="">1 x 330 ohm resistor</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="basic-knowledge">Basic knowledge<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#basic-knowledge" class="hash-link" aria-label="Direct link to Basic knowledge" title="Direct link to Basic knowledge" translate="no">​</a></h3>
<ul>
<li class="">Simple Python syntax</li>
<li class="">Basic Linux command line operations (create files, install apps, SSH, run programs)</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-circuit-design">Step 1 Circuit design<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-1-circuit-design" class="hash-link" aria-label="Direct link to Step 1 Circuit design" title="Direct link to Step 1 Circuit design" translate="no">​</a></h3>
<p>First let's design the circuit. We need to design a circuit that will allow the <code>GPIO</code> output of the Raspberry Pi to control the on/off of a single LED bulb. In this article, we have used the most straightforward approach, i.e., using <code>GPIO</code> directly to power the LED bulbs.</p>
<p>The circuit diagram is as follows.</p>
<img src="https://shifu.dev/blog-220507/1.png" width="50%">
<p>The <code>GPIO</code> pins 22, 23, and 19 control the red, green, and yellow LEDs respectively. 330 ohms resistors are connected in series at the end to prevent the LEDs from burning out due to excessive current.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-circuit-implementation">Step 2 Circuit Implementation<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-2-circuit-implementation" class="hash-link" aria-label="Direct link to Step 2 Circuit Implementation" title="Direct link to Step 2 Circuit Implementation" translate="no">​</a></h3>
<p>According to the Pin Layout in the official <code>Raspberry Pi</code> documentation, we can see the exact location of the pins, here pins 15, 16, 35 and 39 are used.</p>
<img src="https://shifu.dev/blog-220507/2.png" width="100%">
<p>Connect these four pins to the female port of the cable, and then connect the remaining circuits on the breadboard too.</p>
<img src="https://shifu.dev/blog-220507/3.png" width="100%">
<p>The red, green, yellow, and gray cables in the diagram correspond to <code>GPIO22</code> <code>GPIO23</code> <code>GPIO19</code> and ground, respectively.</p>
<img src="https://shifu.dev/blog-220507/4.png" width="50%">
<img src="https://shifu.dev/blog-220507/5.png" width="50%">
<p>This concludes the circuit design and connectivity section.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-raspberry-pi-preparation">Step 3 Raspberry Pi Preparation<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-3-raspberry-pi-preparation" class="hash-link" aria-label="Direct link to Step 3 Raspberry Pi Preparation" title="Direct link to Step 3 Raspberry Pi Preparation" translate="no">​</a></h3>
<p>First install an operating system in the Raspberry Pi, the one used in this article is <code>Raspberry Pi OS (64-bit)</code>. <a href="https://www.raspberrypi.com/software/operating-systems/#raspberry-pi-os-64-bit" target="_blank" rel="noopener noreferrer" class="">download link</a></p>
<p>Insert the SD card into the reader, connect it to the USB port of your computer, and then swipe the downloaded zip file into the SD card via <code>balenaEtcher</code>. <a href="https://www.balena.io/etcher/" target="_blank" rel="noopener noreferrer" class="">balenaEtcher link</a></p>
<p>Insert the SD card into the Raspberry Pi, plug in the power and monitor cable, and we can start the configuration.</p>
<p>First, for development/debugging we need to enable SSH, open a terminal from the desktop and enter <code>sudo raspi-config</code> to access the configuration screen and select <code>Interface Options</code>.</p>
<img src="https://shifu.dev/blog-220507/6.png" width="100%">
<p>Select <code>SSH</code>:</p>
<img src="https://shifu.dev/blog-220507/7.png" width="100%">
<p>Press enter, then press left to select <code>Yes</code> to enable the SSH service: <img src="https://shifu.dev/blog-220507/7.png"></p>
<img src="https://shifu.dev/blog-220507/8.png" width="100%">
<p>After that, press right and select <code>Finish</code>, then enter to exit.</p>
<img src="https://shifu.dev/blog-220507/9.png" width="100%">
<p>At this point, the SSH service is on, but we need to know the IP of the Raspberry Pi in order to SSH, so we can check it with the built-in <code>ip addr</code> command.</p>
<img src="https://shifu.dev/blog-220507/10.png" width="100%">
<p>As you can see, the IP address is <code>192.168.15.122</code>.</p>
<p>Back in the computer, you can remotely access the Raspberry Pi from the command line via <code>ssh pi@192.168.15.122</code></p>
<img src="https://shifu.dev/blog-220507/11.png" width="100%">
<p>This concludes the preparation of the Raspberry Pi and the hardware.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>Earlier versions of the Raspberry Pi OS may need to manually enable GPIO</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4-write-a-driver">Step 4 Write a Driver<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-4-write-a-driver" class="hash-link" aria-label="Direct link to Step 4 Write a Driver" title="Direct link to Step 4 Write a Driver" translate="no">​</a></h3>
<p>Everything is in place, now let's write the first driver!</p>
<p>First make sure that <code>Python</code> is installed on your system, if not you can run the following command.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ sudo apt-get update &amp;&amp; sudo apt install python3 -y</span><br></span></code></pre></div></div>
<p>After installation, you can check the status of the installation with <code>python -V</code>, if it shows the version, then the installation is successful:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ python -V</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Python 3.9.2</span><br></span></code></pre></div></div>
<p>Next let's start with an LED bulb control, we want to control the red LED on/off using the following code.</p>
<img src="https://shifu.dev/blog-220507/12.png" width="100%">
<p>The modules used in the driver are:</p>
<ul>
<li class=""><code>RPi.GPIO</code> to control the GPIO of the Raspberry Pi</li>
<li class=""><code>argparse</code> is used to parse command line input</li>
</ul>
<p>First set the GPIO mode to <code>GPIO.BCM</code> mode, in this mode the pin numbers are the GPIO numbers, not the pin order on the Raspberry Pi board.</p>
<p><code>GPIO.setmode(GPIO.BCM)</code></p>
<p>Then turn the warning off, the Raspberry Pi will only be controlled only by this driver in this article.</p>
<p><code>GPIO.setwarnings(False)</code></p>
<p>Next process the program input, this driver will accept two inputs.</p>
<ol>
<li class=""><code>-p</code>, <code>--port</code>, representing the GPIO pin that the program is manipulating</li>
<li class=""><code>-o</code>, <code>--operate</code>, represents the program's operation of the GPIO pin, <code>on</code> represents <code>1</code>, i.e. <code>3.3V</code> in the circuit, <code>off</code> represents <code>0</code>, i.e. <code>0V</code> in the circuit</li>
</ol>
<p>The code is as follows</p>
<div class="language-py codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-py codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">parser </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> argparse</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">ArgumentParser</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">parser</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">add_argument</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"-p"</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)">"--pin"</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)">type</span><span class="token operator" style="color:rgb(137, 221, 255)">=</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"> default</span><span class="token operator" style="color:rgb(137, 221, 255)">=</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 class="token builtin" style="color:rgb(130, 170, 255)">help</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"Specify the GPIO pin to operate, e.g.: '17'"</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">parser</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">add_argument</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"-o"</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)">"--operate"</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)">type</span><span class="token operator" style="color:rgb(137, 221, 255)">=</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"> default</span><span class="token operator" style="color:rgb(137, 221, 255)">=</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 class="token builtin" style="color:rgb(130, 170, 255)">help</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"Specify the GPIO output, e.g.: 'on/off'"</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">args </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">parse_args</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></div>
<p>Next we need to handle errors, passing the arguments into the function <code>turnOnLed</code> to operate when the pin count and operation are not empty, otherwise printing a warning</p>
<div class="language-py codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-py codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">pin </span><span class="token keyword" style="font-style:italic">and</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">operate</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">    turnOnLed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">pin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> args</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">operator</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">else</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">print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"need to specify both pin and operate arguments, type --help for more information"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<p>The main part of the program ends, so let's look at the function <code>turnOnLed</code> that controls the LED bulb.</p>
<p>The first thing is to determine whether the <code>operate</code> variable is <code>on</code> or <code>off</code>, otherwise it returns. The output variable <code>gpio_out</code> is set to <code>GPIO.HIGH</code> when the variable is <code>on</code> and to <code>GPIO.LOW</code> when it is <code>off</code>.</p>
<p>These two values represent on or off.</p>
<div class="language-py codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-py codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">if</span><span class="token plain"> operate </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)">"on"</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">    gpio_out </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">HIGH</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">elif</span><span class="token plain"> operate </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)">"off"</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">    gpio_out </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> GPIO</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">LOW</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">else</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">print</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">"operate is neither on/off, quitting..."</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><br></span></code></pre></div></div>
<p>The last thing is to set the mode of the pin to output: <code>GPIO.setup(pin, GPIO.OUT)</code></p>
<p>and switch the pin's output to on/off: <code>GPIO.output(pin, gpio_out)</code></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="outcome">Outcome<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#outcome" class="hash-link" aria-label="Direct link to Outcome" title="Direct link to Outcome" translate="no">​</a></h3>
<p>The program can be executed using <code>python led_driver.py -p {pin #} -o {operate}</code></p>
<p>If we want to make the red bulb light up, we run <code>python led_driver.py -p 22 -o on</code></p>
<img src="https://shifu.dev/blog-220507/13.gif" width="100%">
<p>And that's it, a simple control LED bulb driver for Raspberry Pi!</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>This driver essentially manipulates Raspberry Pi GPIO pin, so we can also use this driver to manipulate any circuit that can be controlled by 3.3V, and the pins are not limited to 22, 23 and 19 in this article. You can use your imagination to create a variety of test circuits.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="integrate-into-shifu">Integrate into Shifu<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#integrate-into-shifu" class="hash-link" aria-label="Direct link to Integrate into Shifu" title="Direct link to Integrate into Shifu" translate="no">​</a></h2>
<p>Next, we use the driver we wrote to access the <em><strong>Shifu</strong></em> framework for interaction and management.</p>
<p>The <em><strong>Shifu</strong></em> architecture in this article is as follows.</p>
<img src="https://shifu.dev/blog-220507/connect-0.jpeg" width="100%">
<p>The northbound opens up the <code>HTTP</code> API interface via <code>deviceshifu-http-http</code> and the southbound interacts with the actual device via <code>rpio-gpio-driver</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="objectives">Objectives<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#objectives" class="hash-link" aria-label="Direct link to Objectives" title="Direct link to Objectives" translate="no">​</a></h3>
<ol>
<li class="">install k3s cluster on Raspberry Pi and install Shifu Framework</li>
<li class="">package the Raspberry Pi LED driver to a container image</li>
<li class="">deploy the digital twin of the Raspberry Pi LED in Shifu</li>
<li class="">Achieve remote automation control of Raspberry Pi LEDs</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="devices-1">Devices<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#devices-1" class="hash-link" aria-label="Direct link to Devices" title="Direct link to Devices" translate="no">​</a></h3>
<ul>
<li class="">Raspberry Pi <code>Raspberry Pi 3B+</code> running 64-bit <code>Raspberry Pi OS</code></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="basic-knowledge-1">Basic knowledge<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#basic-knowledge-1" class="hash-link" aria-label="Direct link to Basic knowledge" title="Direct link to Basic knowledge" translate="no">​</a></h3>
<ul>
<li class="">basic operation of Docker/containerd</li>
<li class="">basic operation of K8s/K3s</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-install-k3s">Step 1 Install k3s<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-1-install-k3s" class="hash-link" aria-label="Direct link to Step 1 Install k3s" title="Direct link to Step 1 Install k3s" translate="no">​</a></h3>
<p>First we need to run a <code>Kubernetes cluster</code> in the Raspberry Pi. There is no restriction on the version users can use here, but to save resources we use <code>k3s</code> in this article. <a href="https://rancher.com/docs/k3s/latest/en/quick-start/" target="_blank" rel="noopener noreferrer" class="">Installation Tutorial</a></p>
<p>After installation, run <code>kubectl version</code> to see the current <code>Kubernetes</code> version.</p>
<img src="https://shifu.dev/blog-220507/connect-1.png" width="100%">
<p>Use <code>kubectl get nodes</code> to see the status of the current cluster, showing <code>Ready</code> means the cluster is available:</p>
<img src="https://shifu.dev/blog-220507/connect-2.png" width="100%">
<p>At this point, the <code>k3s</code> installation is complete.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-install-shifu">Step 2 Install Shifu<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-2-install-shifu" class="hash-link" aria-label="Direct link to Step 2 Install Shifu" title="Direct link to Step 2 Install Shifu" translate="no">​</a></h3>
<p>First clone the <em><strong>Shifu</strong></em> project repository on your computer:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">$ git clone https://github.com/Edgenesis/shifu.git</span><br></span></code></pre></div></div>
<p>You can deploy <em><strong>Shifu</strong></em> to the <code>k3s</code> cluster with one click by using <code>kubectl apply -f shifu/pkg/k8s/crd/install/shifu_install.yml</code>.</p>
<img src="https://shifu.dev/blog-220507/connect-3.png" width="100%">
<p>Execute <code>kubectl get pods -A</code> again to see the <code>Shifu Framework</code> controller deployed to the cluster: <img src="https://shifu.dev/blog-220507/connect-3.png"></p>
<img src="https://shifu.dev/blog-220507/connect-4.png" width="100%">
<p>We can also manage device resources (currently there are no devices) via <code>edgedevices</code> the <code>CRD</code>: <img src="https://shifu.dev/blog-220507/connect-4.png"></p>
<img src="https://shifu.dev/blog-220507/connect-5.png" width="100%">
<p>At this point,  <em><strong>Shifu</strong></em> is successfully installed.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-package-the-driver">Step 3 Package the driver<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-3-package-the-driver" class="hash-link" aria-label="Direct link to Step 3 Package the driver" title="Direct link to Step 3 Package the driver" translate="no">​</a></h3>
<p>We need to use a small tool provided by <em><strong>Shifu</strong></em> to realize that we can manipulate the local driver remotely, for a detailed tutorial please see.</p>
<ul>
<li class="">New version: <a href="https://github.com/Edgenesis/shifu/tree/main/cmd/httpstub/sshstub" target="_blank" rel="noopener noreferrer" class="">https://github.com/Edgenesis/shifu/tree/main/cmd/httpstub/sshstub</a></li>
<li class="">Older version: <a href="https://github.com/Edgenesis/shifu/tree/c0cab1ce98870eb470ddc9e01e1d99c13b611411/driver_util" target="_blank" rel="noopener noreferrer" class="">https://github.com/Edgenesis/shifu/tree/c0cab1ce98870eb470ddc9e01e1d99c13b611411/driver_util</a></li>
</ul>
<p>This tool helps to convert HTTP requests sent by the user/program to a local command line for execution.</p>
<p>A sample driver is provided inside the tutorial at <a href="https://github.com/Edgenesis/shifu/blob/main/examples/driver_utils/simple-alpine/Dockerfile.sample" target="_blank" rel="noopener noreferrer" class="">https://github.com/Edgenesis/shifu/blob/main/examples/driver_utils/simple-alpine/Dockerfile.sample</a></p>
<p>The content is as follows.</p>
<img src="https://shifu.dev/blog-220507/connect-6.png" width="100%">
<p>You can see that the <code>Dockerfile</code> has two parts, the first is to use the <code>golang</code> image to compile the <code>http_to_ssh_stub.go</code> provided by <em><strong>Shifu</strong></em> to convert HTTP command to SSH command. The next step is to use an empty <code>alpine</code> image to configure SSH for demonstration.</p>
<p>Next let's practice it.</p>
<p>Considering the limitations of Raspberry Pi, this compilation will be executed from the computer side, and the compiled image will be pushed to <code>Docker Hub</code> for remote invocation.</p>
<p>First, we create a new folder, here we use <code>dev</code>, and then save the created Raspberry Pi LED driver to this directory:.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">dev/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">└── led_driver.py</span><br></span></code></pre></div></div>
<p>The driver content remains the same.</p>
<img src="https://shifu.dev/blog-220507/connect-7.png" width="100%">
<p>Copy <code>Dockerfile.sample</code> from the <code>driver_util/examples/simple-alpine/</code> directory of the <em><strong>Shifu</strong></em> project to the <code>dev</code> directory.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">dev/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├── Dockerfile.sample</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">└── led_driver.py</span><br></span></code></pre></div></div>
<p>Change the following fields to change the second part of the image from <code>alpine</code> to <code>python:alpine</code>, install the <code>Python</code> library for <code>RPi.GPIO</code></p>
<p>Finally, copy the <code>Python driver</code> into the run container, and the new <code>Dockerfile</code> will look like this, with the changes marked with comments.</p>
<div class="language-Dockerfile language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">FROM golang:1.17.1 as builder</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">WORKDIR /</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">ENV GOPROXY=https://goproxy.cn,direct</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">ENV GO111MODULE=on</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">ENV GOPRIVATE=github.com/Edgenesis</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">COPY driver_util driver_util</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">WORKDIR /driver_util</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">RUN go mod download</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"># Build the Go app</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">RUN CGO_ENABLED=0 GOOS=$(go env GOOS) GOARCH=$(go env GOARCH) gobuild -a -o /output/http2ssh-stub http_to_ssh_stub.go</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">FROM python:alpine # modified</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">RUN apk add --no-cache --update openrc openssh \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; mkdir -p /run/openrc \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; touch /run/openrc/softlevel \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; sed -ie "s/#PubkeyAuthentication/PubkeyAuthentication/g"/etc/ssh/sshd_config \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; sed -ie "s/#PasswordAuthenticationyes/PasswordAuthentication no/g" /etc/ssh/sshd_config \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; sed -ie "s/AllowTcpForwardingno/AllowTcpForwarding yes/g" /etc/ssh/sshd_config \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; echo"PubkeyAcceptedKeyTypes=+ssh-rsa" &gt;&gt;  /etc/ssh/ sshd_config\  # modified</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; ssh-keygen -A \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; passwd -d root \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; mkdir ~/.ssh \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; while ! [ -e/etc/ssh/ssh_host_rsa_key.pub ]; do sleep 1; done \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; cp /etc/ssh/ssh_host_rsa_key.pub~/.ssh/authorized_keys</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">RUN apk add --no-cache -Uu --virtual .build-dependencies libffi-devopenssl-dev build-base musl \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; pip3 install --no-cache --upgrade RPi.GPIO\</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; apk del --purge .build-dependencies \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; apk add --no-cache --purge curlca-certificates musl \</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    &amp;&amp; rm -rf /var/cache/apk/* /tmp/*  # modified</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">WORKDIR /root/</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">COPY --from=builder /output/http2ssh-stub http2ssh-stub</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">COPY --from=builder/driver_util/examples/simple-alpine/docker-entrypoint.sh docker-entrypoint.sh</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">COPY dev/led_driver.py led_driver.py  # modified</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">RUN chmod +x docker-entrypoint.sh</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"># Command to run the executable</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">ENTRYPOINT ["./docker-entrypoint.sh"]</span><br></span></code></pre></div></div>
<p>Next we will package the Docker image, because the CPU of the Raspberry Pi is <code>ARM64</code> processor, the computer used for compiling in this article is <code>x86-64</code>, so we need to use the <code>buildx</code> function of <code>Docker</code> to build the image, the tutorial about buildx will not be described in this article, you can move to <a href="https://docs.docker.com/buildx/working-with-buildx/" target="_blank" rel="noopener noreferrer" class="">https://docs.docker.com/buildx/working-with-buildx/</a>.</p>
<p>Use <code>docker buildx build --platform=linux/arm64 -f dev/Dockerfile.sample . -t edgehub/rpi-gpio-driver:v0.0.1 --push</code> to build the image and push it to <code>Docker Hub</code>.</p>
<p>At this point, the image packaging part is complete.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4-deploy-device-twin-to-raspberry-pi">Step 4 Deploy device twin to Raspberry Pi<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#step-4-deploy-device-twin-to-raspberry-pi" class="hash-link" aria-label="Direct link to Step 4 Deploy device twin to Raspberry Pi" title="Direct link to Step 4 Deploy device twin to Raspberry Pi" translate="no">​</a></h3>
<p>Once we have the image, we can deploy the digital twin to the cluster, so let's prepare the files we need for the deployment.</p>
<p>First is a <code>Kuberenetes Deployment YAML</code> file to run <em><strong>deviceShifu</strong></em> and the driver <code>Pod</code>.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> deviceshifu-rpi-gpio-deployment.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> apps/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"> Deployment</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">labels</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> default</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">replicas</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 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">matchLabels</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">template</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">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">labels</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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">containers</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">image</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> edgehub/deviceshifu</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">http</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">v0.0.1</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"> deviceshifu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">http</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">containerPort</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)">8080</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">volumeMounts</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">mountPath</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)">"/etc/edgedevice/config"</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">readOnly</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">env</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"> EDGEDEVICE_NAME</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">value</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)">"edgedevice-rpi-gpio"</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"> EDGEDEVICE_NAMESPACE</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">value</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)">"devices"</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">image</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> edgehub/rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">driver</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">v0.0.1</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"> driver</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">volumeMounts</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">mountPath</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> /dev/gpiomem</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"> gpiomem</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">securityContext</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">privileged</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">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">containerPort</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)">11112</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">env</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"> EDGEDEVICE_DRIVER_SSH_KEY_PATH</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">value</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)">"/etc/ssh/ssh_host_rsa_key"</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"> EDGEDEVICE_DRIVER_HTTP_PORT</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">value</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)">"11112"</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"> EDGEDEVICE_DRIVER_EXEC_TIMEOUT_SECOND</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">value</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)">"5"</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"> EDGEDEVICE_DRIVER_SSH_USER</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token key atrule">value</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)">"root"</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">volumes</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">configMap</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"> rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">configmap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">0.0.1</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"> gpiomem</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token key atrule">hostPath</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">path</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> /dev/gpiomem</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token key atrule">serviceAccountName</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">sa</span><br></span></code></pre></div></div></div></div></details>
<p>Please note that in the Deployment file we need to add <code>privileged: true</code> to the container's <code>securityContext</code>, so that we can use the Raspberry Pi's GPIO in the container, then mount the Raspberry Pi's <code>/dev/gpiomem</code> to the container as volume.</p>
<p>Write a <code>Kubernetes Service YAML</code> file to proxy requests from the <em><strong>deviceShifu</strong></em> to the real <code>Pod</code> from the domain.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> deviceshifu-rpi-gpio-service.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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">labels</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> default</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">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">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><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">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)">8080</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">deployment</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"> LoadBalancer</span><br></span></code></pre></div></div></div></div></details>
<p>A <code>Kubernetes ConfigMap YAML</code> file to configure <em><strong>deviceShifu</strong></em>.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> deviceshifu-rpi-gpio-configmap.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> ConfigMap</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"> rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">configmap</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> default</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">data</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">driverProperties</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 scalar string" style="color:rgb(195, 232, 141)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    driverSku: RaspberryPiB+</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    driverImage: edgenesis/rpi-gpio-python:v0.0.1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    driverExecution: "python led_driver.py"</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">instructions</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 scalar string" style="color:rgb(195, 232, 141)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    pin:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    operate:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    help:</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"># Telemetries are configurable health checks of the EdgeDevice</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"># Developer/user can configure certain instructions to be usedas health check # of the device.</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"># of the device. In this example, the device_health telemetry ismapped to</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"># "get_status" instruction, executed every 1000 ms</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">telemetries</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 scalar string" style="color:rgb(195, 232, 141)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">    device_health:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">      properties:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">        instruction: help</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">        initialDelayMs: 1000</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token scalar string" style="color:rgb(195, 232, 141)">        intervalMs: 1000</span><br></span></code></pre></div></div></div></div></details>
<p>In <code>ConfigMap</code> we need to configure the execution path of the driver, because we put the Python file directly under the default path when generating the image, just fill in <code>python led_driver.py</code> here. If the driver is a binary file, you can directly fill in the binary directory here.</p>
<p>Write a <code>Shifu EdgeDevice YAML</code> file to generate the device twin.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary> edgedevice-rpi-gpio-edgedevice.yaml </summary><div><div class="collapsibleContent_i85q"><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><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"> shifu.edgenesis.io/v1alpha1</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"> EdgeDevice</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"> edgedevice</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">rpi</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">gpio</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> devices</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">sku</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)">"RaspberryPi 3B+"</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">connection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Ethernet</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> 0.0.0.0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token number" style="color:rgb(247, 140, 108)">11112</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">protocol</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> HTTPCommandline</span><br></span></code></pre></div></div></div></div></details>
<p>Put these four files into the Raspberry Pi with the following directory contents.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">led-deploy/</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├──deviceshifu-rpi-gpio-configmap.yaml</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├──deviceshifu-rpi-gpio-deployment.yaml</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">├──deviceshifu-rpi-gpio-service.yaml</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">└──edgedevice-rpi-gpio-edgedevice.yaml</span><br></span></code></pre></div></div>
<p>Use <code>kubectl apply -f &lt;dir&gt;</code> to deploy <em><strong>deviceShifu</strong></em> to the <code>k3s</code> cluster:</p>
<img src="https://shifu.dev/blog-220507/connect-8.png" width="100%">
<p>Then check the running status with <code>kubectl get pods</code>.</p>
<img src="https://shifu.dev/blog-220507/connect-9.png" width="100%">
<p>View all device twins in the cluster with <code>kubectl get edgedevices -n devices</code>.</p>
<img src="https://shifu.dev/blog-220507/connect-10.png" width="100%">
<p>To see the details of the digital twin via <code>describe</code>.</p>
<img src="https://shifu.dev/blog-220507/connect-11.png" width="100%">
<p>Next we can interact with the device, where we deploy an <code>nginx</code> container to represent the application in a real-world scenario
The deployment command is <code>kubectl run nginx --image=nginx</code></p>
<p>Then execute <code>kubectl exec -it nginx -- bash</code> to get to the <code>nginx</code> command line</p>
<img src="https://shifu.dev/blog-220507/connect-12.png" width="100%">
<p>Finally, using <code>curl</code> to send commands to the device, the driver accepts commands in the format: <code>python led_driver --pin &lt;x&gt; --operate &lt;on/off&gt;</code></p>
<p>Using <em><strong>Shifu</strong></em> to send commands will convert from HTTP to command line, the request address is written as: <code>http://edgedevice-rpi-gpio/pin?flags_no_parameter=&lt;pin&gt;,--operate,&lt;on/off&gt;</code></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="outcome-1">Outcome<a href="https://shifu.dev/technical-blogs/2022/05/07/connect-private-driver#outcome-1" class="hash-link" aria-label="Direct link to Outcome" title="Direct link to Outcome" translate="no">​</a></h3>
<p>The program can control the LED bulb on/off by sending an HTTP request directly to the device's domain name.</p>
<img src="https://shifu.dev/blog-220507/connect-13.gif" width="100%">
<p>At this point, we have successfully plugged the Raspberry Pi driver into <em><strong>Shifu</strong></em>.</p>]]></content>
    </entry>
</feed>