惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
Google DeepMind News
Google DeepMind News
S
SegmentFault 最新的问题
Project Zero
Project Zero
D
DataBreaches.Net
I
InfoQ
L
Lohrmann on Cybersecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
The Register - Security
The Register - Security
Recorded Future
Recorded Future
Vercel News
Vercel News
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
I
Intezer
The Hacker News
The Hacker News
F
Fortinet All Blogs
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
Help Net Security
Help Net Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Scott Helme
Scott Helme
T
Threatpost
爱范儿
爱范儿
N
Netflix TechBlog - Medium
D
Docker
云风的 BLOG
云风的 BLOG
C
Cisco Blogs
K
Kaspersky official blog
H
Help Net Security
S
Secure Thoughts
T
Threat Research - Cisco Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Security @ Cisco Blogs
Cyberwarzone
Cyberwarzone
N
News and Events Feed by Topic
G
Google Developers Blog
Forbes - Security
Forbes - Security
博客园 - 三生石上(FineUI控件)
博客园 - 叶小钗
B
Blog
Google DeepMind News
Google DeepMind News
Recent Announcements
Recent Announcements
Simon Willison's Weblog
Simon Willison's Weblog
S
Securelist
P
Privacy International News Feed
Spread Privacy
Spread Privacy
The Last Watchdog
The Last Watchdog

夜行人

回家路上 第一期的直播演示项目 震动检测器 正能量 在线参观CodeLab Neverland 发布 CodeLab Adapter 3.3.1 DynamicTable 之 纸糊方向盘 CodeLab DynamicTable: 一个可实施的技术方案 CodeLab Insight 发布 Alpha 版 情人节 Home Assistant 周报 && IoT 周报 (02) Joplin: 关注隐私的 Evernote 开源替代软件 浏览器的未来与 Web 传感器 Home Assistant 周报 && IoT 周报 (01) 百宝箱(01) 论自由 介绍 WebThings Home Assistant 周报 && iot 周报 (00) 百宝箱(00) 毛姆读书心得 传世之作 周末徒步 CodeLab Adapter ❤️ Jupyter/Python 航班 躲雨 夏令营途中 [译]思想--作为一种技术 The future of coding 美国之行 三门问题的程序模拟 从Python转向Pharo https://blog.just4fun.site/post/iot/iot-open-source-projects/ Python异步编程笔记 https://blog.just4fun.site/post/iot/iot-open-source-hardware-community/ 万物积木化开发者社区 CodeLab ❤️ Blender Scratch3技术分析之云变量 API(第7篇) [译]对管道(Pipes)的偏爱 [译]提出正确的问题比得到正确答案更重要 蓝牙设备与Scratch3.0 创建你的第一个Scratch3.0 Extension Scratch3技术分析之项目内部数据(第6篇) Scratch3技术分析之社区 API(第5篇) Scratch3技术分析之User API(第4篇) Scratch3技术分析之项目主页API(第3篇) Scratch3技术分析之静态资源API(第2篇) Scratch3.0、micro:bit与Windows7 https://blog.just4fun.site/post/iot/zerynth-vs-micropython/ 核聚变、方所与半宅空间 可视化编程为何是个糟糕的主意 codelab.club周末聚会 关于codelab.club '下一件大事'是一个房间 Hungry Robot - Eat everything 编程作为一种思考方式 今日简史 史蒂夫·乔布斯传 罗素自选文集 https://blog.just4fun.site/post/edx/tianjin-scratch-ai/ https://blog.just4fun.site/post/edx/richie-cms-openedx/ 徒步武功山 WebUSB与micro:bit 积木化编程与3D场景 夜宿武功山顶 scratch3-adapter接入优必选Alpha系列机器人 https://blog.just4fun.site/post/edx/video-migration-note/ scratch3-adapter重构笔记 https://blog.just4fun.site/post/edx/edx-community-members/ 两种硬件编程风格的比较 使用micro:bit自制PPT翻页笔 柏拉图对话集 scratch3.0 + micro:bit 七月电影放映计划 非营利组织的管理 Screenly--用树莓派让任何屏幕变为可编程的数字标牌 以最佳实践开始你的Django项目 micro:bit与事件驱动 为Scratch3.0设计的插件系统(上篇) OCR应用一例 近两年读过的一些好书 blockly开发之使用python驱动浏览器中的turtle(2) 牛顿新传 文学理论入门 逻辑的引擎 人生的意义 blockly开发之生成并运行js代码(1) blockly开发之hello world(0) micro:bit使用笔记 神器之Termux https://blog.just4fun.site/post/iot/micropython-notes/ Cozmo what is this Scratch的前世今生 下段旅程 我行在远方 爆裂 途中杂记 https://blog.just4fun.site/post/edx/open-edx-startup/ cozmo系列之入门 - 有性格且可编程的机器人 PaperWeekly开发笔记 创业二三事
对webduino运行流程的分析
2017-05-21 · via 夜行人

文章目录

背景

在前一篇关于blockly的文章中,我参考了webduino对Web Speech的包装,并将其移植到blockly4pi中。

