unofficial

unofficial 查看完整档案

成都编辑  |  填写毕业院校××科技  |  前后端工程师 编辑 www.unofficial.cn 编辑
编辑

姓名:吴非
网名:unofficial
博客://www.unofficial.cn

只想做一个自由工作者

个人动态

unofficial 发布了文章 · 2020-06-15

Warning: Accessing non-existent property "?" of module export...

编译项目的时候提示如下警告,如何才能定位到警告的具体位置呢

(node:48258) Warning: Accessing non-existent property 'lineno' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:48258) Warning: Accessing non-existent property 'column' of module exports inside circular dependency
(node:48258) Warning: Accessing non-existent property 'filename' of module exports inside circular dependency
(node:48258) Warning: Accessing non-existent property 'lineno' of module exports inside circular dependency
(node:48258) Warning: Accessing non-existent property 'column' of module exports inside circular dependency
(node:48258) Warning: Accessing non-existent property 'filename' of module exports inside circular dependency

按照警告提示,使用如下命令:

node --trace-warnings ...

得到如下的结果也不能很好的定位具体问题是什么引起的:

internal/modules/cjs/loader.js:1017
  throw err;
  ^

Error: Cannot find module '/Users/unofficial/www/work'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1014:15)
    at Function.Module._load (internal/modules/cjs/loader.js:884:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

为了看到详细的信息,我们可以使用下面的命令:

# yarn dev 是我项目本身需要执行的开发命令
npx cross-env NODE_OPTIONS="--trace-warnings" yarn dev

得到如下警告提示,可以分析出是和 stylus 相关,但是这个具体的问题也和 NodeJs 版本有关系,具体如何解决问题呢

(node:49923) Warning: Accessing non-existent property 'lineno' of module exports inside circular dependency
    at emitCircularRequireWarning (internal/modules/cjs/loader.js:814:11)
    at Object.get (internal/modules/cjs/loader.js:825:5)
    at Boolean.Node [as constructor] (/Users/unofficial/www/work/dw-weapp-base/miniprogram/node_modules/stylus/lib/nodes/node.js:44:23)
查看原文

赞 0 收藏 0 评论 2

unofficial 发布了文章 · 2020-01-12

我的大脑被挖矿代码搞的不能好好思考了

我被攻击了

个人服务器去年底最后两天被攻击了,因为一些事情拖着没来得及处理,今天实在忍不住了,记录一下被攻击后发现以及修复的过程。

2019-12-30 23:39:44 云盾预警访问恶意IP 178.170.189.5
这一次预警中有一个关键字“kdevtmpfsi”

2019-12-31 04:19:19 云盾预警矿池通信行为 178.170.189.5
kdevtmpfsi

如何找到根源

kdevtmpfsi 伪装的挺好,因为它和一个系统进程的名字非常相似 kdevtmpfs ,一不小心研究的重心就偏移了。我现在的程序是以 docker 运行的,宿主机如果被攻击了问题就严重了。

因为本身不是专业运维,排雷全靠猜测。云盾感知的 cms 可能存在安全漏洞,代码扫描后没有发现异常,到这里我感觉问题可能就更严重了。

容器存在漏洞?容器也就运行了 nmp,会是哪一个容器出现问题了呢?有些手足无措。cpu 占用高,docker 查看一下容器的 cpu 占用呢?

top

使用 top 命名直接可以查看到下图,kdevtmpfsi 差不多100%的CPU占用,导致服务器完全被恶意程序占用,我本身的服务难以正常运行。

container

cpu 被 kdevtmpfsi 挖矿程序占用 100%。按照上面的定位到容器的问题,使用命令查看容器状态 docker stats 获得下图。

看到是 redis 容器被利用了,使用命令 docker exec -it 容器ID /bin/bash 进入内部看看具体问题呢?CTRL+P+Q

使用命令 ls -lrt 可以看到最早下载的 kinsing 文件是去年30日,与最早告警时间也基本在同一天。通过搜索学习到这个文件是挖矿程序的手续进程,后续需要清理掉。

按照云盾报警的情况我们看下文件是否存在 /tmp/kdevtmpfsi ,如果存在也需要清理掉才行。文件肯定是存在的,我还干了一件事情就是 kill -9 ID,CPU 占用明显就降下来了 ,然后手动运行了一下这个程序,发现 CPU 直接就飙升了

它是如何做到的

问题找到了,只要杀掉当前进程以及守护进程,问题也就暂时解决了。没有找到根源,问题还是可能被利用,继续写入挖矿程序,我们先思考一下漏洞在哪里呢?

上面分析出来是因为 redis 的漏洞导致的?想一下我们的 redis 是如何安装的,我当初测试一个需要登录才能使用的应用程序,登录的方式是关注公众号,然后获取授权码去解锁使用。就使用 redis 存放了临时 token ,安装 redis 的时候直接就是裸奔在空气中,没有密码。

可以使用命令检测一下,例如我的公网 IP 是 110.110.110.110。 只需要使用命令 redis-cli -h 110.110.110.110 -p 6379 就直接可以连上我的 redis 服务了。

通过云盾安全预警查看到《【漏洞预警】Redis 4.x/5.x 远程命令执行高危漏洞》,解决这个问题的关键可以设置仅内网访问 redis,特殊对外的 IP 使用密码策略。

version: '3'
services:

  # 使用 command 命令设置一下密码
  redis:
    image: redis:5.0.7
    command: ["redis-server", "--requirepass", "yourpassword"]
    hostname: redis
    networks:
      - redis-net
    volumes:
      - redis-data:/data

networks:
  redis-net:

volumes:
  redis-data:

安全放心上

长呼一口气之后,想起了《亡羊补牢》的故事。

查看原文

赞 0 收藏 0 评论 0

unofficial 发布了文章 · 2019-12-09

分享给微信好友的淘宝乱码中隐藏了什么秘密

马上要过生日了,我尝试在淘宝找到了自己喜欢的同款礼物,点击右上角分享到她的微信,看她能不能读懂我的小心思。这个分享的过程涉及到一段“乱码”(淘口令,后续均以淘口令来称呼),可别小看这段淘口令,它包含了很多信息。今天主要就是分享一下为什么淘宝分享出来的内容是淘口令?淘口令包含了什么信息?以及解析这段工具是怎么制作的。

这是一个系列文章,涉及淘客工具的使用与制作,后续陆续会完成一个整套系列工具的开发,欢迎收藏关注看整个系列。文中可能涉及到链接信息,仅仅只是做程序解释演示使用,并不能直接达到具体商品地址。图片上的二维码地址已做马赛克处理。

Image

为什么是乱码(淘口令)

对于下面这段从淘宝分享出来的文字,你除了能看懂中括号里面的问题,其它的文字是不是也能猜出个八九不离十?这段所谓的乱码文字就是淘口令。

【手撕素肉豆腐干100包素牛排整箱小包装麻辣条休闲好吃不贵的零食】點ゞ撃°鏈ㄣ接,再选择瀏覽●噐○咑№亓;或復ず■淛这句话¢HvpZYBM7U6D¢后咑閞👉淘灬寳👈

微信对于分享有很多限制,有了限制我们可以不被太多的分享信息打扰。有了限制我们就需要认识上面类似火星文的乱码,乱码为什么微信就限制不了了呢?其实也是可以限制的,在去年有一段时间就有淘客反馈,淘口令也被限制分享了。但是对于聊天内容这个还是比较容易误伤。

这个二维码是上述乱码文字生成的二维码

淘口令中有什么

上述一段文字你认识或者不认识的汉字或者符号其实都是修饰文字,里面的关键信息只有“¢HvpZYBM7U6D¢”这一句淘口令才是关键信息,这个类似与链接,其实也可以叫短链接。淘口令中首先会对应出商品链接,商品标题等信息都可以查询出来,这里我们用代码来识别一下这个淘口令。看一下代码怎么写?

Image

const { TopClient: ApiClient } = require('./lib/api/topClient.js'); // 官方可以下载到 SDK

/**
 * 按照自己的实际情况配置 KEY SECRET
 */
const client = new ApiClient({
    'appkey': APP_KEY,
    'appsecret': APP_SECRET,
    'REST_URL': 'http://gw.api.taobao.com/router/rest'
});

const tpwdQuery = tpwd => {
    return new Promise((resolve, reject) => {
        client.execute('taobao.wireless.share.tpwd.query', {
            'password_content': tpwd
        }, (err, response) => {
            if (!err) {
                resolve(response)
            } else {
                reject(err);
            }
        })
    })   
}

tpwdQuery('¢HvpZYBM7U6D¢')
    .then(res => {
        /**
         * content: 商品标题
         * native_url: 淘宝Schema地址
         * pic_url: 商品主图
         * thumb_pic_url: 商品主图缩略图
         * url: 商品链接(非商品原始链接)
         */
        console.log(res);
    })

通过代码解析我们可以看到能拿到商品的图片链接和标题图片,但是这里的商品链接不是最原始链接。上面这个链接解析出来得到的是一个可以内部券的链接,通过这个解析得到的链接可以领取一张优惠券。这里我们主要讲述的不是领券,而是要继续解析得到的参数内容,看怎么得到商品原始链接。

要得到原始链接我们需要模拟请求一下淘口令解析出来的 url。这里我们使用了 sdk 中用的 request 包。

Image


const request = require('request');

/**
 * 模拟请求获得商品详情链接
 */
function getDetailUrl(url, referer) {
    let options = {
        url,
        headers: {
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
        }
    }
    referer && (options.headers.Referer = referer);
    return new Promise((resolve, reject) => {
        request(options, (err, response) => {
            if (!err) {
                resolve(response)
            } else {
                reject(err);
            }
        })
    })
}

/**
 * 获取原始链接 https?://detail(\.m)?\.taobao|tmall\.com
 */

const getOriginUrl = tpwd => {
    return tpwdQuery(tpwd)
        .then(response => {
            // 通过解析淘口令的URL再继续解析获得商品本身地址
            return getDetailUrl(response.url)

        })
        .then(response => {
            const url = response.request.uri.href;
            // s.click 地址
            if (/s\.click\./.test(url)) {
                try {
                    const nextUrl = response.body.match(/(?<=var real_jump_address = ').*(?=')/)[0].replace(/amp;/g, '');
                    return getDetailUrl(nextUrl, url)
                        .then(response => {
                            return response.request.uri.href;
                        });
                } catch (e) {
                    return Promise.reject(e);
                }
            }
            return url;
        })
        .then(url => {
            return url;
        })

}


getOriginUrl('¢HvpZYBM7U6D¢')
    .then(res => {
        console.log(url); // 这里呢到的就是商品的原始链接了
    })

上面的代码中存在一个问题,就是对于 uland.taobao.com 的解析不能直接拿到商品信息,这个里面存在的信息后续在制作另外一个工具的时候再具体讲解,这里暂时只是做普通淘口令以及非领券淘口令的解析。

工具有什么用途

局部功能是我们解析了淘口令得到了商品链接,整理功能是我们通过商品链接再进行一次定向查询就可以得到这个商品是否存在内部券以及返利信息,这也就是我为什么做工具,如果你正在研究工具制作,或者你正在寻找适合自己的自动化推广工具,或者你想使用工具,可以通过下面图片上的演示地址来体验今晚我们的开发的工具。

后续计划

后续我们要介绍如果通过商品链接自动化查询优惠信息,对于普通用户的你可以了解这个过程是怎么来的,对于开发者来说可以借鉴里面的思想来实现一个自己的工具。感兴趣的你可以点击关注或者收藏,定期更新后续制作过程。

查看原文

赞 0 收藏 0 评论 0

unofficial 发布了文章 · 2019-10-01

凌晨有感

翻来覆去还是没有睡意,只好跟瞌睡暂时告个别,毅然爬了起来。从背包缓缓的拿出电脑,坐在地上望着窗外的一片寂静发了会儿呆。

在慢节奏的生活中,似乎少做了一些事,似乎又多做了很多事,似乎忘记了一些事,似乎又忘不掉一些事。我打开了朋友圈开启了三天可见之外的世界,我删除了太多太多的能量,留下了自认为还能代表最初自己的几条。

1095天。过的好快。 --2016年11月25日 17:49

一切都是那么自然,毕业后没有任何选择的去了专业对口的工作干了一年,这一年对自己的要求最高,可曾想过人生最精准的时刻应该就是在 0.003 - 0.005 ,不知道有没有夸大为自己多添加了一个 0 ,记忆竟然有些模糊了,唯一能记起的是这一年好想坐着上班。

毅然决然于 3 月 7 日离职了,后来却不知道自己能做什么了。这之后有尝试过按照自己的简单想法做一些事情,也有试着尝试一些其他行业,最后准备上班的前夕放弃了。选择了自己的另外一个爱好 程序,在经历投错简历的无奈之举之后,我觉得自己是不是太弱了一点,不到三天竟然被辞退了。

在种种无奈之后,我选择了去培训一下,基础再扎实一些,这个过程认识到了之前自己的知识面是 web 前端的一个范畴,不是所为的网页美工,但好像也会被叫做切图仔,其实后面我还是没有太能分清楚到底属于什么。这个过程还接触到了一门叫 PHP 的语言,也就是凭借这个我参与了第一次技术类面试,没想到的是一个额外争取的面试机会,在经历了多轮多人面试之后,我竟然在当天就拿到了 offer 。下周一来入职报道,这一天上班的时间是 2013 年 11 月 25 日。三年后我写下了这一条心情,时间真的过的好快。

0=1284,1284=0,... --2017年5月31日 18:27

这一天我主动办理了离职手续,准备开始我接下来规划的新路线。带着比较纯粹的想法离开了比较安逸的工作环境,希望可以看到一个崭新的自己。没有太多休息,下一个月的 6 月 7 日我开始投入了接下来的工作。这一次入职后的一年是最辛苦的,但是却没有感觉到任何的疲惫,抱着努力提升的心态一直在往前走。也正是这一年我觉得自己有所成长,也更清晰的对自己的职业有了一些认识,只是不知道如何对未来进行一个很好的规划。

第一天来上班,有点儿找不到北 --2017年7月28日 07:19

出差北京,刚好在百度大厦附近,突然想起了之前成都百度的小伙伴,然后装逼似的在这个位置更新了一条动态。现在想想自己好傻,如果再努力多点是不是还是有希望,不过最近我的希望好想变成了阿里,只是思想的巨人已经站了起来,却迈出了矮子的步伐,这一点深深的被自己鄙视了一番,立再多的 flag,都不如这一天的信仰。今日前几天就到处飘满五星红旗,而我的旗子却还在自己的圈子里。

15:57 走了
24:00 到了
05:00 守灵
...
5个小时做完了改动需求
...

--2017年8月16日 05:15

这一天我最亲近的人的妈妈离世了,躺在冰冷的地上,而我却还在她不远的地方支了一张桌子在做未做完的工作,这时的自己到底在想什么?现在想想有些许无奈,但却又没有任何办法,唯一能做的就是好好的照顾自己,照顾好家人。时间可以冲淡很多事情,我想多年之后又会有谁能够想起那个曾今都喜欢的你,如果能够每年在这一天来你跟前看你的或许只有这几许家人。

天黑到天亮,2‘06’‘的中国式信仰 --2017年9月11日 05:57

没有人同行,最后还是决定独自前往,瞪着一辆摩拜就去了。今天的这个日子正合适,只是茫茫人群之中没有了我,而我也渐渐的没有了这种强烈的信仰,改变自己,试着努力去外面看看是接下来想做的,或许这个梦最终实现不了,但至少我曾在路上,即使前面并不是想象的那么美好。

2019年7月11日

这一天认识了一个邻居,意外接触到了少儿编程,真的挺感兴趣的,只是无奈后面没有机会继续接触更多,自己兴趣浓厚的关注了一个很小的部分,却也不能深入进去,渐渐的好像也就不知道怎么继续了。
后面开始了对已有的一个小程序进行了重新定位,准备做一个认知类的小程序,也是围绕小朋友来做的一些游戏化程序,这个过程自己的规划想好都是停留在自己的世界,最后做好出来唯一支持自己劳动成果的却是南希,她应该是玩的最多的,而我突然觉得这些都是闹着玩似的探索,到底应该怎么发现一个机会。

2019年9月30日

这一天办公区搬家了,这一天。。。从负一爬回了家,开着冷水对自己冲了许久,到底还是没能清楚的认识自己。生活好难,好容易迷失在个人制造的美好之中。望着窗外亮着的些许灯光,对昨天的你我说声抱歉,愿一切在新的一天有一个美好的开始。这一刻着实没有了睡意,竟然坐在地上开始追忆过去的自己,有人说有一天你如果开始了回忆过去,那说明你真的开始变老了。

今天你好,我想象着这一刻我能重新认识自己,不再是单纯的局限在眼前,默默的给自己说一声,加油。

查看原文

赞 0 收藏 0 评论 0

unofficial 发布了文章 · 2019-09-15

mblock是如何让Arduino工作的(中)

上一篇文章我们主要从 WEB IDE 作为入口简单分析了一下,Arduino 是如何与 IDE 连接上的,我们发现是与用户电脑本地的建立了 websocket 连接服务。通过本地的服务查询了串口列表,以及串口脚本写入,这个过程又是如何实现的呢?

分析系列

mLink

Web 应用能够与 Arduino 一起工作,因为本地安装了一个应用 mLink ,是通过启动 mLink 在本地起了一个 websocket 服务。

发现应用

系统盘 - 应用程序 - mLink(右键)- 显示包内容 通过这个路径操作,我们可以看到应用的代码,Resources 目录下有一个项目目录 robocomm-web,看到这个项目就很熟悉了,一个 Node.js 应用。

Local Server

Local Server

Node.js 项目的入口是 package.json,通过这个入口我们可以看到项目有两个依赖包,socket.ioserialport,本地的 websocket 服务是通过 socket.io 创建的,对于 serialport 肯定是用来获取串口对应信息的一个包。

验证分析

为了验证整个分析过程是否正确,我们把 mLink 应用先关闭,这个应用本身还存在一个 Bug,关闭应用的时候本地的服务还是没有关闭。通过关口查找与进程杀死才能完全关闭。

# 端口查找
lsof lsof -i tcp:55278

# 进程杀死 下面的 PID 等于下图中的 31354
kill PID

lsof

直接启动 Node.js 项目,看能不能正常工作。项目根目录直接执行命令

node app

serialport

serialport,这是一个使用 JavaScript 访问串行端口的库。

如何使用

serialport 是所有功能(Stream Interface, Bindings,Parser streams)的集合,暂时先直接引入整个包来上一个简单的上手。

// getDevice
const Serialport = require('serialport');
serialport.list().then(res => {}); // /dev/tty.Bluetooth-Incoming-Port /dev/tty.usbmodem14201

// connect
const comName = '/dev/tty.usbmodem14201';
const port = new SerialPort(comName);

// addEventListener
port.on('open', () => {});
port.on('data', () => {});
port.on('write', () => {});
port.on('error', () => {});
port.on('close', () => {});
port.on('drain', () => {});

上述操作基本都是通过参考项目代码以及官方文档大致了解了一下,还没有实现一个完整的 DEMO。后续文章还需要了解 mBlock 传入的 cmd 为 write 操作时传入的数据是什么?block 是如何转换成为数据的?传入的数据直接通过写操作就成功写入程序了吗?带着这些疑问下一篇文章我们后续继续深入学习实现一个自己的 link。

末了

本次通过分析 mLink ,我们主要认识了一个新的库 serialport ,通过 JavaScript 就能够获取串行端口。我们回顾一下前面学习到知识,了解到 johnny-five 能过获取到端口也是使用了 serialport。

查看原文

赞 0 收藏 0 评论 0

unofficial 发布了文章 · 2019-09-10

mblock是如何让Arduino工作的(上)

从官网原版 DEMO 到 用熟悉的语言来写 DEMO ,如何用更容易让小朋友理解的方式来实现这个 DEMO 呢?今天开始陆续研究这整个过程如何实现。
在这之前了解过一些方案,例如 s4a 等一些其它方案,没有深入了解,从界面等方面来看基本都是基于 Scratch 2 来做的开发,Scratch 3 优化的更漂亮些来,有没有基于 Scratch 3 的解决方案呢?本文暂时以自己看到的内容加上自己的理解,后续按照实际的研究情况更新。

Arduino code by block

mblock

无意之间发现了 mblock ,在 Scratch 的基础上做了一些二次开发,选择设备模块,然后基于设备定制了一些元素,方便用户更直接的使用设备。

  • 编辑器内选择设备 Arduino
  • 系统内安装 mlink 驱动程序
  • 启动 mlink
  • 编辑器内连接
  • ☑️ 显示全部可连接设备
  • 选择设备端口 /dev/tty.usbmodem14101
  • 连接成功
  • 积木编程
  • 上传到设备

原理分析

它是如何工作的?为什么它通过访问网页版本,然后能直接将积木程序转换为可执行代码。
mlink 在这个过程中起到了关键性作用,本地启动的 mlink 是在本地起了一个 websocket 服务。

  • 在第四步中连接的时候实际上是建立了一个与 mlink 的服务连接 ws://127.0.0.1:55278/socket.io/?EIO=3&transport=websocket&sid=-XJBr-WPFDcGSJH6AAAF
  • 在选择设备前,一直在发心跳命令查询设备端口 getDevices
  • 选择设备端口以后,发送了一个 open 命令,这一步编辑器已经与 Arduino 建立了连接
  • 上传设备操作实际上是建立了一个 wss://arduinoserver.makeblock.com/socket.io/?EIO=3&transport=websocket&sid=xDKoLUykR3DtjL5DAG1O 连接,这一步具体做了什么?
  • 代码又是以什么形式上传到设备上去的?

这里还有一些疑问需要继续深入研究一下协议层面的内容

末了

大致有了想法,但是对于 mblock 的整个逻辑还是有一些没有理解到,还需要继续深入研究一下才能完善。

查看原文

赞 0 收藏 0 评论 0

unofficial 发布了文章 · 2019-09-09

如何用熟悉的语言玩转Arduino

今天上班有些忙,时间不是太多,借助空隙时间学习了一下如何用自己喜欢的语言来玩 Arduino。

Firmata

Arduino 可以通过 Firmata(PC 与 MCU 通讯协议) Library 来实现与计算机应用程序的通信。
我么可以使用自己喜欢的语言来实现一段程序,然后将程序写入到 Arduino 中。我们首先需要将 Firmata 协议烧写到芯片中。

烧写协议

Arduino IDE > 文件 > 示例 > Firmata > StandardFirmata

按照上述路径找到标准协议,然后上传至 Arduino

standard firmata protocol

端口查找

以下两种方式任选其一:

  • Arduino IDE > 工具 > 端口
  • 命令行工具中输入 ls /dev/tty.usb*tab

方法1
方法2

按照上述路径找到端口,后续通过 Firmata 协议与 Arduino 连接的时候需要使用该端口值。这里我们得到我的设备的端口为 /dev/tty.usbmodem14101

编写程序

这里我使用的是 javascript 来编写昨天的 Blink

firmata.js

firmata.js

const Firmata = require('firmata');

const port = '/dev/tty.usbmodem14101';
const ledPin = 2;
const board = new Firmata(port);

board.on('ready', () => {
    console.log(`connet ${port}`);
    let status = 0;
    setInterval(() => {
        status = !status + 0;
        board.digitalWrite(ledPin, status);
    }, 1000);
});

johnny-five

johnny-five

const five = require('johnny-five');
const board = new five.Board();

const ledPin = 2;

board.on('ready', function() {
    // Create an Led on pin 13
    var led = new five.Led(ledPin);
    // Blink every half second
    led.blink(1000);
});

Johnny-Five is an Open Source, Firmata Protocol based, IoT and Robotics programming framework, developed at Bocoup.
后者封装的更为简易,兼容多种类型硬件,等待后续深入学习。

末了

如何用熟悉的语言玩转Arduino
结合开源软件框架来驱动开源硬件,用熟悉的语言来驱动硬件是一件很酷的事情。后续期望结合一些其它开源做一些好玩的东西。基于 Firmata 还有一些其它语言的封装,这里我只是以自己最近使用的 JavaScript 为例子来进行来一次复盘 Blink。

查看原文

赞 1 收藏 1 评论 0

unofficial 发布了文章 · 2019-09-08

Arduino 制作第一个单LED闪烁电路

做这个实验前我们要先认识 Arduino ,接触面包板,了解电路中的元件的工作电压和工作电流等。

实验材料

本次实验需要以下零部件

  • Arduino
  • LED 灯一枚
  • 电阻一枚
  • 连接线三根
  • 面包板一个

认识 Arduino

我需要先了解以下 Arduino 板上的组件具体由什么构成。我找了一个参考图。

Arduino

序号名称描述
工作电压5V
1电源 USBArduino 板可以通过计算机上的 USB 线供电
2电源 电池插座Arduino 可以通过电池电源供电
3稳压器稳压器的的功能是控制提供给 Arduino 的电压,并稳定处理器和其他元件使用的直流电压
4晶体振荡器晶体振荡器帮助 Arduino 处理时间问题。上面有数字标识 T16.000 代表频率是 16MHZ
5,17重置重置 Arduino
6,7,8,9引脚3.3V(6) 提供 3.3V 输出电压;5V(7) 提供 5V 输出电压;GND(8) 接地;VVin(9) 此引脚可以用于外部电源为 Arduino 供电
10模拟引脚A0-A5 这些引脚可以从模拟传感器读取信号,并将其转换为可以由微处理器读取的数字值
11微控制器Arduino 的大脑
12ICSP 引脚大多数情况下,ICSP(12)是一个 AVR,一个由 MOSI,MISO,SCK,RESET,VCC 和 GND 组成的 Arduino 的微型编程头。它通常被称为 SPI(串行外设接口),可以被认为是输出的“扩展”。实际上,你是将输出设备从属到 SPI 总线的主机。
13电源 LED 指示灯Arduino 插入电源时,此灯亮说明电路板正常通电
14TX 和 RX LED在你的板上,你会发现两个标签:TX(发送)和 RX(接收)。它们出现在 Arduino UNO 板的两个地方。首先,在数字引脚 0 和 1 处,指示引脚负责串行通信。其次,TX 和 RX LED(13)。发送串行数据时,TX LED 以不同的速度闪烁。闪烁速度取决于板所使用的波特率。RX 在接收过程中闪烁。
15数字 I/OArduino UNO 板有 14 个数字 I/O 引脚(15)(其中 6 个提供 PWM(脉宽调制)输出),这些引脚可配置为数字输入引脚,用于读取逻辑值(0 或 1) ;或作为数字输出引脚来驱动不同的模块,如 LED,继电器等。标有“〜”的引脚可用于产生 PWM。
16AREF模拟参考,它有时用于设置外部参考电压(0 至 5 伏之间)作为模拟输入引脚的上限。

面包板

如何将面包板和 Arduino 连接起来使用呢?
一般默认红色、黄色和绿色为正极,蓝色和黑色为负极。我们这里选择了一根红色一根蓝色的线来连接 Arduino 和面包板。
熟悉了面包板之后知道上下区域一致(“楚河分界”,选择一边作为工作区域)。电压红蓝线之间与工作插线区域是分开的,这里需要连接线连接一下。

线路图

LED

LED 两只脚长度不一致,长脚为正级,短脚为负极。

发光二极管的反向击穿电压大于 5V,由于我们的 Arduino 的工作电压是 5V ,这里需要增加一个电阻来保证 LED 的安全,我们看来一下盒子里面的零件有 1K 4.7K 10K 的电阻,这里我选用了一个 1K 的。

备注:因为 LED 是负温度系数的 温度越高电流越大,电流越大发热越大,然后停不住就烧了。
串电阻就限制了这个过程,温度升高,电流增加,电阻上的分压增大,led 上的电压减小,电流就减小,温度就不会再上升。

程序

这里是在昨天的基础之上继续做的实验,只需要将昨晚的 Blink 代码修改一下即可使用。

拷贝一份示例代码

/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Blink
*/

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

修改一下示例代码

int ledPin = 2;

void setup() {
    pinMode( ledPin, OUTPUT );
}

void loop() {
    digitalWrite( ledPin, HIGH );
    delay( 2000 );
    digitalWrite( ledPin, LOW );
    delay( 1000 );
}

末了

在线视频

通过本次实验我们熟悉了 Arduino 板的构造,了解了如何使用面包板,对于电学知识点进行了一个简单的回顾。

查看原文

赞 0 收藏 0 评论 0

unofficial 发布了文章 · 2019-09-07

Arduino 初次见面

最近很幸运认识了一位朋友,听她讲了一些关于少儿编程的内容,出于工作原因与兴趣使然,我开始准备学习一些相关的知识。

Scratch

在这之前有过耳闻,后初略看了一下,后续目标是详细看一看,然后构建出自己的一套工具,结合硬件做一些有用的东西。

带小朋友了解了一下 ArduinoJR ,兴趣还是有的,只是怎么用她可以理解的形式给她讲解怎么玩起来,我还一时想不到好的方法,后续期望可以以此为基础做一个类似的自媒体频道来记录这个过程(这只是一个期望,感觉要立 Flag 的话可以立好多)。

Arduino

初始

在这之前我一直期望购买一套树莓派,然后做一些程序方面的玩具,一直也是没有太明确的想法,也就一直搁置了下来。最近仔细了解了 Scratch 以后搜索得到了 Arduino 这个开源硬件,对于硬件开源我无能为力,但是基于它的周边还是能做很多可以玩起来的东西(我希望这不只是想好,而是可以坚持做下去的一个爱好)。

淘宝入手 Arduino ,主要应该关注的是配件,不清楚具体做什么的情况之下,选择了标配版本,先试着熟悉熟悉,然后基于 Scratch 与 编程语言之间的转换熟悉,渐渐的再考虑后续的可玩性。

开箱

收到快递之后,果断打开看了一下书名书,面对满目的零配件,是不是有些想退缩不玩了?
开箱

Arduino 本身真的很小,比我想象之中小太多了。
Arduino

IDE 安装

说明书上的指引以及驱动盘都是以 Windows 为主, MAC 用户需要官网安装下载软件,直接 Just Download 等待下载。

应用启动以后的编辑器界面长这样的。
Arduino IDE

运行程序

电源连接运行正常
Arduino USB Link

选择一个 Example
Example

上传程序 Example 运行起来的效果是这样的

在线视频

末了

仅仅简单开了一个箱,给自己树立一个小小的目标,玩起来。在这个过程中接触一些新的东西,巩固一些自己擅长的知识,以兴趣爱好为出发点做一些可以改变心态的事情。

查看原文

赞 0 收藏 0 评论 0

unofficial 发布了文章 · 2019-07-22

如何在一个项目中兼容Wepy和Taro?

背景交待

NJ 项目启动初期,团队技术栈主要是基于 Vue,技术选择上就选择了类 Vue 的 wepy。迭代几个版本后 mpvue 出来了,简单调研了下,准备基于 mpvue-simple 开发部分页面,如果可行再慢慢切换其它页面,尝试后遇到一些问题,就暂时搁置了,还是沿用的 wepy 继续开发。

Taro 初现

在不久之后 Taro 横空出世,按照团队的情况简单对比了一下 wepy、mpvue、taro、原生组件开发。
LB 项目初期的情况是有一部分 wepy 沉淀,但是基本可以摆脱历史包袱,重新启动新业务项目,对于项目本身仅仅是一个活动小程序项目,不会做多端情况的考虑,在技术选择上因为各个技术方案基本解决的问题是多端开发以及在开发过程的舒适度上的提升。对于团队目前的情况来看,在几个小伙伴一起讨论后,还是基于 wepy 的方案来开发。

如何迁移 Taro 到 Wepy

NJ 项目本身还是基于 wepy,在迭代功能的时候,产品提出要做一个活动页面,这个活动可能在商城小程序中也会使用到,然后 NJ 继续迭代功能,需要考虑的是怎么复用商城项目组开发好的活动页面(商城项目基于 taro)。

  • 跳转到商城小程序参加活动 [pass]
  • 拷贝活动页面编译后的文件到 wepy 中直接使用 [cool]

如图,上述文件以及不需要的页面均可以直接删除,然后配置路由到 wepy project 的 app.json 。实际可能也有一些父级逻辑放置在 app.js 中,这个看自己的业务情况来定,我们项目还引入来 dva ,在 wepy 的 app.js 中增加来一个处理 dva 的文件。这个迁移过程总体来说简单容易很多,暂时不做过多描述。

如何迁移 Wepy 到 Taro

为来更为简单的迁移,这中间写了一个插件来处理公共业务,对于业务逻辑可以在回调中单独处理,具体可以参考 wepy-plugin-migratetotaro

NJ 项目经过长期迭代在线上稳定运行。同时另外一条业务线是基于 Taro 开发,也在疯狂开发迭代中。起因一次活动,XX 项目开发活动内容,NJ 项目正常需求开发,但是开发上线时需要复用 XX 项目开发好的活动页面。

由于 Wepy2 目前仍处于 alpha ,1.7.x 在开发中也遇见了不少的问题。问题虽然最终都能解决,而且作者很好沟通,咨询过几次问题也都能耐心指导解答,笔芯感谢。
再说项目实际情况,在迁移后要保证脱离 Taro 相关项目 Wepy 独立编译能够正常运行。

目录结构约定

- Taro
    - src
    - Wepy
        - src

代码管理在 taro project 以子模块的形式管理 wepy project

git submodules

# 添加子模块项目
> git submodule add <taro project url>

# 初始化本地 .gitmodules 文件
> git submodule init

# 同步远端 submodule 源码
> git submodule update

.gitmodules 示例

[submodule <submodule_name>]
    path = <local_directory>
    url = <remote_url>
    branch = <remote_update_branch_name>

迁移过程

默认配置 wepy 编译后的目录(这里建议配置到 taro 编译目录同级目录下的子目录。下文均以 Taro 编译目录 dist 为例,wepy 编译到 dist/wepy 目录下)

  • 编译目标路径配置 wepy.config.js target
  • 安装插件 wepy-plugin-migratetotaro (待开发整理发布)

    • 加载机制 require('app.js') &dollar;instance (BASE)
    • 页面自动配置所有,可以手动配置需要引入的 pages,但是编译还是会编译所有的,编译过程不可控。暂时部分页面引入控制略有问题,这里建议开发过程中以页面为维度来管理页面资源,编译后不需要的页面可以手动删除。
    • 路由处理 页面路径配置按照编译路径最后一级文件夹自动更新引入路径中的 pages 的跳转路径 (BASE)
    • 所有路径添加到子模块路由中或者主模块中 路由配置两种模式,pages 模式 和 subPackages/pages 模式。对应的配置位置不一致,这一点由插件编译处理。
    • taro 组件在 wepy 中使用,在配置中新增 needComponents 配置需要使用组件的组件和页面。

迁移过程中问题分析

① annot read property '&dollar;pages' of undefined

// 页面初始化的时候 $createPage 中 this.$instance 不存在
if (typeof pagePath === "string") {
  this.$instance.$pages["/" + pagePath] = page;
}

// this.$instance 来源于 $createApp
let app = new appClass();

if (!this.$instance) {
  app.$init(this, appConfig);
  this.$instance = app;
  this.$appConfig = appConfig;
}

// appClass 来源于参数 对应 app.wpy
// 如果页面要单独执行必须加载一下 app.wpy 但是插件处理的是编译后的文件,这里只能在每个页面 page 中单独加入 require(wepy/app.js)

② 资源引用,建议图片视频等资源使用相对路径引用,如果项目已有绝对资源路径可以通过插件回调手动替换处理

③ Taro 组件共享,见后续 taro 组件共享使用方法

如何在 wepy 中使用 taro 写的组件

这种略待代码侵入的感觉,可以使用环境变量来处理,只是使用迁移编译时才生效插件的引入。我们使用插件引入这种是在自定义底部 tabbar 后有一个页面需要。

  • wepy page 中引入 taro 项目中的 demo 组件

    config = {
        ...
    
        usingComponents: {
            'demo': '/components/demo/index'
        }
    
        ...
    }
  • template 中使用组件

    ...
    
    <demo compid="demo"></demo>
    
    ...
  • 父页面向子组件传递参数(配合插件配置 needComponents 使用,如果原生小程序或者其它框架需要使用 taro 组件可以使用类似方案)

    // 按照实际情况修改 props 和 compId
    taro.propsManager.set(
      {
        ...props
      },
      compId
    );

思索

wepy taro 解决的问题是什么?对于我而言。
一部分是追求与团队当前技术栈相契合的类似方案。
一部分是多端需求(最新的这个小程序是多个产品的数据整合,其中之前一个产品是 H5 对外可能微信小程序不是合适的选择,一个是小程序,如果统一到一起,后续小程序部分页面可能也会直接转 H5,后续还可能数据要整合到已有 APP,如此转 RN 等也是未来的需求),这一块是为以后做的考虑,如若不然还是原生的来的自然。
这中间更多的应该是思考,我们其实只是针对当前的产品选择一个适合自己的技术方案,不抱着某一种方案自始自终,也不抵触技术的更新,更多的还是需要在这业务堆积过程中不断沉淀出一些东西,然后不断更新自己的知识仓库,这个才是接下来自己要坚持完善的部分。

参考资料

wepy-plugin-migratetotaro
这是一个不相关的参考资料,可以微信扫码浏览一下就走

查看原文

赞 0 收藏 0 评论 0

认证与成就

  • 获得 105 次点赞
  • 获得 31 枚徽章 获得 3 枚金徽章, 获得 10 枚银徽章, 获得 18 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

注册于 2014-05-03
个人主页被 3k 人浏览