<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Untitled RSS Feed]]></title><description><![CDATA[Untitled RSS Feed]]></description><link>http://itmx.cc/</link><image><url>http://itmx.cc/favicon.png</url><title>Untitled RSS Feed</title><link>http://itmx.cc/</link></image><generator>Ghost 1.26</generator><lastBuildDate>Thu, 20 Nov 2025 09:51:35 GMT</lastBuildDate><atom:link href="http://itmx.cc/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[DELL R730xd esxi 6.7u3 升级 esxi 7.0.0u3]]></title><description><![CDATA[<div class="kg-card-markdown"><p>从dell官网下载VMware ESXi 7.0 U3升级包https://www.dell.com/support/product-details/en-us/servicetag/0-bE4vNUxpd2JQNHViYW5GaGRhZ0lodz090/drivers<br>
<img src="http://itmx.cc/content/images/2025/11/1763629246995-1.jpg" alt="1763629246995-1"></p>
<p>将文件存入数据存储，并记住位置</p>
<p>然后通过ssh登录esxi执行命令</p>
<h1 id>查看升级包里面的内容</h1>
<p>esxcli software sources profile list -d /vmfs/volumes/SSD/VMware-VMvisor-Installer-7.0.0.update03-20328353.x86_64-Dell_Customized-A09.zip</p>
<h1 id>执行升级</h1>
<p>esxcli software profile update -d /vmfs/volumes/SSD/VMware-VMvisor-Installer-7.0.0.update03-20328353.x86_64-Dell_</p></div>]]></description><link>http://itmx.cc/dell-r730xd-esxi-6-7u3-sheng-ji-esxi-7-0-0u3/</link><guid isPermaLink="false">691ed8a565328d0001396007</guid><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Thu, 20 Nov 2025 09:01:04 GMT</pubDate><media:content url="http://itmx.cc/content/images/2025/11/1763629246995.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="http://itmx.cc/content/images/2025/11/1763629246995.jpg" alt="DELL R730xd esxi 6.7u3 升级 esxi 7.0.0u3"><p>从dell官网下载VMware ESXi 7.0 U3升级包https://www.dell.com/support/product-details/en-us/servicetag/0-bE4vNUxpd2JQNHViYW5GaGRhZ0lodz090/drivers<br>
<img src="http://itmx.cc/content/images/2025/11/1763629246995-1.jpg" alt="DELL R730xd esxi 6.7u3 升级 esxi 7.0.0u3"></p>
<p>将文件存入数据存储，并记住位置</p>
<p>然后通过ssh登录esxi执行命令</p>
<h1 id>查看升级包里面的内容</h1>
<p>esxcli software sources profile list -d /vmfs/volumes/SSD/VMware-VMvisor-Installer-7.0.0.update03-20328353.x86_64-Dell_Customized-A09.zip</p>
<h1 id>执行升级</h1>
<p>esxcli software profile update -d /vmfs/volumes/SSD/VMware-VMvisor-Installer-7.0.0.update03-20328353.x86_64-Dell_Customized-A09.zip -p DEL-ESXi-703_20328353-A09</p>
<h1 id>若显示成功，则重启生效</h1>
<p>reboot</p>
<p>此时UI界面还未更新到7.0的版本，esxi 7.0之后要在broadcom下载：<a href="https://support.broadcom.com/group/ecx/solutionfiles?displayGroup=VMware%20vSphere%20-%20Enterprise&amp;os=&amp;release=7.0&amp;solution=VMware%20vSphere%20-%20Enterprise&amp;subfamily=VMware%20vSphere&amp;freeDownloads=true">https://support.broadcom.com/group/ecx/solutionfiles?displayGroup=VMware vSphere - Enterprise&amp;os=&amp;release=7.0&amp;solution=VMware vSphere - Enterprise&amp;subfamily=VMware vSphere&amp;freeDownloads=true</a></p>
<p>因为服务器现在运行的已经是7.0版本了，可以直接选择最新版本进行下载https://support.broadcom.com/web/ecx/solutiondetails?patchId=15940，试过6.7u3直接升7.0U3w是不支持的</p>
<p>下载后，使用同样的指令进行升级<br>
esxcli software sources profile list -d /vmfs/volumes/SSD/VMware-ESXi-7.0U3w-24784741-depot.zip<br>
esxcli software profile update -d /vmfs/volumes/SSD/VMware-ESXi-7.0U3w-24784741-depot.zip -p ESXi-7.0U3w-24784741-standard<br>
升级成功后，重启即可生效<br>
reboot</p>
<p>激活esxi 7<br>
网上试过的许可：<br>
JA0W8-AX216-08E19-A995H-1PHH2<br>
JU45H-6PHD4-481T1-5C37P-1FKQ2<br>
1U25H-DV05N-H81Y8-7LA7P-8P0N4<br>
HV49K-8G013-H8528-P09X6-A220A<br>
1G6DU-4LJ1K-48451-3T0X6-3G2MD 我用的这个<br>
5U4TK-DML1M-M8550-XK1QP-1A052</p>
<p>参考链接：<br>
<a href="https://zhuanlan.zhihu.com/p/564990618">https://zhuanlan.zhihu.com/p/564990618</a> 如何将VMWare ESXi 6.7升级版本到7.0？<br>
<a href="https://zhuanlan.zhihu.com/p/557061355">https://zhuanlan.zhihu.com/p/557061355</a> ESXI 7.0 注册机 许可证分配<br>
<a href="https://knowledge.broadcom.com/external/article/372545/download-esxi-patch-and-the-isos-for-lat.html#mcetoc_1irp2msto3">https://knowledge.broadcom.com/external/article/372545/download-esxi-patch-and-the-isos-for-lat.html#mcetoc_1irp2msto3</a></p>
<p>历史esxi版本号：<a href="https://knowledge.broadcom.com/external/article?legacyId=2143832">https://knowledge.broadcom.com/external/article?legacyId=2143832</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[SVG动画示例]]></title><description><![CDATA[<div class="kg-card-markdown"><pre><code>		&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; preserveAspectRatio=&quot;none&quot; viewBox=&quot;-540 -900 1080 1800&quot;
			style=&quot;display: block; margin: 0 auto; max-width: none !important;&quot; width=&quot;100%&quot;&gt;
			&lt;g&gt;
				&lt;!------------------------ 【倒计时停止】 ------------------------&gt;
				&lt;g data-author=&quot;</code></pre></div>]]></description><link>http://itmx.cc/svgdong-hua-shi-li/</link><guid isPermaLink="false">628da52276e76e0001038fda</guid><category><![CDATA[html]]></category><category><![CDATA[web]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Wed, 25 May 2022 03:42:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><pre><code>		&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; preserveAspectRatio=&quot;none&quot; viewBox=&quot;-540 -900 1080 1800&quot;
			style=&quot;display: block; margin: 0 auto; max-width: none !important;&quot; width=&quot;100%&quot;&gt;
			&lt;g&gt;
				&lt;!------------------------ 【倒计时停止】 ------------------------&gt;
				&lt;g data-author=&quot;懂点君·梦幻雪冰&quot;&gt;
					&lt;foreignObject x=&quot;-540&quot; y=&quot;-900&quot; width=&quot;1080&quot; height=&quot;1800&quot;&gt; &lt;svg height=&quot;1800&quot;
							style=&quot;display: block; background-image: url(https://images.weserv.nl/?url=https://mmbiz.qpic.cn/mmbiz_png/JpraGu7eGqTLC8ib9EnUSRQziaaicJ2fNFbibfOvzl8Vmg2xCibicnpDbKicDLu0PbrI9t1a5BqsGKrnDfWvvPdlwggYg/0?wx_fmt=png); background-size: 100% auto; background-repeat: no-repeat;&quot;
							width=&quot;1080&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;/svg&gt; &lt;/foreignObject&gt;
				&lt;/g&gt;
				&lt;g&gt;
					&lt;!------------------------ 【倒计时数字4】 ------------------------&gt;
					&lt;g data-author=&quot;懂点君·梦幻雪冰&quot;&gt;
						&lt;foreignObject x=&quot;-540&quot; y=&quot;-900&quot; width=&quot;1080&quot; height=&quot;1800&quot;&gt; &lt;svg height=&quot;1800&quot;
								style=&quot;display: block; background-image: url(https://images.weserv.nl/?url=https://mmbiz.qpic.cn/mmbiz_png/JpraGu7eGqTLC8ib9EnUSRQziaaicJ2fNFbjqzI3SAAW5GQukHl0HuZP2Lzvg1rlPqTCjouh2KEW9grbVkGuwlQhQ/0?wx_fmt=png); background-size: 100% auto; background-repeat: no-repeat;&quot;
								width=&quot;1080&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;/svg&gt; &lt;/foreignObject&gt;
						&lt;animateTransform calcMode=&quot;spline&quot; keySplines=&quot;0.42 0 0.58 1.0; 0.42 0 0.58 1.0&quot;
							restart=&quot;never&quot; begin=&quot;1.8s&quot; values=&quot;1; 0.90; 1.5;&quot; keyTimes=&quot;0; 0.3; 1&quot; dur=&quot;0.6s&quot;
							type=&quot;scale&quot; attributeName=&quot;transform&quot; fill=&quot;freeze&quot; additive=&quot;sum&quot;&gt;&lt;/animateTransform&gt;
						&lt;animate attributeName=&quot;opacity&quot; restart=&quot;never&quot; begin=&quot;2.0s&quot; dur=&quot;0.4s&quot; values=&quot;1; 0;&quot;
							keySplines=&quot;0.42 0 0.58 1.0&quot; fill=&quot;freeze&quot;&gt;&lt;/animate&gt;
						&lt;!------------------------ 【倒计时数字3】 ------------------------&gt;
						&lt;g data-author=&quot;懂点君·梦幻雪冰&quot;&gt;
							&lt;foreignObject x=&quot;-540&quot; y=&quot;-900&quot; width=&quot;1080&quot; height=&quot;1800&quot;&gt; &lt;svg height=&quot;1800&quot;
									style=&quot;display: block; background-image: url(https://images.weserv.nl/?url=https://mmbiz.qpic.cn/mmbiz_png/JpraGu7eGqTLC8ib9EnUSRQziaaicJ2fNFbqslMfFH9FrT1lODWRBbjxhNT6B4SXhnu09NC8JziaHkIfxLxFoia4BcA/0?wx_fmt=png); background-size: 100% auto; background-repeat: no-repeat;&quot;
									width=&quot;1080&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;/svg&gt; &lt;/foreignObject&gt;
							&lt;animateTransform calcMode=&quot;spline&quot; keySplines=&quot;0.42 0 0.58 1.0; 0.42 0 0.58 1.0&quot;
								restart=&quot;never&quot; begin=&quot;1.2s&quot; values=&quot;1; 0.90; 1.5;&quot; keyTimes=&quot;0; 0.3; 1&quot; dur=&quot;0.6s&quot;
								type=&quot;scale&quot; attributeName=&quot;transform&quot; fill=&quot;freeze&quot; additive=&quot;sum&quot;&gt;&lt;/animateTransform&gt;
							&lt;animate attributeName=&quot;opacity&quot; restart=&quot;never&quot; begin=&quot;1.4s&quot; dur=&quot;0.4s&quot; values=&quot;1; 0;&quot;
								keySplines=&quot;0.42 0 0.58 1.0&quot; fill=&quot;freeze&quot;&gt;&lt;/animate&gt;
							&lt;!------------------------ 【倒计时数字2】 ------------------------&gt;
							&lt;g data-author=&quot;懂点君·梦幻雪冰&quot;&gt;
								&lt;foreignObject x=&quot;-540&quot; y=&quot;-900&quot; width=&quot;1080&quot; height=&quot;1800&quot;&gt; &lt;svg height=&quot;1800&quot;
										style=&quot;display: block; background-image: url(https://images.weserv.nl/?url=https://mmbiz.qpic.cn/mmbiz_png/JpraGu7eGqTLC8ib9EnUSRQziaaicJ2fNFbrPxZDRRI785uc2nm4DARicBgDXWCFrAE1SzMCWTI6SOEgZS4WFrnb4A/0?wx_fmt=png); background-size: 100% auto; background-repeat: no-repeat;&quot;
										width=&quot;1080&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;/svg&gt; &lt;/foreignObject&gt;
								&lt;animateTransform calcMode=&quot;spline&quot; keySplines=&quot;0.42 0 0.58 1.0; 0.42 0 0.58 1.0&quot;
									restart=&quot;never&quot; begin=&quot;0.6s&quot; values=&quot;1; 0.90; 1.5;&quot; keyTimes=&quot;0; 0.3; 1&quot; dur=&quot;0.6s&quot;
									type=&quot;scale&quot; attributeName=&quot;transform&quot; fill=&quot;freeze&quot; additive=&quot;sum&quot;&gt;
								&lt;/animateTransform&gt;
								&lt;animate attributeName=&quot;opacity&quot; restart=&quot;never&quot; begin=&quot;0.8s&quot; dur=&quot;0.4s&quot; values=&quot;1; 0;&quot;
									keySplines=&quot;0.42 0 0.58 1.0&quot; fill=&quot;freeze&quot;&gt;&lt;/animate&gt;
								&lt;!------------------------ 【倒计时数字1】 ----------------------&gt;
								&lt;g data-author=&quot;懂点君·梦幻雪冰&quot;&gt;
									&lt;foreignObject x=&quot;-540&quot; y=&quot;-900&quot; width=&quot;1080&quot; height=&quot;1800&quot;&gt; &lt;svg height=&quot;1800&quot;
											style=&quot;display: block; background-image: url(https://images.weserv.nl/?url=https://mmbiz.qpic.cn/mmbiz_png/JpraGu7eGqTLC8ib9EnUSRQziaaicJ2fNFbqP026KVp9XZiaLFv1k0wnJKA8DIzibpjOqVC75TRpNrfRy81xpY5wXxA/0?wx_fmt=png); background-color: #000; background-size: 100% auto; background-repeat: no-repeat;&quot;
											width=&quot;1080&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;/svg&gt; &lt;/foreignObject&gt;
									&lt;!-- 缩放 --&gt;
									&lt;animateTransform calcMode=&quot;spline&quot; keySplines=&quot;0.42 0 0.58 1.0; 0.42 0 0.58 1.0&quot;
										keyTimes=&quot;0; 0.3; 1&quot; restart=&quot;never&quot; begin=&quot;0s&quot; values=&quot;1; 0.90; 1.5;&quot;
										dur=&quot;0.6s&quot; type=&quot;scale&quot; attributeName=&quot;transform&quot; fill=&quot;freeze&quot; additive=&quot;sum&quot;&gt;
									&lt;/animateTransform&gt; &lt;!-- 透明度 --&gt;
									&lt;animate attributeName=&quot;opacity&quot; restart=&quot;never&quot; begin=&quot;0.2s&quot; dur=&quot;0.4s&quot;
										values=&quot;1; 0;&quot; keySplines=&quot;0.42 0 0.58 1.0&quot; fill=&quot;freeze&quot;&gt;&lt;/animate&gt;
								&lt;/g&gt;
							&lt;/g&gt;
						&lt;/g&gt;
					&lt;/g&gt;
				&lt;/g&gt;
			&lt;/g&gt;
		&lt;/svg&gt;
</code></pre>
<p>代码注释：<br>
calcMode：该属性指定动画的插值模式。默认模式是线性的。<br>
additive：此属性规定是否将当前动画结束的状态作为下一次动画的起始状态 。<br>
restart：此属性指示何时动画可以或不能重新启动。<br>
fill：属性fill=&quot;freeze&quot;时，动画终止时，发生变化的元素属性值停留在动画终止时的状态；当fill=&quot;remove&quot;时，动画终止时，发生变化的元素属性值回复到动画起始时的状态。fill属性默认值为remove。</p>
<p>来源<br>
<a href="https://www.aisoutu.com/a/31374">公众号图文『SVG倒计时动效』模板代码</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[Centos 7 安装xface和xrdp]]></title><description><![CDATA[<div class="kg-card-markdown"><p><a href="https://www.cnblogs.com/chr-wonder/p/8464196.html">CentOS 使用 Xfce 桌面并通过 xrdp 登录</a></p>
</div>]]></description><link>http://itmx.cc/centos-7-an-zhuang-xfacehe-xrdp/</link><guid isPermaLink="false">600fc2419efa2300017c4899</guid><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Tue, 26 Jan 2021 07:20:10 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p><a href="https://www.cnblogs.com/chr-wonder/p/8464196.html">CentOS 使用 Xfce 桌面并通过 xrdp 登录</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[js清除当前站点所有域下的Cookie]]></title><description><![CDATA[<div class="kg-card-markdown"><pre><code>function delCookie () {
  var keys = document.cookie.match(/[^ =;]+(?==)/g)
  if (keys) {
    for (var i = keys.length; i--;) {
      document.cookie = keys[i] + '=0;path=/;expires=' + new Date(0).toUTCString() // 清除当前域名下的,例如：m.ratingdog.cn
      document.cookie = keys[i] + '=0;path=/;domain=' + document.domain + ';expires=' + new Date(</code></pre></div>]]></description><link>http://itmx.cc/qing-chu-dang-qian-zhan-dian-suo-you-yu-xia-de-cookie/</link><guid isPermaLink="false">5fa0fa549efa2300017c4894</guid><category><![CDATA[js]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Tue, 03 Nov 2020 06:37:23 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><pre><code>function delCookie () {
  var keys = document.cookie.match(/[^ =;]+(?==)/g)
  if (keys) {
    for (var i = keys.length; i--;) {
      document.cookie = keys[i] + '=0;path=/;expires=' + new Date(0).toUTCString() // 清除当前域名下的,例如：m.ratingdog.cn
      document.cookie = keys[i] + '=0;path=/;domain=' + document.domain + ';expires=' + new Date(0).toUTCString() // 清除当前域名下的，例如 .m.ratingdog.cn
      document.cookie = keys[i] + '=0;path=/;domain=ratingdog.cn;expires=' + new Date(0).toUTCString() // 清除一级域名下的或指定的，例如 .ratingdog.cn
    }
  }
}
</code></pre>
<p>参考 <a href="https://www.cnblogs.com/handsome-jm/p/11505191.html">js 清除 当前站点所有域cookie</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[加载js并判断是否加载成功]]></title><description><![CDATA[<div class="kg-card-markdown"><p>在网上收集到的一段代码，我增加了指定挂载点的参数</p>
<pre><code>function ScriptLoader() {}
ScriptLoader.prototype = {
	timer: function(
		times, // number of times to try
		delay, // delay per try
		delayMore, // extra delay per try (additional to delay)
		test, // called each try, timer stops if this returns true
		failure, // called on failure
		result // used internally, shouldn't be passed
	) {
		var me = this;
		if(</code></pre></div>]]></description><link>http://itmx.cc/jia-zai-jsbing-pan-duan-shi-fou-jia-zai-cheng-gong/</link><guid isPermaLink="false">5f8fa6559efa2300017c4890</guid><category><![CDATA[js]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Wed, 21 Oct 2020 03:30:52 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>在网上收集到的一段代码，我增加了指定挂载点的参数</p>
<pre><code>function ScriptLoader() {}
ScriptLoader.prototype = {
	timer: function(
		times, // number of times to try
		delay, // delay per try
		delayMore, // extra delay per try (additional to delay)
		test, // called each try, timer stops if this returns true
		failure, // called on failure
		result // used internally, shouldn't be passed
	) {
		var me = this;
		if(times == -1 || times &gt; 0) {
			setTimeout(function() {
				result = (test()) ? 1 : 0;
				me.timer((result) ? 0 : (times &gt; 0) ? --times : times, delay + ((delayMore) ? delayMore : 0), delayMore, test, failure, result);
			}, (result || delay &lt; 0) ? 0.1 : delay);
		} else if(typeof failure == 'function') {
			setTimeout(failure, 1);
		}
	},
	addEvent: function(el, eventName, eventFunc) {
		if(typeof el != 'object') {
			return false;
		}
		if(el.addEventListener) {
			el.addEventListener(eventName, eventFunc, false);
			return true;
		}
		if(el.attachEvent) {
			el.attachEvent(&quot;on&quot; + eventName, eventFunc);
			return true;
		}
		return false;
	},
	// add script to dom
	require: function(url, args) {
		var me = this;
		args = args || {};
		var mountNode = args.mountNode || document.head || document.body || document.firstElementChild;
		var scriptTag = document.createElement('script');
		setTimeout(function() {
			var f = (typeof args.success == 'function') ? args.success : function() {};
			args.failure = (typeof args.failure == 'function') ? args.failure : function() {};
			var fail = function() {
				if(!scriptTag.__es) {
					scriptTag.__es = true;
					scriptTag.id = 'failed';
					args.failure(scriptTag);
				}
			};
			scriptTag.onload = function() {
				scriptTag.id = 'loaded';
				f(scriptTag);
			};
			scriptTag.type = 'text/javascript';
			scriptTag.async = (typeof args.async == 'boolean') ? args.async : false;
			scriptTag.charset = 'utf-8';
			me.__es = false;
			me.addEvent(scriptTag, 'error', fail); // when supported
			// when error event is not supported fall back to timer
			me.timer(15, 1000, 0, function() {
				return(scriptTag.id == 'loaded');
			}, function() {
				if(scriptTag.id != 'loaded') {
					fail();
				}
			});
			scriptTag.src = url;
			setTimeout(function() {
				try {
					mountNode.appendChild(scriptTag);
				} catch(e) {
					fail();
				}
			}, 1);
		}, (typeof args.delay == 'number') ? args.delay : 1);
		return true;
	}
};
</code></pre>
<p>使用方式</p>
<pre><code>new ScriptLoader().require('xxx/js/main.js', {
    async: true, 
    success: function(){/*这里可以再次验证一下main.js里面定义的全局变量是否存在，双重确认加载成功*/},
    failure: function () {}
});
</code></pre>
</div>]]></content:encoded></item><item><title><![CDATA[解决Node.js依赖下载不下来及环境问题]]></title><description><![CDATA[<div class="kg-card-markdown"><p>如果<code>node</code>项目中遇到了依赖<code>python2.7</code>、<code>node v8</code>等旧版本的依赖，可以将相关版本的zip下载到当前目录解压<br>
然后执行以下命令进行安装依赖和启动项目</p>
<ul>
<li>set path=%cd%\node-v8.17.0-win-x64 (强行替换node)</li>
<li>set PYTHON=%cd%\Python27 (指定python)</li>
<li>npm config set proxy=http://127.0.0.1:8888 (梯子)</li>
<li>npm config set https-proxy <a href="http://127.0.0.1:8888">http://127.0.0.1:8888</a> (梯子)</li>
<li>npm config set registry=https://registry.</li></ul></div>]]></description><link>http://itmx.cc/jie-jue-node-jsyi-lai-xia-zai-bu-xia-lai-ji-huan-jing-wen-ti/</link><guid isPermaLink="false">5f3f7651e99f35000188cbea</guid><category><![CDATA[js]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Fri, 21 Aug 2020 07:26:53 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>如果<code>node</code>项目中遇到了依赖<code>python2.7</code>、<code>node v8</code>等旧版本的依赖，可以将相关版本的zip下载到当前目录解压<br>
然后执行以下命令进行安装依赖和启动项目</p>
<ul>
<li>set path=%cd%\node-v8.17.0-win-x64 (强行替换node)</li>
<li>set PYTHON=%cd%\Python27 (指定python)</li>
<li>npm config set proxy=http://127.0.0.1:8888 (梯子)</li>
<li>npm config set https-proxy <a href="http://127.0.0.1:8888">http://127.0.0.1:8888</a> (梯子)</li>
<li>npm config set registry=https://registry.npm.taobao.org</li>
<li>npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver</li>
<li>npm install</li>
<li>npm config delete proxy (取消梯子)</li>
<li>npm config delete https-proxy (取消梯子)</li>
<li>npm run build</li>
</ul>
</div>]]></content:encoded></item><item><title><![CDATA[安装VM后，Docker无法以Hyper-V模式启动]]></title><description><![CDATA[<div class="kg-card-markdown"><p>以管理员权限打开命令提示符<br>
输入</p>
<pre><code>bcdedit /set hypervisorlaunchtype Auto
</code></pre>
<p>重启计算机<br>
此时<code>VMware Workstation</code>将无法启动虚拟机</p>
<p>本方法用于临时需要在本地用到<code>Docker</code>而又安装了<code>VMware Workstation</code>的情况下使用，<br>
不过一般情况下用了<code>Docker for window</code>就不会再装<code>VMware Workstation</code>了，<br>
<code>Win10</code>自带的<code>Hyper-V</code>也很好用，实在不行用<code>Oracle VM VirtualBox</code>也是可以的，<br>
不会抢占虚拟化</p>
</div>]]></description><link>http://itmx.cc/an-zhuang-vmhou-dockerwu-fa-yi-hyper-vmo-shi-qi-dong/</link><guid isPermaLink="false">5f30e0b9e99f35000188cbe6</guid><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Mon, 10 Aug 2020 05:57:09 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>以管理员权限打开命令提示符<br>
输入</p>
<pre><code>bcdedit /set hypervisorlaunchtype Auto
</code></pre>
<p>重启计算机<br>
此时<code>VMware Workstation</code>将无法启动虚拟机</p>
<p>本方法用于临时需要在本地用到<code>Docker</code>而又安装了<code>VMware Workstation</code>的情况下使用，<br>
不过一般情况下用了<code>Docker for window</code>就不会再装<code>VMware Workstation</code>了，<br>
<code>Win10</code>自带的<code>Hyper-V</code>也很好用，实在不行用<code>Oracle VM VirtualBox</code>也是可以的，<br>
不会抢占虚拟化</p>
</div>]]></content:encoded></item><item><title><![CDATA[IP地址Excel排序]]></title><description><![CDATA[<div class="kg-card-markdown"><p>公式如下</p>
<pre><code>=SUMPRODUCT(MID(SUBSTITUTE(A2,&quot;.&quot;,REPT(&quot; &quot;,20)),{1,21,41,61},20)*10^{9,6,3,0})
</code></pre>
</div>]]></description><link>http://itmx.cc/ipdi-zhi-excelpai-xu/</link><guid isPermaLink="false">5ef1a3cfe99f35000188cbe0</guid><category><![CDATA[excel]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Tue, 23 Jun 2020 06:40:53 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>公式如下</p>
<pre><code>=SUMPRODUCT(MID(SUBSTITUTE(A2,&quot;.&quot;,REPT(&quot; &quot;,20)),{1,21,41,61},20)*10^{9,6,3,0})
</code></pre>
</div>]]></content:encoded></item><item><title><![CDATA[go http接口返回1x1像素图片]]></title><description><![CDATA[<div class="kg-card-markdown"><p>最近做一个统计接口，准备用图片方式发起网络请求</p>
<pre><code>new Image().src='http://xxx.xxx.com/s?_='+new Date().getTime();
</code></pre>
<p>然后接口<code>/s</code>用<code>go</code>快速写了个接口，返回<code>200</code>状态码和空响应体。<br>
统计用的好好的，但是遇上一些懒加载框架就会出现反复请求的情况，<br>
因为这张图片并不是真的图片，图片在预加载时失败，故反复加载。</p>
<p>要解决也很简单，返回一个<code>1x1</code>像素的图片数据就可以了。</p>
<pre><code>http.HandleFunc(&quot;/a.gif&quot;, func(writer http.ResponseWriter, request *http.Request) {
	writer.Header().Set(&quot;Content-Type&quot;</code></pre></div>]]></description><link>http://itmx.cc/go-httpjie-kou-fan-hui-1x1xiang-su-tu-pian/</link><guid isPermaLink="false">5edf5797e99f35000188cbda</guid><category><![CDATA[golang]]></category><category><![CDATA[js]]></category><category><![CDATA[html]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Tue, 09 Jun 2020 09:42:01 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>最近做一个统计接口，准备用图片方式发起网络请求</p>
<pre><code>new Image().src='http://xxx.xxx.com/s?_='+new Date().getTime();
</code></pre>
<p>然后接口<code>/s</code>用<code>go</code>快速写了个接口，返回<code>200</code>状态码和空响应体。<br>
统计用的好好的，但是遇上一些懒加载框架就会出现反复请求的情况，<br>
因为这张图片并不是真的图片，图片在预加载时失败，故反复加载。</p>
<p>要解决也很简单，返回一个<code>1x1</code>像素的图片数据就可以了。</p>
<pre><code>http.HandleFunc(&quot;/a.gif&quot;, func(writer http.ResponseWriter, request *http.Request) {
	writer.Header().Set(&quot;Content-Type&quot;, &quot;image/gif&quot;)
	writer.Header().Set(&quot;Cache-Control&quot;, &quot;private, no-cache, no-cache=Set-Cookie, proxy-revalidate&quot;)
	writer.Header().Set(&quot;Pragma&quot;, &quot;no-cache&quot;)
	writer.Header().Set(&quot;Expires&quot;, &quot;Wed, 17 Sep 1975 21:32:10 GMT&quot;)
	_, _ = writer.Write([]byte{
		0x47, 0x49, 0x46, 0x38, 0x39, 0x61,
		0x01, 0x00, 0x01, 0x00, 0x80, 0xff,
		0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
		0x00, 0x2c, 0x00, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x01, 0x00, 0x00, 0x02,
		0x02, 0x44, 0x01, 0x00, 0x3b,
	})
})
_ = http.ListenAndServe(&quot;:8088&quot;, nil)
</code></pre>
</div>]]></content:encoded></item><item><title><![CDATA[HTML反防盗链，Referer]]></title><description><![CDATA[<div class="kg-card-markdown"><pre><code>&lt;meta name=&quot;referrer&quot; content=&quot;never&quot;&gt;

&lt;img src=&quot;//example.com/xxx.jpg&quot; referrerPolicy=&quot;no-referrer&quot; alt=&quot;&quot;&gt;

//使用第三方代理
&lt;img src=&quot;https://images.weserv.nl/?url=example.com/xxx.jpg&quot; referrerPolicy=&quot;no-referrer&quot; alt=&quot;&quot;</code></pre></div>]]></description><link>http://itmx.cc/h/</link><guid isPermaLink="false">5e96d9f52d73b50001fb14af</guid><category><![CDATA[html]]></category><category><![CDATA[js]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Wed, 15 Apr 2020 10:00:54 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><pre><code>&lt;meta name=&quot;referrer&quot; content=&quot;never&quot;&gt;

&lt;img src=&quot;//example.com/xxx.jpg&quot; referrerPolicy=&quot;no-referrer&quot; alt=&quot;&quot;&gt;

//使用第三方代理
&lt;img src=&quot;https://images.weserv.nl/?url=example.com/xxx.jpg&quot; referrerPolicy=&quot;no-referrer&quot; alt=&quot;&quot;&gt;

//使用js全局设置，针对new Image()
&lt;script type=&quot;text/javascript&quot;&gt;
	! function() {
		var p_src = Object.getOwnPropertyDescriptor(Image.prototype, 'src') || { 
			set: Image.prototype.__lookupSetter__('src'), 
			get: Image.prototype.__lookupGetter__('src')
		};
		Object.defineProperty(Image.prototype, 'src', {
			set: function(url) {
				this.referrerPolicy = 'no-referrer';
				p_src.set.call(this, url);
			},
			get: function() {
				return p_src.get.call(this);
			},
			configurable: true
		});
	}();
&lt;/script&gt;
</code></pre>
<p>参考资料<br>
<a href="https://www.cnblogs.com/xiaxuening/p/9714492.html">主流浏览器图片反防盗链方法总结</a><br>
<a href="https://www.freebuf.com/news/57497.html">使用Referer Meta标签控制referer</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[docker搭建samba供小米电视访问]]></title><description><![CDATA[<div class="kg-card-markdown"><p>最近在小米电视上看电影，绝大部分电影需要会员，因为我长期是京东PLUS+爱奇艺联名会员，所以一般会用爱奇艺投屏，但是有些电影在爱奇艺上也找不到，甚至有些不支持投屏，那没办法，我只能通过电脑下载下来看了，毕竟电脑投屏的效果太差，画质、声音都是对我这65英寸4k超清屏幕的不尊重。</p>
<p>一开始按照常我以往的方式，使用<code>dperson/samba</code>镜像启动了docker，但是电视上始终显示连接失败，华为手机文件管理上也是，于是想起之前配置摄像头远程存储事遇到过的镜像<code>servercontainers/samba</code>，终于配置成功了，华为手机上也能正常连接。</p>
<p>编排文件<code>docker-compose.yml</code></p>
<pre><code>version: '2'

services:
  main:
    hostname: samba-tv
    container_name: samba-tv
    image: servercontainers/samba
    restart: always
    environment:
      ACCOUNT_tv: ********
      SAMBA_VOLUME_CONFIG_tv: &quot;[TV</code></pre></div>]]></description><link>http://itmx.cc/dockerda-jian-sambagong-xiao-mi-dian-shi-fang-wen/</link><guid isPermaLink="false">5e8b32147376f400012eeafd</guid><category><![CDATA[linux(centos)]]></category><category><![CDATA[docker]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Mon, 06 Apr 2020 14:30:15 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>最近在小米电视上看电影，绝大部分电影需要会员，因为我长期是京东PLUS+爱奇艺联名会员，所以一般会用爱奇艺投屏，但是有些电影在爱奇艺上也找不到，甚至有些不支持投屏，那没办法，我只能通过电脑下载下来看了，毕竟电脑投屏的效果太差，画质、声音都是对我这65英寸4k超清屏幕的不尊重。</p>
<p>一开始按照常我以往的方式，使用<code>dperson/samba</code>镜像启动了docker，但是电视上始终显示连接失败，华为手机文件管理上也是，于是想起之前配置摄像头远程存储事遇到过的镜像<code>servercontainers/samba</code>，终于配置成功了，华为手机上也能正常连接。</p>
<p>编排文件<code>docker-compose.yml</code></p>
<pre><code>version: '2'

services:
  main:
    hostname: samba-tv
    container_name: samba-tv
    image: servercontainers/samba
    restart: always
    environment:
      ACCOUNT_tv: ********
      SAMBA_VOLUME_CONFIG_tv: &quot;[TV Share]; path=/shares/tv; valid users = tv; guest ok = no; read only = no; browseable = yes; veto files = /._*/.apdisk/.AppleDouble/.DS_Store/.TemporaryItems/.Trashes/desktop.ini/ehthumbs.db/Network Trash Folder/Temporary Items/Thumbs.db/; delete veto files = yes&quot;
    volumes:
      - ./shares:/shares
    ports:
      - &quot;137:137/udp&quot;
      - &quot;138:138/udp&quot;
      - &quot;139:139/udp&quot;
      - &quot;139:139/tcp&quot;
      - &quot;445:445/tcp&quot;
    networks:
      tv_net:
        ipv4_address: 192.168.1.88

networks:
  tv_net:
    driver: macvlan
    driver_opts:
      parent: enp4s0
    ipam:
      config:
        - subnet: 192.168.1.0/24
          gateway: 192.168.1.1
</code></pre>
<p>要注意的是，最好手动创建好<code>./shares/tv</code>目录然后修改权限，<br>
<code>chown -R 1000:1001 ./shares/tv</code></p>
<p>这个镜像默认是不启动<code>nmbd</code>服务的，nmbd可以让当前samba服务被发现，<br>
我是为了启用<code>nmbd</code>服务才创建vlan让这个容器独自占用一个IP<br>
有了独立IP后，找到作者的Github项目，将代码克隆下来，<br>
修改<code>scripts/entrypoint.sh</code>文件在末尾处加了一行代码，</p>
<pre><code>echo &quot;&gt;&gt; Start nmbd service...&quot;
nmbd -D
</code></pre>
<p>然后重新构建镜像。</p>
<p>修改后的<code>scripts/entrypoint.sh</code>文件末尾：</p>
<pre><code>...
##
# CMD
##
echo &quot;&gt;&gt; Start nmbd service...&quot;
nmbd -D
echo &quot;&gt;&gt; CMD: exec docker CMD&quot;
echo &quot;$@&quot;
exec &quot;$@&quot;
</code></pre>
<p>打开小米电视-&gt;应用中心-&gt;高清播放器，切换到设备标签，大功告成<br>
<img src="http://itmx.cc/content/images/2020/04/WechatIMG1.jpeg" alt="WechatIMG1"></p>
<p>参考链接：<br>
<a href="https://github.com/ServerContainers/samba">Github仓库</a><br>
<a href="https://www.cnblogs.com/fanweisheng/p/11089671.html">nmbd使用</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[使用ESP8266显示实时公交]]></title><description><![CDATA[<div class="kg-card-markdown"><h3 id>引言</h3>
<p>最近在学习物联网方面的知识，由于正好最近天天要坐公交，老是打开微信再启动一个小程序来查看，这可不是我的风格。<br>
于是从零开始学习ESP8622 WIFI模块，再配上一块OLED显示屏，因为USB供电一般是5.1v，再买了一个3.3v降压稳压模块。</p>
<h3 id>亮相</h3>
<p><img src="http://itmx.cc/content/images/2020/04/esp8622.jpg" alt="esp8622"><br>
<img src="http://itmx.cc/content/images/2020/04/oled.jpg" alt="oled"><br>
<img src="http://itmx.cc/content/images/2020/04/3.3v.jpg" alt="3.3v"><br>
<img src="http://itmx.cc/content/images/2020/04/usb.jpg" alt="usb"></p>
<h3 id>简单说一下接线</h3>
<p>使用<code>USB TO TTL</code>上传代码时，IO0需要接GND才能进入刷机模式<br>
<img src="http://itmx.cc/content/images/2020/04/line.jpg" alt="line"></p>
<h3 id>上代码</h3>
<pre><code>/*
       Next Bus
      86: -1;-1
      23: -1;-1
   Update 16:26:07
*/

#include &lt;Arduino.h&gt;
#include &lt;ESP8266WiFi.h&gt;
#include &lt;ESP8266WiFiMulti.h&gt;
#include &lt;</code></pre></div>]]></description><link>http://itmx.cc/shi-yong-esp8266xian-shi-shi-shi-gong-jiao/</link><guid isPermaLink="false">5e8b29d37376f400012eeaf8</guid><category><![CDATA[iot]]></category><category><![CDATA[arduino]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Mon, 06 Apr 2020 13:43:37 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><h3 id>引言</h3>
<p>最近在学习物联网方面的知识，由于正好最近天天要坐公交，老是打开微信再启动一个小程序来查看，这可不是我的风格。<br>
于是从零开始学习ESP8622 WIFI模块，再配上一块OLED显示屏，因为USB供电一般是5.1v，再买了一个3.3v降压稳压模块。</p>
<h3 id>亮相</h3>
<p><img src="http://itmx.cc/content/images/2020/04/esp8622.jpg" alt="esp8622"><br>
<img src="http://itmx.cc/content/images/2020/04/oled.jpg" alt="oled"><br>
<img src="http://itmx.cc/content/images/2020/04/3.3v.jpg" alt="3.3v"><br>
<img src="http://itmx.cc/content/images/2020/04/usb.jpg" alt="usb"></p>
<h3 id>简单说一下接线</h3>
<p>使用<code>USB TO TTL</code>上传代码时，IO0需要接GND才能进入刷机模式<br>
<img src="http://itmx.cc/content/images/2020/04/line.jpg" alt="line"></p>
<h3 id>上代码</h3>
<pre><code>/*
       Next Bus
      86: -1;-1
      23: -1;-1
   Update 16:26:07
*/

#include &lt;Arduino.h&gt;
#include &lt;ESP8266WiFi.h&gt;
#include &lt;ESP8266WiFiMulti.h&gt;
#include &lt;ESP8266HTTPClient.h&gt;
#include &lt;WiFiClientSecureBearSSL.h&gt;
#include &lt;ArduinoJson.h&gt;

#include &lt;Wire.h&gt;
#include &lt;Adafruit_GFX.h&gt;
#include &lt;Adafruit_SSD1306.h&gt;

ESP8266WiFiMulti WiFiMulti;

// https 证书指纹 aecd3b*********************************feab
const uint8_t fingerprint[20] = {0xae, 0xcd, 0x3b, ..., 0xfe, 0xab};
std::unique_ptr&lt;BearSSL::WiFiClientSecure&gt;client(new BearSSL::WiFiClientSecure);

Adafruit_SSD1306 display(4);

const String zero(&quot;0&quot;);
// current timestamp
int timestamp = 0;
String crtShow = &quot;&quot;;


void setup() {
  Wire.begin(0, 2);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.setTextSize(2);

  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(&quot;WIFI_SSID&quot;, &quot;WIFI_PASS&quot;);

  client-&gt;setFingerprint(fingerprint);

  println(&quot;Connecting wifi.&quot;);
  delay(1000);
  while (WiFiMulti.run() != WL_CONNECTED) {
    println(&quot;Connecting wifi..&quot;);
    delay(500);
  }
}

void loop() {

  // wait for WiFi connection
  while (WiFiMulti.run() != WL_CONNECTED) {
    println(&quot;Connecting wifi...&quot;);
  }

  if (timestamp % 10 == 0) {
    String bus86 = httpGet(&quot;https://busapi.proxy.itmx.xyz/*********&quot;);
    String bus23 = httpGet(&quot;https://busapi.proxy.itmx.xyz/*********&quot;);
    crtShow = &quot; Next Bus\n86:&quot; + bus86 + &quot;23:&quot; + bus23 + &quot; &quot;;
  } else {
    timestamp++;
  }
  println(crtShow + getCrtTime());

  delay(1000);
}

void println(String line) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println(line);
  display.display();
  Serial.println(line);
}

void setCrtTime(String date) {
  int pos = date.indexOf(':');
  if (pos == -1) {
    return;
  }
  timestamp = atoi(date.substring(pos - 2, pos).c_str()) * 3600 +
              atoi(date.substring(pos + 1, pos + 3).c_str()) * 60   +
              atoi(date.substring(pos + 4, pos + 6).c_str());
}

String getCrtTime() {
  int h = (timestamp / 3600 + 8) % 24, m = timestamp % 3600 / 60, s = timestamp % 60;
  return String(h &lt; 10 ? zero + h : h) + &quot;:&quot; + (m &lt; 10 ? zero + m : m) + &quot;:&quot; + (s &lt; 10 ? zero + s : s);
}

String httpGet(String url) {
  HTTPClient https;
  String result;

  // 请求接口
  if (https.begin(*client, url)) {
    https.addHeader(&quot;content-type&quot;, &quot;application/json&quot;);
    https.addHeader(&quot;user-agent&quot;, &quot;&quot;);
    https.addHeader(&quot;connection&quot;, &quot;close&quot;);
    const char *keys[] = {&quot;Date&quot;};
    https.collectHeaders(keys, 1);

    if (https.GET() == HTTP_CODE_OK) {
      setCrtTime(https.header(&quot;Date&quot;));

      String payload = https.getString();
      int posS = payload.indexOf('[');
      int posE = payload.indexOf('}', posS);
      if (posS != -1 &amp;&amp; posE != -1) {
        DynamicJsonDocument doc(JSON_OBJECT_SIZE(6) + 60);
        payload = payload.substring(posS + 1, posE + 1);
        if (!deserializeJson(doc, payload)) {
          int c = doc[&quot;count&quot;].as&lt;int&gt;(); // 获取距离当前站还有几个站
          int t = doc[&quot;time&quot;].as&lt;int&gt;();  // 大约还有多少分钟到达本站（家门口的公交站）
          result = (c &lt; 10 &amp;&amp; c &gt;= 0 ? zero + c : c) + &quot;s &quot; + (t &lt; 10 &amp;&amp; t &gt;= 0 ? zero + t : t) + &quot;m&quot;;
        } else {
          result = &quot;-2;-2&quot;;
        }
      } else {
        result = &quot;-3;-3&quot;;
      }
    } else {
      result = &quot;-4;-4&quot;;
    }
  } else {
    result = &quot;-5;-5&quot;;
  }
  https.end();
  return result;
}
</code></pre>
<h3 id>参考资料</h3>
<p><a href="http://www.log4cpp.com/smarthome/10.html">WIFI模块ESP8266使用方法</a><br>
<a href="http://www.log4cpp.com/Tutorials/Arduino/2018-02-26/57.html">【Arduino教程】第十三课：Arduino通过ESP8266接入互联网</a><br>
<a href="http://www.elecfans.com/d/1076324.html">怎样使用ESP8266-01引脚和指示灯</a><br>
<a href="https://github.com/esp8266/Arduino">Github仓库，大量示例</a></p>
<h3 id>成品</h3>
<p><img src="http://itmx.cc/content/images/2020/04/result0.jpg" alt="result0"><br>
<img src="http://itmx.cc/content/images/2020/04/result2.jpg" alt="result2"><br>
<img src="http://itmx.cc/content/images/2020/04/result1.jpg" alt="result1"></p>
<p>害，但凡有个3D打印机，也不至于丑成这样啊。<br>
<em>之前在学习的时候跟朋友一起买了个3D打印机，没用几次就成装饰品在角落落灰了。。。</em></p>
</div>]]></content:encoded></item><item><title><![CDATA[Arduino初体验-自动加水烧水壶]]></title><description><![CDATA[<div class="kg-card-markdown"><h3 id>前言</h3>
<p>春节疫情期间有些闲，<br>
在某宝上看到物联网开发套件，<br>
于是分6期花呗(穷)买下来玩一下。</p>
<p>货到了之后，没啥想法，简单体验了一下蜂鸣器模块，做了重复播放摩斯电码的demo之后，突然想到以前夸下海口说：这自动电热水壶我自己都能做得出来。好吧，装逼重要能装得下去，对吧？</p>
<h3 id>思路</h3>
<p>这个热水壶只有一个按钮，<br>
插上电后，电源指示灯亮起来，状态指示灯是灭的，<br>
按下按钮（水壶已就位，否则按钮无响应），壶内如果没八成水就加水，有八成就直接开始加热，<br>
加水时，状态指示灯为蓝色，先旋转加水臂杆至壶口，然后水泵开始工作，<br>
直到壶内足够八成水便收起臂杆并开始加热，<br>
加热时，状态指示灯为红色，壶内水温加热至100℃，停止加热，<br>
加热完成后，状态指示灯为绿色，<br>
当水温下降或者再次点击工作按钮后，状态指示灯灭掉。</p>
<h3 id="c">代码（C语言）</h3>
<p>嗯，直接贴代码吧：</p>
<pre><code>#include &lt;Servo.h&gt;

const int tempDigitalPin</code></pre></div>]]></description><link>http://itmx.cc/arduinochu-ti-yan-zi-dong-shao-shui-hu/</link><guid isPermaLink="false">5e60a6181e4d910001540d77</guid><category><![CDATA[arduino]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Thu, 05 Mar 2020 07:12:36 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><h3 id>前言</h3>
<p>春节疫情期间有些闲，<br>
在某宝上看到物联网开发套件，<br>
于是分6期花呗(穷)买下来玩一下。</p>
<p>货到了之后，没啥想法，简单体验了一下蜂鸣器模块，做了重复播放摩斯电码的demo之后，突然想到以前夸下海口说：这自动电热水壶我自己都能做得出来。好吧，装逼重要能装得下去，对吧？</p>
<h3 id>思路</h3>
<p>这个热水壶只有一个按钮，<br>
插上电后，电源指示灯亮起来，状态指示灯是灭的，<br>
按下按钮（水壶已就位，否则按钮无响应），壶内如果没八成水就加水，有八成就直接开始加热，<br>
加水时，状态指示灯为蓝色，先旋转加水臂杆至壶口，然后水泵开始工作，<br>
直到壶内足够八成水便收起臂杆并开始加热，<br>
加热时，状态指示灯为红色，壶内水温加热至100℃，停止加热，<br>
加热完成后，状态指示灯为绿色，<br>
当水温下降或者再次点击工作按钮后，状态指示灯灭掉。</p>
<h3 id="c">代码（C语言）</h3>
<p>嗯，直接贴代码吧：</p>
<pre><code>#include &lt;Servo.h&gt;

const int tempDigitalPin = 4; // 温度传感器

// 三色LED状态指示灯
const int stateLedRPin = 9;
const int stateLedGPin = 10;
const int stateLedBPin = 11;

const int startBtnPin = 8; // 工作按钮
const int poolBtnPin = 12; // 水位检测按钮
const int baseBtnPin = 6;  // 水壶基座按钮

const int pumpRelayPin = 5; // 抽水泵
const int heatingCoilRelayPin = 2; // 加热线圈继电器
const int buzzerPin = 7; // 蜂鸣器
const int readyLedPin = 13; // 电源指示灯

const int servoPin = 3; // 舵机

// 0：初始状态
// 1：加水状态
// 2：烧水状态
// 3：开水状态
int GState = 0;
// 上一次状态记录
int GStateLast = -1;

Servo myservo;

void setup() {
  pinMode(tempDigitalPin, INPUT);

  pinMode(stateLedRPin, OUTPUT);
  pinMode(stateLedGPin, OUTPUT);
  pinMode(stateLedBPin, OUTPUT);

  pinMode(startBtnPin, INPUT);
  pinMode(poolBtnPin, INPUT);
  pinMode(baseBtnPin, INPUT);

  pinMode(pumpRelayPin, OUTPUT);
  pinMode(heatingCoilRelayPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(readyLedPin, OUTPUT);

  myservo.attach(servoPin);

  tone(buzzerPin, 4000, 500);

  digitalWrite(readyLedPin, LOW);
}

void loop() {
  boolean startBtnVal = digitalRead(startBtnPin);
  boolean poolBtnPinVal = digitalRead(poolBtnPin);
  boolean baseBtnPin = digitalRead(baseBtnPin);
  baseBtnPin = LOW;//模块足够时删去

  // 如果水壶不在基座上，恢复初始状态
  if (baseBtnPin == HIGH) {
    GState = 0;
    startBtnVal = HIGH; // 使工作按钮无效
  }

  // 初始状态，按钮被按下
  if (GState == 0 &amp;&amp; startBtnVal == LOW) {
    //水壶有水，那就烧水，水壶没水，那就加水
    if (poolBtnPinVal == HIGH) {
      GState = 2;
    } else {
      GState = 1;
    }
  }

  // 加水状态，水壶满了，那就烧水
  if (GState == 1 &amp;&amp; poolBtnPinVal == HIGH) {
    GState = 2;
  }

  // 烧水状态，水温达到目标值，变成完成状态
  if (GState == 2 &amp;&amp; digitalRead(tempDigitalPin) == LOW) {
    GState = 3;
  }

  // 完成状态，水温下降则恢复为初始状态，点击按钮恢复初始状态
  //if (GState == 3 &amp;&amp; (digitalRead(tempDigitalPin) == LOW || startBtnVal == LOW)){
  if (GState == 3 &amp;&amp; startBtnVal == LOW) {
    GState = 0;
    delay(1500);
  }

  //检查状态是否发生改变
  if (GState == GStateLast) {
    return;
  } else {
    GStateLast = GState;
  }

  switch (GState) {
    case 0:
      defaultState();
      break;
    case 1:
      addWaterState();
      break;
    case 2:
      heatingState();
      break;
    case 3:
      finishState();
      break;
  }
}

void stateLedColor(unsigned char red, unsigned char green, unsigned char blue) {
  analogWrite(stateLedRPin, red);
  analogWrite(stateLedBPin, blue);
  analogWrite(stateLedGPin, green);
}

void defaultState() {
  stateLedColor(0, 0, 0); //关闭指示灯
  digitalWrite(heatingCoilRelayPin, HIGH);// 关闭加热线圈
  //digitalWrite(pumpRelayPin, HIGH);// 关闭加水马达
  analogWrite(pumpRelayPin, 0);
  myservo.write(0);// 归位加水导杆
}

void addWaterState() {
  stateLedColor(0, 0, 255); //指示灯纯蓝色
  myservo.write(45);// 启动加水导杆
  delay(1000);
  //digitalWrite(pumpRelayPin, LOW);// 启动加水马达
  analogWrite(pumpRelayPin, 200);
}

void heatingState() {
  stateLedColor(255, 0, 0); //指示灯纯红色
  digitalWrite(heatingCoilRelayPin, LOW);// 启动加热线圈
  //digitalWrite(pumpRelayPin, HIGH);// 关闭加水马达
  analogWrite(pumpRelayPin, 0);
  delay(1000);
  myservo.write(0);// 归位加水导杆
}

void finishState() {
  stateLedColor(0, 255, 0); //指示灯纯绿色
  digitalWrite(heatingCoilRelayPin, HIGH);// 关闭加热线圈
  //digitalWrite(pumpRelayPin, HIGH);// 关闭加水马达
  analogWrite(pumpRelayPin, 0);
  myservo.write(0);// 归位加水导杆

  // 蜂鸣器响三声
  tone(buzzerPin, 4000, 500);
  delay(600);
  tone(buzzerPin, 4000, 500);
  delay(600);
  tone(buzzerPin, 4000, 500);
}
</code></pre>
<h3 id>各模块实拍</h3>
<p>就随手拍几张图片吧：<br>
首先上场的是来自某宝的Arduino UNO主板，主控程序运行的所在地<br>
<img src="http://itmx.cc/content/images/2020/03/UNO--.jpg" alt="Arduino UNO主板"></p>
<p>下面是轻触开关，在本实验中作为工作按钮<br>
<img src="http://itmx.cc/content/images/2020/03/-----2.jpg" alt="轻触开关"></p>
<p>接下来是触摸开关，在本实验中充当壶内水位监测按钮<br>
<img src="http://itmx.cc/content/images/2020/03/-----3.jpg" alt="触摸开关"></p>
<p>下面是直流电机和达林顿阵列，在本实验中充当抽水泵<br>
<img src="http://itmx.cc/content/images/2020/03/----------.jpg" alt="直流电机和达林顿阵列"></p>
<p>还有三色LED灯，在本实验中作为状态指示灯<br>
<img src="http://itmx.cc/content/images/2020/03/--LED.jpg" alt="三色LED灯"></p>
<p>下面是热敏温度传感器，在本实验中作为水温检测模块<br>
<img src="http://itmx.cc/content/images/2020/03/-------.jpg" alt="热敏温度传感器"></p>
<p>蜂鸣器，当水烧好了之后，嘀嘀嘀叫三声<br>
<img src="http://itmx.cc/content/images/2020/03/---.jpg" alt="蜂鸣器"></p>
<p>舵机，在本实验中充当加水杆的旋转电机<br>
<img src="http://itmx.cc/content/images/2020/03/--.jpg" alt="舵机"></p>
<p>继电器，在本实验中充当加热器模块<br>
<img src="http://itmx.cc/content/images/2020/03/----1.jpg" alt="继电器"></p>
<p><em>未完待续</em></p>
</div>]]></content:encoded></item><item><title><![CDATA[Service Worker了解一下？]]></title><description><![CDATA[<div class="kg-card-markdown"><p>我怎么会遇到这玩意？<br>
其实一开始我并不是想了解<code>Service Worker</code>，而是我最近有个业务用到了<a href="https://su.baidu.com">百度云加速</a>的边缘计算能力。<br>
<img src="http://itmx.cc/content/images/2020/02/---------.png" alt="---------"><br>
其实主要是用来实现智能缓存，在写函数时对这种代码的运行方式很好奇，想知道怎样搭建一个类似的环境在本地调试代码。</p>
<pre><code>addEventListener('fetch', event =&gt; {
  event.respondWith(handleRequest(event.request))
})

/**
 * Fetch and log a request
 * @param {Request} request
 */
async function handleRequest(request) {
  console.log('Got request', request)
  const response = await fetch(request)
  console.log('Got response', response)
  return response
}
</code></pre>
<p><img src="http://itmx.cc/content/images/2020/02/----.png" alt="----"></p>
<p>于是我就找啊找，找到了<code></code></p></div>]]></description><link>http://itmx.cc/service-workerliao-jie-yi-xia/</link><guid isPermaLink="false">5e4f6e611e4d910001540d71</guid><category><![CDATA[web]]></category><category><![CDATA[js]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Fri, 21 Feb 2020 07:12:09 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>我怎么会遇到这玩意？<br>
其实一开始我并不是想了解<code>Service Worker</code>，而是我最近有个业务用到了<a href="https://su.baidu.com">百度云加速</a>的边缘计算能力。<br>
<img src="http://itmx.cc/content/images/2020/02/---------.png" alt="---------"><br>
其实主要是用来实现智能缓存，在写函数时对这种代码的运行方式很好奇，想知道怎样搭建一个类似的环境在本地调试代码。</p>
<pre><code>addEventListener('fetch', event =&gt; {
  event.respondWith(handleRequest(event.request))
})

/**
 * Fetch and log a request
 * @param {Request} request
 */
async function handleRequest(request) {
  console.log('Got request', request)
  const response = await fetch(request)
  console.log('Got response', response)
  return response
}
</code></pre>
<p><img src="http://itmx.cc/content/images/2020/02/----.png" alt="----"></p>
<p>于是我就找啊找，找到了<code>Service Worker</code>这个关键词，还有一些相关资料：</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent">FetchEvent</a></li>
<li><a href="https://github.com/mdn/sw-test">demo</a></li>
<li><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers">Using Service Workers</a></li>
<li><a href="https://www.cnblogs.com/worktile/p/10418283.html">Service Worker</a></li>
<li><a href="https://blog.csdn.net/i10630226/article/details/78885664?utm_source=distribute.pc_relevant.none-task">【PWA】Service Worker 全面进阶</a></li>
</ul>
<p><em>不过这些都是描述运行在浏览器的文章，还不是我想找的服务端运行环境，继续探索吧~</em></p>
</div>]]></content:encoded></item><item><title><![CDATA[解密微信图片]]></title><description><![CDATA[<div class="kg-card-markdown"><p>寻找最新的图片文件，30分钟内修改过的文件</p>
<pre><code>find ./ -mmin -30
</code></pre>
<p>找到后进入相应的文件夹，保存以下代码为<code>WechatImageDecoder.py</code>文件</p>
<pre><code>#!/usr/bin/env python
# zhangxiaoyang.hit[at]gmail.com

import re

class WechatImageDecoder:
    def __init__(self, dat_file):
        dat_file = dat_file.lower()

        decoder = self._match_decoder(dat_file)
        decoder(dat_file)

    def _match_decoder(self, dat_file):
        decoders = {
            r'.</code></pre></div>]]></description><link>http://itmx.cc/jie-mi-wei-xin-tu-pian/</link><guid isPermaLink="false">5e2554ab1e4d910001540d68</guid><category><![CDATA[python]]></category><dc:creator><![CDATA[ITMX]]></dc:creator><pubDate>Mon, 20 Jan 2020 07:37:22 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>寻找最新的图片文件，30分钟内修改过的文件</p>
<pre><code>find ./ -mmin -30
</code></pre>
<p>找到后进入相应的文件夹，保存以下代码为<code>WechatImageDecoder.py</code>文件</p>
<pre><code>#!/usr/bin/env python
# zhangxiaoyang.hit[at]gmail.com

import re

class WechatImageDecoder:
    def __init__(self, dat_file):
        dat_file = dat_file.lower()

        decoder = self._match_decoder(dat_file)
        decoder(dat_file)

    def _match_decoder(self, dat_file):
        decoders = {
            r'.+\.dat$': self._decode_pc_dat,
            r'cache\.data\.\d+$': self._decode_android_dat,
            None: self._decode_unknown_dat,
        }

        for k, v in decoders.items():
            if k is not None and re.match(k, dat_file):
                return v
        return decoders[None]

    def _decode_pc_dat(self, dat_file):
        
        def do_magic(header_code, buf):
            return header_code ^ list(buf)[0] if buf else 0x00
        
        def decode(magic, buf):
            return bytearray([b ^ magic for b in list(buf)])
            
        def guess_encoding(buf):
            headers = {
                'jpg': (0xff, 0xd8),
                'png': (0x89, 0x50),
                'gif': (0x47, 0x49),
            }
            for encoding in headers:
                header_code, check_code = headers[encoding] 
                magic = do_magic(header_code, buf)
                _, code = decode(magic, buf[:2])
                if check_code == code:
                    return (encoding, magic)
            print('Decode failed')
            sys.exit(1) 

        with open(dat_file, 'rb') as f:
            buf = bytearray(f.read())
        file_type, magic = guess_encoding(buf)

        img_file = re.sub(r'.dat$', '.' + file_type, dat_file)
        with open(img_file, 'wb') as f:
            new_buf = decode(magic, buf)
            f.write(new_buf)

    def _decode_android_dat(self, dat_file):
        with open(dat_file, 'rb') as f:
            buf = f.read()

        last_index = 0
        for i, m in enumerate(re.finditer(b'\xff\xd8\xff\xe0\x00\x10\x4a\x46', buf)):
            if m.start() == 0:
                continue

            imgfile = '%s_%d.jpg' % (dat_file, i)
            with open(imgfile, 'wb') as f:
                f.write(buf[last_index: m.start()])
            last_index = m.start()

    def _decode_unknown_dat(self, dat_file):
        raise Exception('Unknown file type')


if __name__ == '__main__':
    import sys
    if len(sys.argv) != 2:
        print('\n'.join([
            'Usage:',
            '  python WechatImageDecoder.py [dat_file]',
            '',
            'Example:',
            '  # PC:',
            '  python WechatImageDecoder.py 1234567890.dat',
            '',
            '  # Android:',
            '  python WechatImageDecoder.py cache.data.10'
        ]))
        sys.exit(1)

    _,  dat_file = sys.argv[:2]
    try:
        WechatImageDecoder(dat_file)
    except Exception as e:
        print(e)
        sys.exit(1)
    sys.exit(0)
</code></pre>
<p>保存后执行命令</p>
<pre><code>python WechatImageDecoder.py 某图文件名一般32个字符.dat
</code></pre>
<p>如需解密整个目录的图片文件</p>
<pre><code>for i in `ls | grep .dat`; do python WechatImageDecoder.py $i; done;
</code></pre>
<p><a href="https://github.com/zhangxiaoyang/WechatImageDecoder">参考链接 Github</a></p>
</div>]]></content:encoded></item></channel></rss>