1

Squeak 与 MicroBlocks 互操作

 2 years ago
source link: http://wwj718.github.io/post/%E7%BC%96%E7%A8%8B/squeak-microblocks-interoperability/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Squeak 与 MicroBlocks 互操作

2022-09-05

Smalltalk 爱好者们期待已久的 Making Smalltalk 在上周五举行。Lounsen 提议在来一场 After Party。

6e934c02a195cd32836e268aeb55e2.jpg

我想在 After Party 上分享近期使用 Squeak 做的项目: Squeak 中的 dotPack 模拟器

为了让分享更加充实,我做了些增强,使这个 dotPack 模拟器可以跟 dotPack 实物互动。我喜欢在 MicroBlocks 里为硬件写固件,它是我迄今为止最喜欢的物理计算平台。

我就打算把分享的话题定为 《Squeak 与 MicroBlocks 的互操作》,这样我不仅能够在分享时讨论 Smalltalk,还能讨论 Smalltalk 的精神后裔: MicroBlocks,它们共享了大量的系统特性和个人计算愿景,值得一提的是 MicroBlocks 的创始者 John Maloney 也是 Squeak 创始团队的成员,John Maloney 在 Squeak 的贡献包括: Smalltalk-to-C 翻译器(可移植性的关键)、第一个 Squeak VM (Mac)、Morphic 用户界面框架…

原定 2 小时的 After Party,持续了 3 个小时,虽然大家都是 Smalltalk 爱好者,依然被 Smalltalk 的灵活和强大所震惊,我们几乎是一边讨论,一边实时编程,在系统中探索碰撞出的新想法,而且几乎总是能够实现突如其来的灵感。

制作出色且可扩展的系统的关键在于设计模块的通信方式,而不是设计其内部属性和行为应该是什么 – Alan Kay

我最初打算在 Squeak 中使用串口(serial)来跟 dotPack 硬件通信,后来发现 Squeak 中的串口插件(MacOS)年久失修。于是打算采用网络来通信(dotPack 使用 ESP32,所以能够支持网络)。

前后设计了两个版本的通信机制。

  • 基于 HTTP 的互操作
  • 基于 UDP 的互操作

相关的源码都已经放到 Github: DotPack

只需把 DotPack.st 下载下来拖到 Squeak 桌面(确保后缀是.st, MacOS 会把后缀名改为 txt,最好在命令行里检查一下),然后选择 fileIn entire file 即可载入相应的 DotPack 包。

你在 browser 里应该能看到 DotPack。

基于 HTTP 的互操作

HTTP 是一个服务端和客户端模型,在我们的案例里,MicroBlocks 中的程序充当服务端,Squeak 充当客户端。

我们先来看下 MicroBlocks 里的程序:

squeak-microblocks-01.png

.

前边说到 MicroBlocks 是 Smalltalk 的精神后裔,它具有大量 Smalltalk 的典型特征, 诸如 “活性(liveness)“的环境: 你可以实时与环境交互,每一块积木都是活的,点击它将实时得到反馈: 你将看到积木的功能, 如果你用过 Scratch,你对此应该十分熟悉,这种方式支持你以建构主义的方式自由探索系统,整个系统是一个活的文档,它通过响应你来帮助你理解它。一旦你接触过这种编程体验,就再也无法忍受大多数编程环境。硬件领域的编程环境更是令人难以忍受。

计算机应该像乐器,它应该对用户的操作作出即时且一致的响应。想象一下,在吹出一个音符和听到它之间的一秒钟的延迟是多么荒谬!

我喜欢的一个演示是以交互的方式应答 HTTP 请求。你可以先点击 HTTP 服务器请求 积木,对用户的请求做一番探索,等你玩够了,再决定 回应xx至HTTP请求, 对客户端来说一切正常,Ta 完全不知道有一个人手动处理了他的请求!这是一个真正的"人工"智能服务器!

我最初使用 Squeak 内置的 HTTP 客户端编程跟 MicroBlocks http server 通信,结果遇到一个问题, 我把问题反馈给了 John, John 给出了精彩分析, 记录在此: https://bitbucket.org/john_maloney/smallvm/issues/287/http-server-can-not-work-with-squeak

这个问题通信的双方(Squeak 和 MicroBlocks)都有责任,MicroBlocks 的责任多一些,John 说近期会修复。

后来我用 curl 暂时绕开了这个问题。

为了在 Squeak 中使用 curl, 需要 Squeak 与宿主系统的互操作,让 Squeak 能够调用 shell 命令。CommandShell 是很棒的选择。这是我的意料之外的收获,当我决定用 Squeak 时,我几乎做好了放弃在 Unix/Linux 下积累的经验(我从大二开始用 Linux,差不多十年的经验)。现在这些经验突然又能够在 Squeak 里使用了, Unix/Linux 里有大量实用小工具,一口气都丢了真有些可惜。更加意料之外的是, CommandShell 支持 Unix 管道(pipe), 而且能够用 Squeak 的 inspect 增强它! 这样一来,我不仅没有丢掉 Unix/Linux 工具,还能够随时使用 Squeak 增强它们!

为了在 Squeak 里调用 shell 命令,需要现在 squeak 安装 CommandShell:

MCMcmUpdater updateFromRepository: 'http://www.squeaksource.com/OSProcess'
MCMcmUpdater updateFromRepository: 'http://www.squeaksource.com/CommandShell'

Squeak 客户端中相关代码:

pack := DotPack new.
pack stopStepping.
pack clear.

pack withDevice: true deviceAddress: #[192 168 1 8]. "IP Address"
pack sendMessageWith: 'HTTP'. "default"
pack clear.

pack x: 1 y:1 color: Color red.
1 to: 16 do: [:i | pack x: i y:i color: Color red].
1 to: 16 do: [:i | pack x: i y:i color: Color blue].

以下是一个演示视频:

通过在 browser 中探索 DotPack 类,你应该能很快弄懂它的工作方式。

我把视频分享给 John,John 觉得很有意思。他建议我试试他最近设计的 UDP 积木,代码将更简单,响应速度也会更快。

基于 UDP 的互操作

这个版本是在分享开始前的半个小时前做的。我突然想在 16x16 的粗糙"屏幕"上构建出鼠标的幻觉

为了获得足够好的实时性,我决定试一试 UDP。

MicroBlocks 中的程序

squeak-microblocks-02.png

Squeak 客户端中相关代码:

pack := DotPack new.
pack stopStepping.
pack clear.

pack withDevice: true deviceAddress: #[192 168 1 8]. "IP Address"
pack sendMessageWith: 'UDP'.
pack clear.

pack x: 1 y:1 color: Color red.
1 to: 16 do: [:i | pack x: i y:i color: Color red].
1 to: 16 do: [:i | pack x: i y:i color: Color blue].

Python client & MicroBlocks UDP server

以下是使用 Python UDP 客户端 与MicroBlocks 的 UDP 服务交互的例子, 运行以下代码将把 dotPack (8,8) 位置的 LED 点亮为红色。

# https://wiki.python.org/moin/UdpCommunication
import socket

ip = "192.168.1.8"
port = 5000
x,y = (8,8)
r,g,b = (255,0,0)
color = r<<16|g<<8|b
message = "setpixel,{},{},{}".format(x,y,color)
sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.sendto(message.encode(), (ip, port))

netcat(nc) client & MicroBlocks UDP server

echo ‘setpixel,8,8,255’ | nc -u 192.168.1.8 5000 -w0


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK