解决Android Studio Electric Eel | 2022.1.1 Patch 2系统下gradle.properties中文注释乱码

以前在 Windows系统上的 Android Studio 上编辑 gradle.properties 的时候增加了不少的中文注释,现在升级到 Android Studio Electric Eel | 2022.1.1 Patch 2 结果发现中文都变成乱码了。

原因是升级到 Android Studio Electric Eel | 2022.1.1 Patch 2 之后,Windows系统上 gradle.properties 的默认编码格式被设置成了 ISO-8859-1 ,导致文件显示乱码。

现在调整回 UTF-8 格式即可解决问题。如下图:

继续阅读解决Android Studio Electric Eel | 2022.1.1 Patch 2系统下gradle.properties中文注释乱码

优化Android Studio构建速度

构建时间太长会拖慢您的开发过程。本页将介绍一些有助于解决构建速度瓶颈的技巧。

提高应用构建速度的一般过程如下:

  1. 采取一些对大多数 Android Studio 项目立竿见影的措施,优化 build 配置
  2. 对构建进行性能剖析,确定并诊断一些对您的项目或工作站来说比较棘手的瓶颈问题。

开发应用时,您应尽可能将其部署到搭载 Android 7.0(API 级别 24)或更高版本的设备中。较新版本的 Android 平台有更出色的机制来向您的应用推送更新,例如 Android 运行时 (ART) 以及对多个 DEX 文件的原生支持。

注意:您完成首次干净构建后,可能会注意到后续构建(干净和增量)的执行速度明显加快了(即使您没有使用本页面介绍的任何优化措施)。这是因为 Gradle 守护程序有一个性能提升“预热”期,类似于其他 JVM 进程。

优化 build 配置

按照下面的提示操作,以提高 Android Studio 项目的构建速度。

保持工具处于最新状态

几乎每次更新时,Android 工具都会获得构建方面的优化和新功能,本页介绍的一些提示假设您使用的是最新版本。为了充分利用最新的优化措施,请确保以下工具始终是最新版本:

避免编译不必要的资源

避免编译和打包不测试的资源(例如,其他语言本地化和屏幕密度资源)。您可以仅为“dev”变种的版本指定一个语言资源和屏幕密度,如下面的示例中所示:

尝试将 Gradle 插件门户放置在最后

在 Android 中,所有插件都位于 google() 和 mavenCentral() 代码库中。不过,build 可能需要使用 gradlePluginPortal() 服务解析的第三方插件。

Gradle 会按照声明的顺序搜索代码库,因此,如果先列出的代码库包含大多数插件,build 性能就会得到提升。因此,您可以尝试将 gradlePluginPortal() 条目放置在 settings.gradle 文件的代码库中最靠后的位置。在大多数情况下,这样可以最大限度地减少冗余插件搜索次数,并提高构建速度。

如需详细了解 Gradle 如何导航多个代码库,请参阅 Gradle 文档中的声明多个代码库

将静态 build 配置值用于调试 build

始终为会进入调试 build 类型的清单文件或资源文件的属性使用静态值。

您每次想运行更改时,都需要完整的应用 build 才能使用动态版本代码、版本名称、资源或可更改清单文件的任何其他构建逻辑,即使实际更改可能仅需要 1 次热交换也是如此。如果您的 build 配置需要此类动态属性,请将这些属性隔离到您的发布 build 变体中,并使相应值对您的调试 build 保持静态,如下例所示:

如需了解如何在项目中设置动态版本代码,请参阅 GitHub 上的 setVersionsFromTask 配方

使用静态依赖项版本

在 build.gradle 文件中声明依赖项时,请避免使用动态版本号(以加号结尾的版本号,例如 'com.android.tools.build:gradle:2.+')。使用动态版本号可能会导致意外的版本更新和难以解析版本差异,并会因 Gradle 检查有无更新而减慢构建速度。 请改用静态版本号。

创建库模块

在应用中查找可以转换成 Android 库模块的代码。以这种方式将您的代码模块化,可以让构建系统仅编译您修改的模块,并缓存输出以用于未来的构建。此外,这种方式也会让并行项目执行更有效(当您启用该优化时)。

为自定义构建逻辑创建任务