webduino对blockly的使用,有许多出彩的地方。这篇文章将简要对其核心部分做个分析,为了更深入地借鉴它的设计

入手

我买了webduino的smart模块,所以我们从最简单的案例入手:将smart的led灯设为红色

首先当然是将smart连上wifi,完成后它分配到网址:192.168.0.119(显示在wifi名称中)

接着我们拼搭出积木块

运行后,成功点亮红灯

分析

首先查看上边的积木生成的代码:

1
2
3
4
5
6
7
8
var rgbled;

boardReady({board: 'Smart', url: '192.168.0.119'}, function (board) {
  board.systemReset();
  board.samplingInterval = 50;
  rgbled = getRGBLedCathode(board, 15, 12, 13);
  rgbled.setColor('#ff0000');
});

可以看到webduino通过积木生成js代码, 然后运行js代码来控制start.(我的blockly4pi同时生成js和python)

容易看出,boardReady是浏览器与start通信的代理,接着我们进入源码,去跟踪boardReaety,它定义在这里

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  function boardReady(options, autoReconnect, callback) {
    var callback = (typeof autoReconnect === 'function' ? autoReconnect : callback),
        index = boards.length,
        board = createBoard(options),
        terminate = function () {
        board = null;
    delete boards[index];
    boards.splice(index, 1);

    if (autoReconnect === true) {
        setTimeout(function () {
        boardReady(options, autoReconnect, callback);
        }, 5000);
    }
    };

    board.once(webduino.BoardEvent.ERROR, function (err) {
      if (board.isConnected) {
        board.once(webduino.BoardEvent.DISCONNECT, terminate);
        board.disconnect();
      } else {
        terminate();
      }
    });

    board.once(webduino.BoardEvent.READY, callback);

    boards.push(board);
  }

其中board定义在Board

通过EventEmitter传递全局消息

休眠一秒

在js中休眠是个有趣的话题,我们知道js是非阻塞的,webduino使用await来实现(很新的特性,之后会通过babel来在浏览器里编译,后文再说)

对应的代码是

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
(async function () {

var rgbled;


boardReady({board: 'Smart', url: '192.168.0.119'}, async function (board) {
  board.systemReset();
  board.samplingInterval = 50;
  await delay(1);
  rgbled = getRGBLedCathode(board, 15, 12, 13);
  rgbled.setColor('#ff0000');
});

}());

这部分很有意思,我们仅仅添加一个等待一秒的模块,生成的代码结构整体变了,新添加的模块并不特殊,它生成的代码为

1
2
3
4
5
Blockly.JavaScript['delay'] = function (block) {
      var value_secs_ = Blockly.JavaScript.valueToCode(block, 'secs_', Blockly.JavaScript.ORDER_NONE);
        var code = 'await delay(' + value_secs_ + ');\n';
          return code;
};

可以推测,代码在generate之前有个预处理,大概是根据generate出来的代码里是够包含await关键字来处理,我们可以搜索源码来验证我们的想法:search await,果不其然

代码执行

早期

blockly-src/demos/code/code.js Code.runJS这个好理解,早期的做法,目前被废弃

早期的执行机制如注释中说的Just a quick and dirty eval,简单粗暴

1
2
3
4
5
6
7
var code = Blockly.JavaScript.workspaceToCode(Code.workspace);
Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
try {
eval(code);
} catch (e) {
alert(MSG['badCode'].replace('%1', e));
}

后来的机制颇为费解

后来的机制

我们可以从bindClick runButton追踪起、经过Code.reloadSandbox(),在这个函数中将模块generate为代码:Code.getContext,generate的过程会判断是否需要使用babel编译,如果需要会做好编辑,在之后的程序中用babel编译它:Code.transform

如此一来我们就得到了可在普通浏览器里运行的js代码,如果是早期的做法,至此丢到eval里就结束了,目前的做法要复杂些,把代码丢到一个iframe中跑,用到了iframe-api (本质上是window.postMessage)

一些核心步骤如下:

通信过程

websocket

我们先关注采用websocket的通信过程(本地运行)

onmessage handle定义了收到smart数据的回调

值得注意的是,数据的传输使用了二进制数据

之后通过事件系统发布消息,emit的定义之处在EventEmitter emit

ps:使用mqtt与云端通信的部分在这 MqttTransport.js

控制流

有了上边这些探索,我们可以挑战最后一个问题了,控制指令是如何抵达smart的,拿最初的例子来说,把点亮红灯积木块跑起来的时候发生了什么?

首先是积木生成对应的代码

1
2
  rgbled = getRGBLedCathode(board, 15, 12, 13);
  rgbled.setColor('#ff0000');

board我们在前头说过,检索源码发现getRGBLedCathode不过是对webduino.module.RGBLed的包装

于是我们到webduino-js继续探索.我们沿着rgbled.setColor('#ff0000');一路追踪下去,看到DataTransfer.js , webduino采用二进制来通信,发送数据的地方定义在send -> sendOut 在此我们可以看到数据的发送也是用的二进制(收发都是)

其他感兴趣的地方

与页面元素交互

demo_light_click generator

参考

文章作者 种瓜

上次更新 2017-05-21