创建构建性能剖析报告后,如果性能剖析报告显示相当长的一部分构建时间用在了“配置项目”阶段,请检查 build.gradle 脚本并查找您可以添加到自定义 Gradle 任务中的代码。将某些构建逻辑移到任务中后,您可以确保它仅在需要时运行,可以缓存结果以用于后续构建,并且该构建逻辑将可以并行运行(如果您已启用并行项目执行)。如需详细了解自定义构建逻辑的任务,请参阅官方 Gradle 文档

提示:如果您的构建包含大量自定义任务,您可能需要通过创建自定义任务类来整理 build.gradle 文件。将您的类添加到 project-root/buildSrc/src/main/groovy/ 目录中;Gradle 会自动将这些类添加到项目中所有 build.gradle 文件的类路径中。

将图片转换为 WebP 格式

WebP 是一种既可以提供有损压缩(像 JPEG 一样)也可以提供透明度(像 PNG 一样)的图片文件格式,不过与 JPEG 或 PNG 相比,WebP 格式可以提供更好的压缩。

减小图片文件大小可以加快构建速度(无需在构建时进行压缩),尤其是当应用使用大量图片资源时。不过,在解压缩 WebP 图片时,您可能会注意到设备的 CPU 使用率有小幅上升。通过使用 Android Studio,您可以轻松地将图片转换为 WebP 格式

停用 PNG 处理

即使您不将 PNG 图片转换为 WebP 格式,仍然可以在每次构建应用时停用自动图片压缩,以加快构建速度。

如果您使用的是 Android Gradle 插件 3.0.0 或更高版本,则系统会在默认情况下针对“调试”编译类型停用 PNG 处理。如需针对其他 build 类型停用此优化,请将以下代码添加到 build.gradle 文件中:

由于 build 类型或产品变种不定义此属性,因此在构建应用的发布版本时,您需要手动将此属性设置为 true

使用 JVM 并行垃圾回收器进行实验

通过配置 Gradle 所用的最佳 JVM 垃圾回收器,可以提升构建性能。虽然 JDK 8 默认配置为使用并行垃圾回收器,JDK 9 及更高版本已配置为使用 G1 垃圾回收器

为提高构建性能,我们建议您使用并行垃圾回收器测试 Gradle 构建。在 gradle.properties 中设置以下内容:

如果此字段中已设置了其他选项,请添加一个新选项:

如需衡量采用不同配置时的构建速度,请参阅对构建进行性能剖析

增加 JVM 堆大小

如果您发现构建速度较慢(尤其是在 Build Analyzer 结果中发现构建时间超时 15% 的情况),则应增加 Java 虚拟化机器 (JVM) 堆大小。 在 gradle.properties 文件中,将限制设置为 4 GB、6 GB 或 8 GB,如以下示例所示:

然后测试构建速度是否有提升。确定最佳堆大小最简单的方法是增加限额,然后测试是否有足够的构建速度提升效果。

如果您还使用 JVM 并行垃圾回收器,则整行命令应如下所示:

您可以通过开启 HeapDumpOnOutOfMemoryError 标记分析 JVM 内存错误。这样,JVM 会在内存耗尽时生成堆转储。

使用非传递 R 类

使用非传递 R 类可为具有多个模块的应用构建更快的 build。这样做有助于确保每个模块的 R 类仅包含对其自身资源的引用,而不会从其依赖项中提取引用,从而帮助防止资源重复。这样可以获得更快的 build,以及避免编译的相应优势。这是 Android Gradle 插件 8.0.0 及更高版本中的默认行为。

从 Android Studio Bumblebee 开始,新项目的非传递 R 类默认处于开启状态。 对于使用早期版本的 Android Studio 创建的项目,请依次前往 Refactor > Migrate to Non-transitive R Classes,将项目更新为使用非传递 R 类。

如需详细了解应用资源和 R 类,请参阅应用资源概览

使用非常量 R 类

您可在应用和测试中使用非常量 R 类字段,以提高 Java 编译的增量并允许进行更精准的资源缩减。 对库而言,R 类字段始终不是常量,因为在为依赖于相应库的应用或测试打包 APK 时,资源会进行编号。 这是 Android Gradle 插件 8.0.0 及更高版本中的默认行为。

停用 Jetifier 标志

由于大多数项目都直接使用 AndroidX 库,因此您可以移除 Jetifier 标志,以便获得更好的构建性能。如需移除 Jetifier 标志,请在 gradle.properties 文件中设置 android.enableJetifier=false

Build Analyzer 可以执行一项检查,确认是否可以安全移除该标记,使您的项目能够具有更好的构建性能,并不再使用未加维护的 Android 支持库。如需详细了解 Build Analyzer,请参阅排查构建性能问题

使用配置缓存(实验性功能)

配置缓存是一项实验性功能,可让 Gradle 记录有关构建任务图的信息,并在后续 build 中重复使用该任务图,而不必再次重新配置整个 build。

如需启用配置缓存,请按以下步骤操作:

  1. 检查所有项目插件是否兼容。

    使用 Build Analyzer 检查项目是否与配置缓存兼容。Build Analyzer 会运行一系列测试 build,以确定是否可以为项目启用该功能。请参阅问题 13490,查看受支持的插件列表。

  2. 将以下代码添加到 gradle.properties 文件:

启用配置缓存后,当您首次运行项目时,build 输出应该会显示 Calculating task graph as no configuration cache is available for tasks。 在后续运行期间,构建输出应该会显示 Reusing configuration cache

如需详细了解配置缓存,请参阅配置缓存深度解析这篇博文和有关配置缓存的 Gradle 文档。

参考链接


RS485 软件流控 及 数据完整性确保

首先 串口 的流控大家应该都有所了解,通常是硬件 CTS/RTS 或软件 XON/XOFF 这两种流控方式,然而因为 RS485 是总线形式,所以传统的方法都不再适用。

有人会觉得奇怪,貌似从来没有考虑过 RS485 流控的问题,没错,传统 RS485 都是一收一发,用不着考虑流控,然而这种一收一发的效率比较低,譬如在 IoT 火热的今天,如果用 RS485 来传输网络数据,那么传统的做法就很低效了。

然后,针对数据完整性确保的问题,很多同行都没有留意到一个细节问题,他们通常判断是否收到回复 OK 的数据包,如果没收到数据包就超时重发一次。 这种做法大多情况都没有问题,但是某些场景,譬如发送一个命令让滑轨左移 10mm, 滑轨成功接收命令并返回 OK, 然而主机因为干扰等各种问题没有收到滑轨的回复,那么重发命令就会导致滑轨错误左移 20mm. 当然你可以说目前用到的设备都是绝对位置控制,不会有影响,但万一哪天新做一个设备,到那时再改协议,难道就不考虑兼容自己以往的产品了吗?

当然还是有很多朋友有注意到这个问题,本文使用的解决方法原理上跟这些朋友也是相同的。

我接下来提出的方案最大的亮点是共用同一套机制,同时解决了流控、数据完整性确保、大数据分包等功能,而且比较高效和简单。

同样,最底层的协议我们依然使用 CDBUS, 因为它比较简单,又支持硬件增强(可以主动避让冲突,实现多主机、对等通讯、主动上报数据等功能),能最大程度体现出本文方法的性能优势。

你可能没有听过 CDBUS 这个名字,但你可能曾经或正在使用相似的协议,它的组成包含 3 个部分: - 3 个字节的头:「源地址,目标地址,用户数据长度」 - 0~255 字节的用户数据(因为数据长度用 1 个字节表示) - 2 个字节的 CRC 校验,涵盖整个数据包,校验算法同 ModBus.

数据包与数据包之间要有一定的空闲时间,来隔开不同的数据包,详细请参见 CDBUS 的协议定义: https://github.com/dukelec/cdbus_ip

譬如地址 0x00 为主机,0x01 为 1 号从机,那么主机发送两个字节数据 0x10 0x11 给 1 号从机的完整数据为:

然后 1 号从机回覆单个 0x10 给主机:

然而 CDBUS 只是最底层的协议,接下来我们要定义上述用户数据的格式,最简单常用的方式就是首字节为命令号,然后后面跟可选命令参数; 回覆数据第一个字节通常为状态,然后是返回的数据。

这种方式完善之后也有一个名字,叫 CDNET, 它的定义在:https://github.com/dukelec/cdnet
(本文的内容这个连接都有包含,但本文会更加通俗的讲解一下关键细节。)

CDNET 协议有 3 个级别,由首字节的高两位决定:

实际使用根据情况自由选择某一个或某几个来用就好。

Level 0 格式
请求
首字节:

CDNET 的端口号可以看做类似电脑的 UDP 端口,也可以看做是一个命令号。

第二字节及其后:命令参数

回复
首字节:

例如: 回复 [0x40, 0x0c] 和回复 [0x6c] 是相同的意思。

首字节的用户数据(如果有)、第二个字节及其后:回复的状态 和/或 数据。

Level 1 格式
首字节:

MULTI_NET & MULTICAST

这个与本文主题无关,就不展开了。

SEQUENCE
0: 无序列号;
1: 追加 1 字节序列号 SEQ_NUM, 这个是重点,稍后会主要说明。

PORT_SIZE:

注: - 默认端口通常定为 0xcdcd, 所以不用额外追加字节. - 追加的字节按顺序,先是 src_port 再是 dst_port.

Level 2 格式
首字节:

注: - 使用分包功能的时候必须同时选择使用 SEQUENCE. - 开始分包的时候 SEQ_NUM 不需要归零.

一般情况下,要求不高,使用最简单的 Level 0 格式就好了,如果命令比较多,那么就可以用 Level 1 格式,用不到的功能不用理会即可。

Level 1 没有大数据分包功能,因为通常 MCU 也用不到那么大的数据包,即使是烧录代码这种要传大数据的功能,也是可以在命令内部定义地址和数据长度的,譬如我的 STM32 总线代码升级的命令定义:

而 Level 2 譬如可以用来传 IPv4/v6 数据包,那么就不得不加入拆包的功能了。因为 Level 1 和 Level 2 的序列号部分是一样的,所以接下来就混在一起讲了。

CDBUS 协议将前 0~9 保留专用,10 及其后的用户可以随便用,保留的部分目前也就用了 4 个,而且也不是强制的,用户愿意实现就实现,不用或者自己想怎么用就怎么用也没问题。 上篇文章说了端口或命令 0x01 是用来查询设备信息的,命令 0x03 是用来设置地址的,还详细说了如何使用这两个端口来实现地址自动分配,剩下两个端口其中 0x02 是用来设置波特率的, 对于本文最关键的端口 0x00 是用于流控、完整性确保、大数据拆包的了,其定义如下:

Port 0
配合 Level 1 和 2 头中的 SEQUENCE 字段使用。
命令启用 SEQUENCE 后追加的对应字节 SEQ_NUM[6:0] 的低 7 位会每次自动加 1.
而 SEQ_NUM 的第 7 位用来指示接收方是否要报告状态。
Port 0 本身的命令不可以启用 SEQUENCE.

Port 0 命令定义:

实际示例:
(-> 和 <- 是端口层的数据流, >> 和 << 是 CDNET 数据包层面的数据流,不含最低层的 CDBUS 的部分)

效率提升的重点就在这里,我们可以自行选择多久回复一次,而不是每次都要回复状态,如果最后一次数据包没有标注需要回复,那么会引发超时,然后主动读一次目标的 SEQ_NUM 以做同步。 之所以引发超时,是因为所有发出的数据包都不能立刻释放,要等确认对方收到才会释放,以防需要出错重传。 因为有 SEQ_NUM 号,所以即使同一个命令重复发送,对方也会只执行一次。

流控的功能也包含在内,譬如发送方时刻只允许最多 6 个数据包没有释放,那么等收到回复,释放掉 3 个,再发送 3 个数据包,这样可以最大化的利用总线带宽。 而且万一有多方发送数据至同一个节点,发送方也可以因频繁超时,来动态降低最大允许 pending 的数据包数量。

再来说大包拆分,也是很简单,拆分包有 3 个标记,分别是起始、继续、结束,譬如一个大包拆开了 4 个小包,且如果当前 SEQ_NUM 为 23,那么这四个小包的 SEQ_NUM 和标记对应关系就是:

这样接收方也就很容易的把四个小包还原成原始的大包,万一出问题,也只是重新传输错掉或丢掉的包(及其后的包)。

为了简便,对于 CDNET 协议,并不是丢一个包就只重传一个包,其后传的包也需要重传,因为接收方只是简单判断序号,不对便拒绝接收,这么做是为了保持简单,毕竟错包、丢包的概率很低。

最后,想说的是,这篇文章的内容都是经过实践检验的,我有用来传输摄像头视频,DEMO 可以在这篇介绍文章中看到:https://github.com/dukelec/cdbus_doc/blob/master/intro_zh.md

协议的实现部分代码也是开源的,就是上面的 CDNET 连接,另外有一些使用 CDNET 的示例代码,譬如这个 STM32F103 的步进电机控制器:https://github.com/dukelec/stepper_motor_controller

当然,这些代码、库我也会进一步优化改善。

参考链接


RS485 软件流控 及 数据完整性确保

完整教程:设计一款小巧但强大的传感器

由IEEE制定的新型单对以太网(SPE)或10BASE-T1L物理层标准,为传输设备运行状况信息实施状态监测(CbM)应用提供了新的连接解决方案。SPE提供共享电源和高带宽数据架构,可通过低成本双线电缆在超过1000米的距离实现10 Mbps数据和电源的共享。

ADI公司设计了业界首款10BASE-T1L MAC-PHY(ADIN1110),这是一款集成MAC的单对以太网收发器。ADIN1110使用简单的SPI总线与嵌入式微控制器通信,从而可降低传感器的功耗并减少固件开发时间。

在本文中,您将了解如何设计一款体型小巧但功能强大的传感器,如图1所示。本文将介绍:

● 如何设计小型共享数据和电源通信接口

● 如何为传感器设计超低噪声电源

● 微控制器和软件架构选择

● 选择合适的MEMS振动传感器

● 集成数字硬件设计和机械外壳

● 电脑上的数据采集UI示例

继续阅读完整教程:设计一款小巧但强大的传感器

【玩转ESP32】ESP32串口使用

1、ESP32串口

ESP32芯片有三个UART控制器(UART0, UART1UART2),其中UART0GPIO3用于U0RXDGPIO1用于U0TXD)用作下载、调试串口,引脚不可改变;

UART1UART2的引脚是可以设置的。 UART1默认引脚是GPIO9用作U1RXDGPIO10用作U1TXD,但是这两个引脚也是用于外接flash的,因此在使用UART1的时候需要设置其他引脚;

UART2默认引脚是GPIO16用作U2RXDGPIO17用作U2TXD

2、API

components/driver/include/driver/uart.h中可以查看api;

在examples/peripherals/uart中也可以参考官方的各种串口例程。

2.1、安装uart驱动

这里要注意参数:uart_queue属于freertos里面的队列句柄,在这里表示用于指示来自串口底层中断的队列消息。

2.2、uart参数配置

2.3、接收阈值设置

2.4、串口引脚设置

2.5、从接收缓冲区读取数据

2.6、数据写入发送缓冲区

3、代码实现

3.1、参数定义

3.2、串口初始化

3.3、串口任务函数

4、使用总结

  1. 初始化串口参数,(队列指针、缓冲区、引脚等);
  2. 任务中阻塞等待串口队列 。

如何实现 ESP32 固件的 OTA 在线升级更新

1、背景

在实际产品开发过程中,在线升级可以远程解决产品软件开发引入的问题,更好地满足用户需求。

2、OTA 简介

OTA(空中)更新是使用 Wi-Fi 连接而不是串行端口将固件加载到 ESP 模块的过程。

2.1、ESP32 的 OTA 升级有三种方式:
  • Arduino IDE:主要用于软件开发阶段,实现不接线固件烧写
  • Web Browser:通过 Web 浏览器手动提供应用程序更新模块
  • HTTP Server:自动使用http服务器 - 针对产品应用

在三种升级情况下,必须通过串行端口完成第一个固件上传。

OTA 进程没有强加的安全性,需要确保开发人员只能从合法/受信任的来源获得更新。更新完成后,模块将重新启动,并执行新的代码。开发人员应确保在模块上运行的应用程序以安全的方式关闭并重新启动。

2.2、保密性 Security

模块必须以无线方式显示,以便通过新的草图进行更新。 这使得模块被强行入侵并加载了其他代码。 为了减少被黑客入侵的可能性,请考虑使用密码保护您的上传,选择某些OTA端口等。

可以提高安全性的 ArduinoOTA 库接口:

已经内置了某些保护功能,不需要开发人员进行任何其他编码。ArduinoOTA和espota.py使用Digest-MD5来验证上传。使用MD5校验和,在ESP端验证传输数据的完整性。

2.3、OTA 升级策略 - 针对 HTTP

ESP32 连接 HTTP 服务器,发送请求 Get 升级固件;每次读取1KB固件数据,写入Flash。

ESP32 SPI Flash 内有与升级相关的(至少)四个分区:OTA data、Factory App、OTA_0、OTA_1。其中 FactoryApp 内存有出厂时的默认固件。

首次进行 OTA 升级时,OTA Demo 向 OTA_0 分区烧录目标固件,并在烧录完成后,更新 OTA data 分区数据并重启。

系统重启时获取 OTA data 分区数据进行计算,决定此后加载 OTA_0 分区的固件执行(而不是默认的 Factory App 分区内的固件),从而实现升级。

同理,若某次升级后 ESP32 已经在执行 OTA_0 内的固件,此时再升级时 OTA Demo 就会向 OTA_1 分区写入目标固件。再次启动后,执行 OTA_1 分区实现升级。以此类推,升级的目标固件始终在 OTA_0、OTA_1 两个分区之间交互烧录,不会影响到出厂时的 Factory App 固件。

3、OTA 实例解析

3.1、Arduino IDE方案固件更新

从 Arduino IDE 无线上传模块适用于以下典型场景:

在固件开发过程中,通过串行加载更快的替代方案 - 用于更新少量模块,只有模块在与 Arduino IDE 的计算机相同的网络上可用。

参考实例:

3.2、Web Browser 方案固件更新

该方案使用场景:

直接从 Arduino IDE 加载是不方便或不可能的

用户无法从外部更新服务器公开 OTA 的模块

在设置更新服务器不可行时,将部署后的更新提供给少量模块

参考实例:

3.3、HTTP 服务器实现更新

ESPhttpUpdate 类可以检查更新并从 HTTP Web 服务器下载二进制文件。可以从网络或 Internet 上的每个 IP 或域名地址下载更新,主要应用于远程服务器更新升级。

参考实例:

refer:

参考链接


esp32在Arduino 1.8下的I2C引脚

终于知道为什么esp的IO21和IO22引脚是SDA和SCL的默认接口。
恐惧:恐惧是给C++的,我这几天正好在网上看到别人说,C++语法可以特别特别恶心,常量特别特别难定位。我就在想有多难,有多恶心,CTRL+f很快就定位到了。然后这几天头头在捣鼓传感器,我就在旁边看着,学习学习。记下了当时他接的引脚号,回去自己捣鼓捣鼓,一般来说,接传感器都是要在程序里指定引脚的,我看了看样例代码里也没有指定就很纳闷(我也在头文件里面找,也没找到)。就问头头,为什么=这个不指定引脚啊?头头很随意的说“因为这个是使用I2C的接口,只需要指定传感器的编号(相当于人的手机号,每类传感器都有一个,也可以人为设定),esp32会自动扫描在总线上的设备,不用管接哪个引脚。”那我听了这话,就很感慨,原来现在传感器也这么智能了,就试了试其他的引脚,不行,我大概尝试了几十种组合方式,除了头头的那一种其他的都不行。这个时候也不好意思去问头头 ,感觉很简单的一个东西。于是就上网看看I2C协议,再看看一些实例,哦,原来随便接是说在同一个I2C接口上可以随便接很多个传感器,在这个I2C接口上会自动的扫描不同的传感器设备。好,那我们来看看esp32上的I2C接口是哪个引脚。如果不出所料应该是头头用的IO21,22

继续阅读esp32在Arduino 1.8下的I2C引脚

根据温度、气压计算海拔高度

有趣的是,这个简单的内容居然在国内的网站上很难搜索。不过无妨,毕竟是学过多年英语的人,链接在此。闲话不说,请看公式

1. hypsometric 公式

$ \Large h = \frac{[(\frac{P_0}{P})^{\frac{1}{5.257}}-1] \times (T + 273.15)}{0.0065} \tag{1}$

(1)

其中,$P_0$为标准大气压强,取值 $101.325 {\rm kPa}$; $P$为实际测量的大气压强,单位 ${\rm kPa}$; $T$为实际测量温度,单位 ℃。

上式中( T + 273.15 )是将摄氏度转化为华氏度。该公式同时考虑为温度和压强计算海拔高度,计算结果的单位是米。

2. barometric 公式

$\Large h = 44330 \times \left [ 1 - (\frac{P}{P_0})^{\frac{1}{5.255}} \right ] \tag{2}$

(2)

其实该公式只是只是(1)式在一定条件下取值,不考虑温度的影响,计算结果的单位是米。

继续阅读根据温度、气压计算海拔高度

MicroPython入坑记(四)关于MicroPython的代码保护

脚本开发东西,可能面临的第一个问题就是:拷给别人,代码怎么写的他不就都知道了?不行,我要保住我的小秘密!

先说下结果:没有攻不破的堡垒,即使你写成C语言,只要能拿到二进制结果,都可以反汇编逆向出你是怎么实现的,关键是值不值得

另外,这跟逆向者对系统的了解程度有关,比如对方连代码都不会上传,那你即使把源文件放进去也他也无可奈何。

好了,言归正传,我们知道普通python有个编译成字节码的功能,也就是源代码会在解释时先编译成一个类似java中间代码的结果,这是不可读的(但是这也不排除反编译的可能,毕竟JAVA的class文件是有反编译软件的)。

micropython也有这个功能,不过这个文件的扩展名是mpy,也不能在运行时自动生成,需要一款软件:mpy-cross.exe,这是micropython官方提供的,可以用python pip直接安装,安装完成后,可以运行mpy-cross.exe pythonfile,py,就可以生成一个pythonfile.mpy的字节码文件,这文件使用跟py文件是等效的。把所有文件生成mpy,可以在一定程度上保护你的代码。

更进一步的方式:把mpy文件藏到固件中去,这不光能保护代码,还能降低程序的内存占用,官方的描述如下:

Cross-installing packages with freezing

For the low-memory MicroPython ports, the process described in the previous section does not provide the most efficient resource usage,because the packages are installed in the source form, so need to be compiled to the bytecome on each import. This compilation requires RAM, and the resulting bytecode is also stored in RAM, reducing its amount available for storing application data. Moreover, the process above requires presence of the filesystem on a device, and the most resource-constrained devices may not even have it.

The bytecode freezing is a process which resolves all the issues mentioned above:

  • The source code is pre-compiled into bytecode and store as such.
  • The bytecode is stored in ROM, not RAM.
  • Filesystem is not required for frozen packages.

Using frozen bytecode requires building the executable (firmware) for a given MicroPython port from the C source code. Consequently, the process is:

  1. Follow the instructions for a particular port on setting up a toolchain and building the port. For example, for ESP8266 port, study instructions in ports/esp8266/README.md and follow them. Make sure you can build the port and deploy the resulting executable/firmware successfully before proceeding to the next steps.
  2. Build MicroPython Unix port and make sure it is in your PATH and you can execute micropython.
  3. Change to port’s directory (e.g. ports/esp8266/ for ESP8266).
  4. Run make clean-frozen. This step cleans up any previous modules which were installed for freezing (consequently, you need to skip this step to add additional modules, instead of starting from scratch).
  5. Run micropython -m upip install -p modules <packages>... to install packages you want to freeze.
  6. Run make clean.
  7. Run make.

After this, you should have the executable/firmware with modules as the bytecode inside, which you can deploy the usual way.

大体的意思是这样的:运行py文件不能有效的使用内存资源,因为代码执行时需要被编译成bytecode代码,该编译需要RAM,生成的字节码也存在RAM中,这就降低了可用内存。并且存储py文件需要文件系统,而一些嵌入设备本身不存在文件系统。

嗯,神一样的保护功能,不但降低了内存占用,还把字节码藏到了固件中,代价就是需要自己编译micropython固件。

参考链接


MicroPython入坑记(四)关于MicroPython的代码保护

The supplied javaHome seems to be invalid

Windows 11 系统 Android Studio 从低版本升级到 Android Studio Electric Eel | 2022.1.1 Patch 1 结果构建报错:

原因为 Android Studio Electric Eel | 2022.1.1 Patch 1 安装目录下存在 jre 文件夹的残留,需要移除这个残留目录即可解决问题。

参考链接


The supplied javaHome seems to be invalid