20230106-竖排书籍常见名词

夹注

割注


https://zhuanlan.zhihu.com/p/183126390

书籍排版设计的相关术语

封面 又称 封一 前封面 封皮 书面

封面印有书名、作者、译者姓名和出版社的名称,封面起着美化书刊和保护书芯的作用

封里 又称 封二

是指 封面的背页,封里一般是空白的,但在中常用它来印 目录,或有关的图片

封底里 又称 封三

是指封底的里面一页,封底里 一般为空白页,但中 常用它来印正文或其他正文 以外的文字,图片,

封底 又称 封四、底封

图书在封底的右下方印统一书号和定价,在封底印版权页,或用来印目录及其他非正文部分的文字、图片

书脊 又称 封脊

书脊是指连接封面和封底的书脊部,书脊上一般印有书名、册次 作者、译者姓名和出版社名,以便于查找

书冠

书冠是指封面上方印书名文字的部分

书脊排版设计的相关术语

书脚

书脚是指封面下方印出版单位名称的部分

扉页 又称里封面或副封面

扉页是指在书籍封面或衬页之后,正文前的一页,扉页上一般印有书名、作者或译者姓名、出版社 和出版的年月等 扉页也起装饰作用,增加书籍的美观

插页

插页是指凡版面超过开本范围的、单独印刷插装在书刊内、印有图或表的单页、有时也指版面不超过开本、纸张与开本尺寸相同,但用不同于正文的纸张或颜色印刷的书页

篇章页 又称中扉页或隔页

篇章页是指在正文各篇 章起始前排的,印有篇 编 或章 名称的一面单页,篇章页只能利用单码 双码留空白,篇章页插在双页之后,一般作暗码计算或不急页码,篇章页有时用带色的纸印刷来显示区别

目录

目录是书刊中 章 节 标题的记录,起到主题索引的作用,便于读者查找,目录一般放在书刊正文之前

中因印张所限 常将目录放在封二 封三 或封四 上

版权页

版权页是指版本的记录页,版权页中,按有关规定记录有书名、作者或译者姓名、出版社、发行者、印刷者、版次、印次、印数、开本、印张、字数、出版年月、定价、书号等项目,图书版权页一般印在扉页背页的下端,版权页主要供读者了解图书的出版情况,常附于书刊的正文前后

书籍排版设计的相关术语

索引

索引分为主题索引、内容索引、名词索引、学名索引、人名索引等多种,索引属于正文以外部分的文字记载,一般用较小字号双栏排于正文之后,索引中标有页码以便于读者查找,在科技书中索引作用十分重要,它能使读者迅速找到需要查找的资料

版式

版式是指书刊正文部分的全部格式,包括正文和标题的字体、字号、版心大小、通栏、双栏、每页的行数、每行字数、行距及表格、图片的排版位置等

版心

版心是指每面书页上的文字部分,包括章、节标题、正文以及图表 公式等

版口

版口是指版心左右上下的极限,在某种意义上即指版心,严格来说,版心是以版面的面积来计算范围的,版口则以左右上下的周边来计算范围

超版口

超版口是指超过左右或上下版口极限的版面,当一个图或一个表的左右或上下超过了版口,则称为超版口图或超版口表

直(竖)排本

是指翻口在左,订口在右,文字从上至下,字行有右至左排印的版本,一般用于古书

横排本

就是翻口在右,订口在做,文字从左至右,字行由上至下排印的版本

刊头

刊头又称 题头,头花,用于表示文章或版别的性质,也是一种点缀性的装饰,刊头一般排在报刊 诗歌 散文的大标题的上边或左上角

破栏

破栏又称跨栏,报刊大多数是用分栏排的,这种在一栏之内排不下的图或表延伸到另一栏去而占多栏的排法称为破栏排

天头

天头是指每面书页的上端空白处

地脚

地脚是指没面书页的下端空白处

暗页码

又称暗码是指不排页码而又占页码的书页,一般用于超版心的插图、插表、空白页或隔页等

页与张的意义相同,一页即两面,书页正 反两个印面,应注意另页和另面的概念不同

另页起

另页起是指一篇文章从单码起排,如果第一篇文章以单页码结束,第二篇文章也要求另页起,就必须在上一篇文章的后留出一个双码的空白面,即放一个空码,每篇文章要求另页起的排法,多用于单印本印刷

另面起

另面起是指一篇文章可以从单 双码开始起排,但必须另起一面,不能与上篇文章接排

表注

表注是指表格的注解和说明,一般排在表的下方,也有的排在表框之内,表注的行长一般不要超过表的长度

图注

图注是指插图的注解和说明,一般排在图题下面,少数排在图题之上,图注的行长一般不应超过图的长度

背题

背题是指排在一面的末尾,并且其后无正文相随的标题,排印规范中禁止背题出现,当出现背题时应设法避免,解决的办法是在本页内加行,缩行或留下尾空而将标题移到下页

20230106-ConTeXt简介和中文排版效果

ConTeXt是什么

ConTeXt 是一种TeX 排版格式和宏包,TeX 及其衍生的排版格式 宏包通常用于排制 可能包含数学公式的高质量出版物,很多人使用纯TeX,但最流行的是latex 格式宏包,latex 有相当完善的中文支持

ConTeXt 继承了TeX的很多传统,兼容纯TeX 格式,但它的目标是排版高质量的通用文档

ConTeXt 目前通常使用LuaTeX (目前的后继者叫LuaMetaTeX 简称LMTX ) 作为引擎,ConTeXt 和LuaTeX 是同一个团队开发的,有活跃的社区

你可以在排版文档中使用ConTeXt TeX 和第三方宏包控提供的命令,以及自己定制的命令,来控制文档的排版效果,这样的排版文档也叫 排版脚本,你还可以在排版脚本中插入lua 代码,处理数据,干预引擎的行为

需要重复使用、分享的自制命令和lua 代码,可以制成模板和模块

下文会说到的,本人所做的ConTeXt 中文支持,即是模块的形式

你也可以在lua 脚本中通过luatex 接口使用ConTeXt 和tex 命令,实际上是在后台生成包含ConTeXt 和tex 命令的排版脚本,完成排版,这叫ConTeXt lua 文档 CLD 。这就是说,你既可以使用熟悉的tex 系命令和资源,还可以使用灵活的lua 语言,实现自动排版

最后,你几乎可以完全抛开 ConTeXt 和tex 命令,而在lua 端直接使用luatex ,比如生成引擎需要的结点列表数据等,完成排版。

ConTeXt 适合用来做什么

就排版内容来说,ConTeXt +LMTX 特别适合

排制结构化文档,如产品目录,数据表 图表,辞书,试卷 练习题 ,格式规范的图书,卡片

自动化排版,比如自动替换内容,随时根据内容变动更新排版,构建自动排版 网站后台排版流水线

精细排版,比如根据实时数据控制特定字符的格式

多语言排版

所谓结构化文档,格式规范的图书,跟复杂程度无关,而重点在于文档结构对应的排版格式,是否都可以转述为数量有限,可重复使用的排版命令,就是说,重复利用率越高越有价值,即越接近自动化排版

ConTeXt 难学吗

ConTeXt 用户

需要学习ConTeXt格式、命令,可以通过官网学习,教程可以看not-so-short-introduction-to-context(本人有汉译计划)。对技术有一些好爱的图书编辑可以做到

如果要精细排版,可能要学一些tex 知识

如果要实现自动化排版,通过lua 控制排版引擎,则需要学习lua cld 以及luatex luametatex

中文支持怎么样

我做了三个支持ConTeXt+LMTX中文排版的模块(链接为GitHub库):

  • 中文标点支持模块zhpunc,支持全角、半角、开明等常见标点样式,行端标点凸排/悬挂,以及竖排时可能用到的行间标点。此模块最初基于liyanrui/zhfonts,谨致谢忱!
  • 竖排模块vertical-typesetting
  • 双行夹注模块jiazhu

大体而言,目前已经实现中文排版的常见功能,包括竖排,可以尝试用于生产性的中文排版,如有问题和新需求,本人愿意支持,请注意,以上并非保证

已知问题,

较短的双行夹住有时过于稀疏

官方支持字符间断行和拉伸的脚本 hanzi 有个别错误,可以提供修正后的版本

20221226-优雅的API接口

设计api 接口时,需要注意的一些地方,希望对你会有所帮助

如何设计一个优雅的api接口,能够满足 安全性,可重复调用性,稳定性,好定位问题等多方面问题

1. 签名

为了防止api 接口中的数据被篡改,很多时候我们需要对api 接口做 签名

接口请求方将 请求参数+时间戳+密钥 拼接成一个字符串,然后通过md5 等hash 算法,生成一个签名sign

然后在请求参数或者请求头中,增加sign 参数,传递给api 接口

API 接口的网关服务,获取到该sign 值,然后用相同的请求参数+时间戳+密钥拼接成一个字符串,用相同的md5算法生成另外一个sign,对比两个sign 值是否相等

如果两个sign 相等,则认为是有效请求,api 接口的网关服务会将给请求转发给相应的业务系统

如果两个sign 不相等,则spi 接口的网关服务会直接返回签名错误

签名中为什么要加时间戳

为了安全性考虑,防止同一次请求被反复利用,增加了密钥没被破解的可能性,我们必须要对每次请求都设置一个合理的过期时间,比如15分钟

这样一次请求,在15分钟之内是有效的,超过15分钟,api 接口的网关服务会返回超过有效期的异常提示

目前生成签名中的密钥有两种形式

一种是双方约定一个固定值 privateKey

另一种是api 接口提供方给出AK/SK 两个值,双方约定用sk 作为签名中的密钥,AK接口调用方作为header 中的accessKey 传递给api 接口提供方,这样api 接口提供方可以根据AK 获取到SK,而生成新的sign

2. 加密

有些时候,我们的api 接口直接传递的非常重要的数据,比如 用户的银行卡号,用户身份证等,如果将这些参数,直接明文,暴露到公网上是非常危险的事情

目前使用比较多的是用BASE64 加密解密

我们可以将所有的数据,按照一定的规律拼接成一个大的字符串,然后在加一个密钥,拼接到一起

然后使用JDK1.8 之后的Base64 工具类处理,效果如下

【加密前的数据】www.baidu.com
【加密后的数据】d3d3LmJhaWR1LmNvbQ==

为了安全性,使用Base64 可以加密多次

API 接口的调用方在传递参数时,body 中只有一个参数data 它就是base64 之后的加密数据

API 接口的网关服务,在接收到data 数据后,根据双方事先预定的密钥、加密算法、加密次数等,进行解密,并且反序列化出参数数据

3. ip 白名单

为了进一步加强api 接口的安全性,防止接口的签名或者加密被破解了,攻击者可以在自己的服务器上请求该接口

需求限制请求ip 增加ip 白名单

只有在白名单中的ip 地址,才能成功请求api 接口,否则直接返回无访问权限

ip 白名单也可以加载api 网关服务上

但也要防止公司的内部应用服务器被攻破,这种情况也可以从内部服务器上发起api 接口的请求

这时候就需要增加web 防火墙了,比如 modsecurity 等

4. 限流

如果你的api 接口被第三方平台调用了,这就意味着,调用频率是没法控制的

第三方平台调用你的api 接口时,如果并发量一下子太高,可能会导致你的api 服务不可用,接口直接挂掉

由此,必须要对api 接口做限流

限流方法有三种

  1. 对请求ip 做限流,比如同一个ip ,在一分钟内,对 api 接口总的请求次数,不能超过10000次

对请求接口做限流 比如同一个ip 在一分钟内,对指定的api 接口,请求次数少不能超过2000次

对请求用户做限流,比如同一个AK/SK 用户,在一分钟内,对api 接口总的请求次数,不能超过10000次

我们在实际工作中,可以通过nginx redis 或者gateway实现限流的功能

5. 参数校验

我们需要对api 接口做参数校验,比如:校验必填字段是否为空,校验字段类型,校验字段长度,校验枚举值等等

这样做可以拦截一些无效的请求

比如在新增数据时,字段长度超过了数据字段的最大长度,数据库会直接报错

但这种异常的请求,我们完全可以在api 接口的前期进行识别,没有必要走到数据库保存数据那一步,浪费系统资源

有些金额字段,本来是正数,但如果用户传入了负数,万一接口没做校验,可能会导致一些没必要的损失

还有些状态字段,如果不做校验,用户如果传入了系统中不存在的枚举值,就会导致保存的数据异常

由此可见,做参数校验是非常有必要的

在java 中校验数据使用最多的是hiberate 的validator 框架,它里面包含了null notempty size max min 等注解

用它们校验数据非常方便

当然有些日期字段和枚举字段,可能需要通过自定义注解的方式实现参数校验

6. 统一返回值

我之前调用过别人的api 接口,正常返回数据是一种json 格式,比如

1
2
3
4
5
{
"code":0,
"message":null,
"data":[{"id":123,"name":"abc"}]
},

签名错误返回的json 格式

1
2
3
4
5
{
"code":1001,
"message":"签名错误",
"data":null
}

没有数据权限返回的json 格式

1
2
3
4
5
{
"rt":10,
"errorMgt":"没有权限",
"result":null
}

这是比较坑的做法,返回值中有多种不同格式的返回数据,这样会导致对接方很难理解

出现这种情况,可能是api 网关定义了一直返回值接口,业务系统定义了另外一种返回值结构,如果是网关异常,则返回网关定义的返回值结构,如果是业务系统异常,则返回业务系统的返回值结构

但这样会导致api 接口出现不同的异常,返回不同的返回值结构,非常不利于接口的维护

其实这个问题我们可以在设计 api 网关时解决

业务系统在出现异常时,抛出

20221226-七律·送瘟神

七律二首·送瘟神
朝代:现代
作者:毛泽东
其一
绿水青山枉自多,华佗无奈小虫何!
千村薜荔人遗矢,万户萧疏鬼唱歌。
坐地日行八万里,巡天遥看一千河。
牛郎欲问瘟神事,一样悲欢逐逝波。
其二
春风杨柳万千条,六亿神州尽舜尧。
红雨随心翻作浪,青山着意化为桥。
天连五岭银锄落,地动三河铁臂摇。
借问瘟君欲何往,纸船明烛照天烧

20221225-docx格式文档详解:xml解析并用html还原

https://juejin.cn/post/7166821284087595038

一、应用场景,有什么好处

解析就是解剖并分析,解析word ,就是提取word 里面的结构和内容

一套试卷有几十道题,一道题又有十来个属性
可以通过技术手段,自己去读出word 的内容

理论上,word 里展示的所有内容,程序员都能拿到,拿到数据之后,家境差点的公司,通过代码逻辑去找试卷名、选项这类属性,家境好点的企业,通过人工智能的NLP 文本分类,可以更好地实现智能分类

而此时,录入员只负责编辑word 就可以了,这个过程就叫做 word 导入

能导入的前提,是可以解析出来word 的内容,能解析word 的前提,就是docx 格式

docx 格式:为什么出现

原来的doc 格式是加密的,只有微软自己家的软件才能打开

后来微软觉得,这样并没有让自己很神圣,反而限制了自己的发展

文件结构:怎么来解析

分析发现,在docx 中同一张图复制多次,media 里面只保留一张原图,这说明,它是个勤俭节约的好孩子,承载同样多的内容,docx 格式比doc 的体积要小

比较关键的几点

3.1 主文件document.xml

位于word 下的document.xml 文件,是docx 的主战场,可以说,文档中你能看到的所有内容,在这里都有直接或间接的记录

document.xml 是一个xml 格式的文档

1
2
3
4
5
6
7
8
9
10
<w:document>
<w:body>
<w:p>...</w:p>
<w:p>...</w:p>
<w:tbl>...</w:tbl>
<w:p>...</w:p>
...
<w:sectPr>...</w:sectPr>
</w:body>
</w:document>

我们看到,body 体力,只有3种标签,分别是<w:p> <w:tbl> 和 <w:sectPr>

一个docx 文档,基本由这三种成分组成,w 指的是word p 指的是paragraph段落,tbl 表示table 表格,sectPr 全称是section primp,这个容易扰乱思路

3.2 段落标签w:p

在docx 中,段落是最常见的,是文档中最主要的组成单元

和你理解的段落一样,不换行就属于一个段落,即便是 咔咔咔 敲上6个回车,虽然没有内容,那它也属于6个段落,在xml 中是6个 <w:p>。

另外,包含图片,流程图,公式等元素的内容,也是包含在段落中的,换句话说,它们都是小弟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 导入解析xml的库
import xml.dom.minidom as xdom
# 加载文档
xp = xdom.parse('word/document.xml')
# 获取文档根节点
root=xp.documentElement
# 获取body节点们
bodys = root.getElementsByTagName("w:body")
# 因为getElements返回多个对象,我们只有一个
body = bodys[0]
# 循环遍历body下的节点
for i,ele in enumerate(body.childNodes):
e_name = ele.nodeName
# 打印{序号} -> {节点名称} is {对象}
print(i,"->",e_name,"is",ele)

下面该详细说一下w:p 的小弟们了

3.3 文本标签 w:t

在纷杂的xml 文件中,可以扒拉出来一个叫 w:t 标签

1
2
3
4
5
6
7
<w:p>
<w:r>
<w:t>word的doc格式原来是不开源的,后来改成了docx格式后,是开源的。</w:t>
……
</w:r>
……
</w:p>

这里面存储的内容,就是word 里面的文字,t 就是text 的简称

你在docx 里面看到的每一个字,基本上都是被 w:t w:r 所包裹的

也就是说,如果我们拿出所有w:t 标签内的文本,我们就做到了纯文本docx 解析

代码,其实很简单,就是在w:p 元素中,扫描 w:t 的标签并取出其内容

上面我们已经拿到了body 标签,所以从那里继续

1
2
3
4
5
6
7
8
# 循环body下的大单元 w:p段落,w:tbl表格
for i,ele in enumerate(body.childNodes):
# 找到包含w:t的标签,可能是多个
wts = ele.getElementsByTagName("w:t")
ele_text = "" # 记录大单元内所有文本
for wt in wts: # 循环
ele_text = ele_text + wt.text
print(ele_text) # 打印输出

提取一个docx的文本,就是那么简单,你现在可以写一个程序,可以做到把docx 转为txt

但是,有一点我要告诉你,运行代码里的wt.text 可能会报错,为了便于你理解,我特意写了伪代码,实际上,要从 w:t 中取出文本内容,可以像下面这样

1
2
3
4
5
import re # 导入正则库
# 构建一个正则,去除<>标签
pattern_del_tag = re.compile(r'<[^>]+>',re.S)
# 把<w:t>元素转为xml格式<w:t>xxx</w:t>,然后去标签
t_text = pattern_del_tag.sub('', wt.toxml())

我认为这么讲,你反而能理解,因为,不用在理解什么叫 w:t 的时候,还要分散注意力到正则表达式

3.4 连续块w:r

上面我们讲了如何去解析文字,但是,那太简单了

文字是有样式的

都在同一段 w:p 内的文字,它们的样式,可能不一样

比如前两个字是红色,那么这两个字样式一样,但是,后两个字是绿色,和前面又不一样

为了解决这个问题,docx 把具有相同样式的文字,用w:r 标签包裹

r 代表run ,关于这个run 的解释,很多国内文档都直接翻译为运行

其实,run 在英文中有很多解释,我觉得在这里更适合它的释义应该是 一段 一系列 连续上演 因此,我个人给这个标签起名叫 连续块,表示在这个标签之内的文本,是一个系列的,他们的特点是连续不间断的

代码依然是处理xml 文件的那一套,不是找标签就是拿属性

还有其他的样式标签,你可以自己研究,我这里先抛砖引玉,举两个例子

比如上面例子中的字体颜色,一般在w:rPr 标签内,w 依然表示word r 表示run Pr 表示 Primp 是修饰,装饰的意思,w:rPr 这个标签的释义就是 连续块的样式说明,类似的还有w:pPr 表示对段落paragraph 的样式说明,w:tcPr 表示对表格单元格 table cell 的样式说明

我们来看以下,连续块修饰 w:rPr 是如何定义的

比如对于粗体、斜体的说明

用代码进行判断,主要是tag 的读取,能找到tag,就说明有此种样式的标记

1
2
3
4
5
6
w_i = w_rPr.getElementsByTagName("w:i")
if w_i:
print("是斜体")
w_b = w_rPr.getElementsByTagName("w:b")
if w_i:
print("是粗体")

再比如对于各种线条的说明

上面的例子,如果用代码进行判断的话,除了对tag 存在的判断,还需要获取属性值 w:val 表示用了哪一类具体的样式

1
2
3
4
5
6
7
8
9
10
11
12
w_u = w_rPr.getElementsByTagName("w:u")
if w_u:
# 获取属性值用 getAttribute
line_value = w_u[0].getAttribute("w:val")
if line_value == "single":
print("是下划线")
if line_value == "double":
print("是双划线")
if line_value == "wave":
print("是波浪形线")
if line_value == "dotted":
print("是虚线")

我可以很负责地说,只要是文档中呈现的信息,在xml 文件中都可以找到对应的标注

我们可以看到,包括 字号,字体,字色,标线都可以复原

3.5 图像标签w:drawing

docx 中的图片是如何从xml 中提取出来的呢

你在连续块 w:r 中会发现,有一个w:drawing 标签,这里面主要存放的,就是图画相关的信息

图片仅仅是 w:drawing 中的一个小分类,除了图片,还有图表、形状、流程图等

今天咱们说个最简单的,那就是如何提取图片

图片的标签是pic:pic ,他在xml 中如下定义

1
2
3
4
5
6
7
<w:drawing>
<pic:pic>
<pic:blipFill>
<a:blip r:embed="rId9"/>
</pic:blipFill>
</pic:pic>
</w:drawing>

其中图片就藏在<a:blip r:embed="rId9"/>中,里面的rId9 就是捕获图片的线索

那个media 文件夹,里面有好多图片

是有图片,但这也不是rId9

有个文件专门做关联这件事情,他就是解压缩之后的word/_rels/document.xml.rels文件。

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<Relationships>
……
<Relationship Target="media/image1.png" Id="rId9"/>
<Relationship Target="media/image3.png" Id="rId11"/>
<Relationship Target="media/image2.GIF" Id="rId10"/>
</Relationships>

这里有档案,记录了哪个id 指向哪个文件,于是,我们解析这个文件,就可以拿到对应关系

然后,遇到pic 和id 等于rId9 的,就把media/image1.png 这个图片文件展示出来

这,就实现了图片的解析

3.6 表格标签w:tbl

表格标签w:tbl 的地位很重,它和段落标签 w:p 平级

分析整个文档的顶层组成元素,我们不难发现,除了 w:tbl 就是 w:p

一开始,我不理解,为什么图表、流程图那么复杂的元素,却不配得到表格那么高的地位

单纯表格的结构,其实不复杂,但是,表格里的每一个单元格,却可以容纳另一个word 文档,表格里面,图片,图表、文本样式,甚至表格里再来一个表格,什么都可以添加,它甚至是包含了w:p 大佬,w:tbl 和w:p 并列,它反而是委屈的

我们来看一下表格w:tbl 的基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
<w:tbl>
<w:tblGrid>
<w:gridCol/>
<w:gridCol/>
</w:tblGrid>
<w:tr>
<w:tc><w:p>...</w:p></w:tc>
<w:tc>...</w:tc>
</w:tr>
<w:tr>
...
</w:tr>
</w:tbl>

节点元素中,主要有两部分内容,一个 w:tblGrid 介绍表格列的个数,另一个是w:tr 包含表格行的信息,tr 是table row 的缩写

其中,w:tr 里面有 w:tc,这里面是格子的内容,我们发现其内容,居然是一个它的兄弟节点 w:p

tc 是table cell 的缩写,表示单元格的意思
从结构上看,我们会感觉 table cell 更适合语境

先说基本表格的解析,如下图所示

解析的代码参考如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
w_table = body.childNodes[0] # 拿到表格节点
# 获取所有的行
w_trs = w_table.getElementsByTagName("w:tr")
rows_text = [] # 存放行的文本
for r_index, tr in enumerate(w_trs):
# 获取所有的单元格
cells = tr.getElementsByTagName("w:tc")
cells_text = [] # 存放单元格的文本
for c_index, cell in enumerate(cells):
# 获取所有的文本
wts = cell.getElementsByTagName("w:t")
for wt in wts: # 把文本拼接
cells_text.append(wt.text)
rows_text.append(cells_text)
print(rows_text) # 打印结果,二维数组[[r1c1,r1c2],[r2c1,r2c2]]

运行一下代码,结果如下

这里面我又挖坑了,除了前面讲 w:t 时的 wt.text 陷阱之外,w:tc 的内容应该是去解析 完整的w:p 结构,而这里我只取了w:t 文本,这样最简单,因为,我们是要理解表格的结构,因此,其他的可以假装看不见

但是,也由此可见,做好表格解析的前提,是做好段落解析,因为表格单元格里是段落

我相信,有了表格的解析结果 二维数组,你很容易就可以把它还原成表格页面用于展示,只需要循环就好,第一层循环,第二层循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
rows_text = [['名称', '后缀名'], ['Word', 'docx']]
table_html = ["<table>"]
for row in rows_text:
table_html.append("<tr>")
for cell in row:
table_html.append("<td>"+cell+"</td>")
table_html.append("</tr>")
table_html.append("</table>")
table_html = "".join(table_html)
print(table_html)
# <table>
# <tr><td>名称</td><td>后缀名</td></tr>
# <tr><td>Word</td><td>docx</td></tr>
# </table>

据我所知,世界上的表格除了上面那种简单的,还有一些稍微复杂的,那就是带有合并单元格的表格

比如下面这种

这类表格的解析稍微复杂一些,它们属于复杂里面最简单的

我们来看看他们的xml 数据是如何定义的

首先来看带有跨行的表格的例子

对于跨行的情况,我们发现表格的xml 数据,该有的行和列,数量都没有变,只是在要合并的单元格上标记了一个w:vMerge 标签

这个标签表示有跨行的单元格,v 表示vertical ,是竖直方向的意思,vMerge 表示竖直合并,这个标签里面还有属性值 w:val 当值为restart 时表示此单元格开始出现合并,continue 表示此单元格没有结束,继续保持,直到遇到非continue 情况

再来看看跨列的情况

跨列因为发生在行内,是行内矛盾,不影响其他行,所以,我们看到只有在第一行的第一格中,采用 w:gridSpan 标签,说明本行有跨列的单元格,val 值是2,表示跨2 个单位

为什么我前面说,tc 是table cell 的缩写,我的依据就在这里,其实这个表格的结构是2行2列,如果c 指的是column 的话,它应该有2个 w:tc 后一个复用前一个,但是,我们看上图里的结构,它只有一个w:tc ,那我们称呼它叫单元格更贴切,因为它只有一个框,你可以反驳我,

带有合并单元格的页面还原,逻辑稍微复杂,但是底层还是和普通表格一样,通过循环行和列,你只需要遇到合并的时候,搞一个colspan=2 或者 rowspan =3 就行

搞合并单元格时,花费了2天时间才完成,

对于复杂表格,最终的数据结构用一维数组更恰当。这个结构可以像这样
[{"x_start":0, "x_end":1, "y_start":0, "y_end":0, "content":"不要问我"}]


前端实现docx pdf 格式文件在线预览

在业务中,如果遇到文档管理类的功能,会出现需要在线预览的业务需求,
本文主要是通过第三方库来实现文档预览功能,并将其封装成preview 组件

docx 的实现需要使用 docx-preview 插件

PDF 的预览需要使用PDFJS 这个插件,通过将文件流解析写到canvas 上实现预览效果

此处pdf的渲染数据this.fileData必须是一个ArrayBuffer格式的数据,如果请求的的数据是Blob格式必须要先使用Blob.arrayBuffer()转换

PDF 的放大和缩小

PDF 文件渲染后如果不能调整大小会因为源文件的大小和文件内容,出现模糊的问题,所以进行缩放渲染是有必要的

多格式的文件渲染函数映射

因为将多种文件渲染放在一个文件中,所以处理函数需要做映射处理,执行对应格式的文件渲染

不支持的文件提示处理

在这个文件中,目前只支持docx 和pdf 的预览,如果出现了不支持的文件,需要增加一个提示处理,告知用户,例如如下的文件提示

20221225-什么是差分信号

差分传输是一种信号传输的技术,区别于传统的一根信号线一根地线的做法,差分传输在这两根线上都传输信号,这两个信号的振幅相等,相位相差180度,极性相反,在这两根线上传输的信号就是差分信号

差分信号与单端信号的区别

单端信号指的是用一个线传输的信号,一根线没参考点怎么会有信号呢?参考点就是地线,也就是说,单端信号是在一根导线上传输的与地之间的电平差,那么当你把信号从A 点传递到B 点的时候,有一个前提就是A 点和B 点的地电势应该差不多是一样的,差分信号指的是用两根信号线传输的信号,传输的是两根信号之间的电平差,当你把信号从A 点传递到B点的时候,A 点和B 点的地电势可以一样也可以不一样,但是A 点和B 点的地电势差有一个范围,超过这个范围就会出问题了,一个差分信号是用一个数值来表示两个物理量之间的差异,从严格意义上来讲,所有电压信号都是差分的,因为一个电压只能是相对于另一个电压而言的,在某些系统里,系统地被用作电压基准点,当地当作电压测量基准时,这种信号规划被称之为单端的,我们使用该术语是因为信号是用单个导体上的电压来表示的

另一方面,一个差分信号作用在两个导体上,信号值是两个导体间的电压差,尽管不是非常必要,这两个电压的平均值还是会经常保持一致,我们用一个方法对差分信号做一下比喻,差分信号就好比是跷跷板上的两个人,当一个人被跷上去的时候,另一个人被跷下来了 - 但是他们的平均位置是不变的。继续跷跷板的类推,正值可以表示左边的人比右边的人高,而负值表示右边的人比左边的人高。0 表示两个人都是同一水平。这两个跷跷板用一对标识为V+和V-的导线来表示。当V+>V-时,信号定义成正极信号,当V+<V-时,信号定义成负极信号。

差分信号的优点

优点一,相对于单端信号,差分信号减小了潜在的电磁干扰 EMI ,使用差分方式传输,信号的电压峰峰值会被放大了一倍,但是单根线上的电流却保持不变,如果采用传统的单线传输方式,在驱动相同的信号时,更容易造成EMI 问题

优点二、差分信号的值很大程度上与地的精确值无关,能很好的抵抗电源的干扰,在一个地做基准,单端信号方案的系统里,测量信号的精确值依赖系统内地的一致性,信号源和信号接收器距离越远,他们局部地电压值之间有差异的可能性就越大,从差分信号恢复的信号值在很大程度上与地的精确值无关,而在某一范围内,假如两条信号都收到同样的 (同向、等幅度) 的干扰信号,由于接收端是对接收的两条线信号进行减法处理,因此干扰信号会被基本抵消,也就是说,一个差分放大器的输入有效信号幅度只需要几毫伏,但是它却能够对一个高达几伏特的共模信号无动于衷

差分信号在做pcb 设计时的处理方法

一般我们在做pcb 设计时,习惯的硬件命名上,会在差分信号的信号名尾部加 + 和 - 或者 P 和N 作为标识,大家可以通过命名来识别差分信号,常规的差分信号处理方法是

差分信号走线要耦合处理,就是2根信号线在PCB 设计时是紧挨着的,不允许分开走线

一对差分信号的2根信号线之间需要做等长处理,等长范围为5mil 等长不需要做到更小,有仿真验证,等长范围做到5mil 以下并不能对信号质量有很大提升,等长处理的位置选择在产生长度误差的地方,等长需要做小波浪处理

20221224-常用坐标系及投影:WGS84-GCJ02-CGCS2000-BD09-Pseudo-Mercator-UTM-BD09MC

简介

先分类

WGS84 GCJ02 CGCS2000 BD09 是地心坐标系,坐标表现形式

Pseudo-Mercator UTM BD09MC 是投影坐标系,坐标表现形式为x y

WGS84 CGCS2000 是原始坐标系,GCJ02 BD09 是加密坐标系

目前,谷歌、OSM 等地图使用的是 WGS84 坐标系和Pseudo-Mercator 投影坐标系,高德、腾讯等地图使用的是GCJ02 坐标系和Pseudo-Mercator 投影坐标系;

天地图使用的CGCS2000坐标系和Pseudo-Mercator 投影坐标系

百度地图使用的是BD09坐标系和BD09MC 投影坐标系

UTM 投影坐标系经常应用在无人驾驶及高精地图上面

国内android系统手机采集的AGPS 数据是GCJ02 坐标系的

RTK 和一些PDA 设备采集的GPS 数据是WGS84 坐标系的

ios系统手机采集的AGPS数据是WGS84 坐标系的,GPS定位芯片获取的定位数据是WGS84 坐标系的,北斗芯片获取的定位数据是CGCS2000 坐标系的

二、分项介绍

WGS84 坐标系

全称 world geodetic system-1984 既 1984 年的全球坐标系统

美国GPS 系统使用的是WGS84 坐标系,受益于GPS 系统的发展,现在全球用的最多的坐标系就是WGS84 坐标系,它的EPSG 编码是4326

EPSG 是大地基准面,空间参考系统,地球椭球体、坐标转换 和相关度量单位的公共注册中心,它为每个坐标系都分配有一个编码

WGS84 坐标系的坐标原点为地球质心,地心空间直角坐标系的Z轴指向 BIH (国际时间服务机构) 1984.0 定义的协议地球极 CTP 方向,X轴指向BIH 1984.0 的零子午面和CTP 赤道的交点,Y轴与Z 轴,X轴垂直构成右手坐标系

它的地球椭球基本参数如下

赤道半径:a=6378137±2(m)

扁率:f=0.003352810664=1/298.257223565

(假设,赤道半径(长半轴)为a,极半径(短半轴)为b,扁率f=(a-b)/a。)

还有几个参数为 地球引力和地球质量的乘积、正常化二阶带谐系数、地球重力场二阶带球谐系数

地球自转角速度,这几个跟大地测量和地球物理相关,很深奥,我们只要了解赤道半径和扁率就行了

地球引力和地球质量的乘积 GM=3986005*108^3s^{-2}\pm 0.6 * 108 m^3s^{-2}

正常化二阶带谐系数 C20=-484.16685*10^{-6}\pm 1.3 * 10 ^{-9}

地球重力场二阶带球谐系数 J2=108263*10^{-8}

地球自转角速度 \omega = 7292115*10^{-11}rads ^{-1} \pm 0.150*10^{-11} rads^{-1}
WGS84 坐标系的OGC WKT 描述为

1
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]

参见:https://epsg.io/4326,

这个网站上可以查阅常用坐标系的各种表现形式,对常用文件格式、软件、数据库、框架都做了兼容

WGS84 坐标系的EPSG 编码为4326,赤道半径为6378137,扁率为1/298.257223565,是目前应用最为广泛的坐标系统,只要跟GPS 定位相关,使用的都是WGS84 坐标系,谷歌、OSM 也用的WGS84坐标系,很多软件 QGIS ARCGIS 、前端脚本库 leaflet mapbox openlayer
在没有特别声明的时候,默认数据使用的是WGS84 坐标

CGCS2000 坐标系

China Geodetic Coordinate System 2000,2000 国家大地坐标系,是我国当前最新的国家大地坐标系,它的EPSG 编码为 4490

2000 国家大地坐标系的原点为包括海洋和大气的整个地球的质量中心,2000 国家大地坐标系 的Z 轴由原点指向历元2000.0 的地球参考极的方向,该历元的指向由国际时间局给定的历元为1984.0 的初始指向推算,定向的时间演化保证相对于地壳不产生残余的全球旋转,X 轴由原点指向格林尼治参考子午线与地球赤道面 历元 2000.0 的交点,Y轴与Z轴 X轴构成右手正交坐标系,采用广义相对论意义下的尺度

相较于WGS84 CGCS2000 坐标系的区别主要在于,它采用的是2000年的地球物理和大地测量的结果平差计算而设定的,坐标系Z轴 指向历元2000 的地球参考极方向,这些差异对高精数据有影响,但对于精度在10m 以上的数据来说,这些差异可以忽略不计

既非高精度的大多数情况下,我们可以认为WGS84 坐标系=CGCS2000坐标系

很多软件和框架还没有兼容CGCS2000坐标系,我们在使用CGCS2000坐标系的数据的时候,可以设置为WGS84坐标系,这样也便于传输和查阅

它的地球椭球基本参数如下
赤道半径 a=6378137m

扁率 f=1/298.257222101

地心引力常数 GM = 3.986004418*1014m^3s^{-2}

自转角速度 \omega=7.292115*10^{-5}rad s^{-1}

短半轴 b= 6356752.31414 m

极曲率半径 = 6399593.62586 m

第一偏心率 e=0.0818191910428

CGCS2000坐标系的OGC WKT 描述为

1
GEOGCS["China Geodetic Coordinate System 2000",DATUM["China_2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","1043"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]

参见:

https://epsg.io/4490

小结:

大多数情况下,我们可以认为CGCS2000 坐标系=WGS84 坐标系,很多软件和框架都还没有兼容CGCS2000 坐标系,我们在使用CGCS2000 坐标系的数据的时候,可以设置为WGS84 坐标系,这样也便于传输和查阅

GCJ02 坐标系

为了数据安全和保密,通过地形图非线性保密处理算法,俗称火星加密,加密过的WGS84 坐标系,俗称国测局坐标系,或火星坐标系

GCJ02 坐标系与WGS84 坐标系之间的偏差大概在50-700m左右

目前国内大部分地图底图和矢量数据(除了LBS 服务的坐标数据,还包括android 手机的定位数据)都使用GCJ02 坐标系,为了使GCJ02 坐标系的底图与数据和WGS84 坐标系的底图与数据适配,通常会使用坐标系纠偏算法,将坐标系统一

各种形式的纠偏算法 javascript java python 等,都可以在网上搜索到,数据处理和webgis 开发,坐标系纠偏与数据融合统一是很重要的环节

通过对原始数据和加偏后的数据进行分析,猜测加偏的算法大概是,使用克拉索夫斯基椭球的参数,将原始坐标对应的经线和纬线上的偏差转为弧度后,与原始坐标相加,形成加偏坐标

这个算法非常优秀,它既能保证GCJ02 坐标系,相对于WGS84 坐标系的线性单调性,又能保证GCJ02 坐标系在伪距墨卡托投影下,相对于WGS84 坐标系在伪距墨卡托投影下的线性单调性,既能保证数据在加偏后,仍能维持实际的空间相对位置,又能保证数据可以无损的纠偏回去

小结

GCJ02 坐标系是一种加密坐标系,目前国内大部分地图底图 和矢量数据 都使用的是GCJ02 坐标系,GCJ02 的加密算法非常精妙,地图底图和矢量数据在使用之前,需要将坐标系进行统一

BD09 坐标系

BD09 坐标系是百度地图使用的地心坐标系,2009年,百度地图在GCJ02的基础上,做了二次加密,形成了BD09 坐标系

BD09 坐标系大概是先将GCJ02 坐标转为极坐标后,添加一个常量叫做偏移值,再将偏移后的极坐标转回到直角坐标

这种加偏算法,仅能保证相对于GCJ02 坐标系的线性单调性,无法保证投影后的线性单调性,所以百度地图的墨卡托投影需要分区域进行

百度地图提供WGS84、GCJ02坐标系向BD09坐标系的转换API:https://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition;在前端,百度地图也支持声明数据坐标系,以自动适配百度地图底图:https://lbsyun.baidu.com/index.php?title=jspopularGL/guide/coorinfo

除了百度自己的API外,网上也能搜索到BD09、GCJ02、WGS84坐标系之间的转换方法:https://blog.csdn.net/sinat_413

因为在GCJ02坐标系的基础上,又做了一次加密,所以百度地图与其他地图的数据兼容性变得很不好,但作为国内硕果仅存的还在做街景的商业地图平台,加之其与echart 开源 javascript 库 的良好结合,我们很多时候,还需要使用百度地图,这时候,虽然麻烦,但还是需要对它的底图和数据进行坐标系统一

小结

BD09 坐标系是在GCJ02 坐标系基础上二次加密而成,仅有百度地图在用,但百度地图有街景、有三维、有echart,很多情况下,我们需要使用百度地图的底图和数据,这时候,就需要对坐标系进行统一了,百度地图webapi 和js api 都支持坐标系的转换

墨卡托投影法

它是所有网络地图投影的基础

墨卡托投影法,又称麦卡托投影法,正轴等角圆柱投影,是一种等角的圆柱形地图投影法

本投影法得名于法兰德斯出身的地理学家杰拉杜斯·墨卡托,他于1569年发表长202公分、宽124公分以此方式绘制的世界地图。在以此投影法绘制的地图上,经纬线于任何位置皆垂直相交,使世界地图可以绘制在一个长方形上。由于可显示任两点间的正确方位,航海用途的海图、航路图大都以此方式绘制。在该投影中线型比例尺在图中任意一点周围都保持不变,从而可以保持大陆轮廓投影后的角度和形状不变(即等角);但墨卡托投影会使面积产生变形,极点的比例甚至达到了无穷大。

墨卡托投影法公式:

img

其中x和y是平面笛卡尔坐标,λ是经度,φ是纬度,λ0是地图的中央经线。

逆推公式为:

img

在制作小比例尺地图的时候,近似认为地球是正球体,将上述中的x 和y 乘以地球半径,即可形成对应地点的墨卡托投影相对坐标,在制作大比例尺地图的时候,要考虑到地球扁率

小结

墨卡托投影 法是一种等角圆柱形地图投影,它的投影公式计算简单,可以将地球投影到一张长方形图上,它是web-mercator 投影的基础

Pseudo-Mercator 投影

是墨卡托投影的一种变体,是WGS84 坐标系的伪距墨卡托投影,是网络地图应用的标准投影,自从2005年,谷歌地图使用web-mercator 投影发布自己的瓦片地图其,后续的图商 OSM 高的 腾讯 百度 都沿袭了这种投影法发布自己的地图,它的EPSG 编码为3857

墨卡托投影在大比例下会考虑地球扁率,但web-mercator 在所有比例尺下都使用球面公式,会导致局部地区的地图偏离同一比例尺下的椭球面墨卡托地图,离赤道越远,偏差就越明显,在地面上可以达到40km

因为很多人不知道web-mercator 和墨卡托投影有这样的差别,导致两者经常被乱用,为了避免投影乱用,致使数据混淆,很多官方机构规定正规途径禁用 web-mercator 投影

通常情况,web mercator 投影仅在网络地图上使用

web-mercator 投影公式与标准球面墨卡托的公式基本相同,但将世界坐标调整为左上角 为00 右下角为256 256 的正方形,假设地图投影在一个256 256 像素的图幅上

img

其中x 和y 是像素坐标,\lambda 是精度 \varphi 是维度,pixel 是像素,zoom level 是地图瓦片比例尺层级

web-mercator 投影的数据覆盖范围 在经度 -180 180 纬度 -85 85 之间
这有两个好处,其一是避免将极点投影到无穷远处,其二是能将整个投影地图变成正方形,虽然他会把部分南北极地区截掉,但毕竟,除了极为特殊的情况外,企鹅和北极熊不看网络地图

web-mercator投影的缺点是变形失真比较严重,不适用于大比例尺,高精度数据的显示,但优点也很明显,投影公式计算简单,投影结果是正方形,切图方便,坐标结果是各层级的像素坐标

Web-Mercator投影坐标系的OGC WKT描述为:

PROJCS[“WGS 84 / Pseudo-Mercator”,GEOGCS[“WGS 84”,DATUM[“WGS_1984”,SPHEROID[“WGS 84”,6378137,298.257223563,AUTHORITY[“EPSG”,”7030”]],AUTHORITY[“EPSG”,”6326”]],PRIMEM[“Greenwich”,0,AUTHORITY[“EPSG”,”8901”]],UNIT[“degree”,0.0174532925199433,AUTHORITY[“EPSG”,”9122”]],AUTHORITY[“EPSG”,”4326”]],PROJECTION[“Mercator_1SP”],PARAMETER[“central_meridian”,0],PARAMETER[“scale_factor”,1],PARAMETER[“false_easting”,0],PARAMETER[“false_northing”,0],UNIT[“metre”,1,AUTHORITY[“EPSG”,”9001”]],AXIS[“X”,EAST],AXIS[“Y”,NORTH],EXTENSION[“PROJ4”,”+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs”],AUTHORITY[“EPSG”,”3857”]

参见:

https://epsg.io/3857

小结:

web-mercator 投影坐标系是网络地图的投影坐标系,几乎所有的网络地图都使用这种投影,它的投影结果是正方形的,计算简单,切图方便

BD09MC 投影

BD09MC 是BD09 坐标系的web-mercator 投影坐标系

前文已经说过,GCJ02坐标系是WGS84坐标系的加密结果,GCJ02坐标系相对于WGS84坐标保证了投影后的线性单调性,所以GCJ02坐标系可以直接使用Web-Mercator投影,
但作为GCJ02 坐标系的二次加密结果BD09 坐标系没有做到投影后的线性单调性,为了保障投影后的线性单调性,百度地图基于web-mercator投影进行了修改,加入了常量矩阵,分区域对投影结果进行纠正

因为BD09坐标系采用极坐标加常量的方法进行偏移,所以BD09MC投影不是基于正球体的,而是椭球,其椭球赤道半径a=6378206m,极半径b=6356584.314245179m,数据覆盖范围与Web-Mercator投影一致。

BD09MC投影坐标系与Web-Mercator投影坐标系之间的转换可参见:

https://blog.csdn.net/sinat_41310868/article/details/113791826

地图底图瓦片栅格的转换,考虑到精度要求不需要太高,通常情况下,仅需进行瓦片中心点坐标的平移即可

小结

因为BD09坐标系是极坐标加常量加密,无法保证投影后的线性单调性,所以BD09MC 投影坐标系需要在BD09 坐标系进行web-mercator投影后,进行坐标纠正,因为精度不需要太高,地图瓦片的坐标纠正,仅需进行瓦片中心点坐标的平移即可

8 UTM投影

Universal Transverse Mercator,通用横轴墨卡托投影,是一种国际标准化的地图投影法,使用笛卡尔坐标系,标记南纬80°至北纬84°之间的所有位置,它的坐标基础是WGS84 坐标系,因为UTM 是一种分度带投影,所以不同经度区间的UTM 投影坐标系的EPSG 编码不同

UTM 采用网格编码,每个网格的编码经度在前,纬度在后

经度区间,每6° 被编排为一经度区间,每一个经度区间均以一个数字表示,由西向东数以01至60编排

纬度区间,从南纬80°开始,每8°被编排为一个纬度区间,而最北的纬度区间 (北纬74°以北) 则被延伸至84°,以覆盖世界上大部分陆地,每一个纬度区间均以一个英文字母表示,由南向北数以C至X 编排

具体情况如下图

在网格编码的基础上,某一点的UTM 坐标表示为该点所在的网格编码,加上该点由网格西南角起向北和向东的距离 细分网格数

坐标可由不同位数的数字组成,根据精度而定

如下图,假设在一个大网格 中,网格被不断以10*10的尺度被细分 第一次细分为100*100

A点的UTM细分坐标为17T 11 83,B点的UTM细分坐标为17T 106 827,C点的细分坐标为17T 1085 8255。

通常,一些自动驾驶项目采集的高精地图数据(点云、街景)是UTM投影坐标系的,某些网站上的卫星影响和自然资源数据,也使用UTM投影编码进行索引

小结

UTM 是通用横轴墨卡托投影,以细分网格的方式表示地球上的区间,一些高精地图数据使用的是UTM投影坐标系,某些网站上的卫星影像和自然资源数据,也是用UTM 投影编码进行索引

三、总结
地球是复杂的,表示地球的手段也是多样的,全球在用的坐标系与投影成千上万,以上仅仅是一些应用比较广的地图坐标系和投影,但这些坐标系和投影,已经涵盖了绝大多数地图的网络数据与应用。

20221224-HomeAssistant树莓派-NewAge篇

Apple homekit

ha 在加入了内置homekit 组件至此再也无需额外安装 homebridge 启用homekit 了,所以mossbian 镜像也下线了homebridge 的安装脚本

UI

HA 引入了新版的卡片ui,和之前同样的卡片样式相比,不得不说视觉美感上升了一个维度,看看这优美的线条和仪表盘

更令人心动的是,新版ui正式支持前台的即时修改生效,是的,yaml 的配置时代结束了

目前版本虽然依旧保留了原ui 的支持,但是默认新装环境ui 已经切换到如上的样式,进一步降低萌新们的入门门槛

配置

昔日一上来就要写yaml 的配置方式一直被萌新们深深诟病,ha team 也非常关切这个问题,引入了自动接入和配置机制,目前对海外的一些畅销设备如宜家的智能灯系列,谷歌和亚马逊的智能音箱 飞利浦彩灯等等都能做到前台的傻瓜式 操作接入,遗憾的是,国内常用的智能设备还不能做到无码接入
不过一次接入后,以往复杂的中文昵称,设置指定icon 等个性化配置在前台可以轻松完成

HA 降低门槛工作并不局限在设备接入环节,现在包括自动化、脚本等工作都可以在前台完成

用户体系

千呼万唤始出来 HA 终于有多用户体系了,满足大家一户多屏的需求

总结

0.8x 以后的HA 已经像模像样把它做出了一个商业paas 该有的模样,甚至不惜以部分代码重构的方式实现

20221224-HomeAssistant树莓派-远程安全访问

Home Assistant 本身为外网访问提供完整的 Let’s Encryption + Duck Dns 支持,
基于国内的网络环境,个人不太推荐,一是前者的加密需要每3个月进行更新,虽然有自动更新脚本和组件,但心里始终挂着一件事不舒服,二是国内网络运行商基本上封闭了80端口,后者直接ng

国内进行端口转发,内网穿透、端口映射甚至是公网ip 设置都障碍重重,所以很多外文教程并不适用于国内的网络环境

背景

80 端口封闭,443 端口开放,。
443 端口是https 的默认端口,映射之后访问不需要在域名后面添加端口号,适合强迫症使用,如果几个端口都封了的话,老实说,除了内网穿透,我也没有办法了

无内网穿透 目前内网穿透没有什么好的免费方法,要么使用花生壳 ,要么使用frps 但是你也得有个服务器

华硕路由器+改版梅林固件,选择koolshare 梅林固件主要是由 阿里云DDNS 插件,手动提交其实也是没有问题的,端口转发的话,基本上所有路由器固件都自带,无需担心

HA 加密且无摄像头接入,没有一个摄像头是安全的,而且犯罪成本低,犯罪收益相当大,你可以试想一下你的生活轨迹、家庭情况瞬间暴露在外。当然,室外监控和店铺使用的朋友可以忽略此项。

申请域名

首先登陆阿里云 进入域名购买界面,在国内购买 cn com 域名必须进行实名认证

这里选择万网的原因是方便接入去CA 证书的申请,一条龙服务舒心

申请证书

阿里云的云盾证书服务 对官人站提供免费的一年期CA 证书,一个账户可以申请5份免费证书

免费证书实际上是由 赛门铁克 颁发的,如果你使用万网的域名,只要在签发过程中选择自动认证即可,手动认证的方法也很简单,前往域名解析页添加一段txt 记录即可

证书签发后,我们就可以下载相关的证书了,如果你是使用ngix 或者apache 的话 按照指南下载调用即可,拿不准的话就选择其他下载,一般情况下可以下载到如下3个文件

xxxx.pem 公钥文件
xxxx.key 私钥文件
xxxx.chain 证书链文件

前2者必须有,后者可有可无,到这里我们的前期准备就基本完成了,接下来是一系列的路由器操作

DDNS

有了域名之后,我们就要将其解析到家中的公网ip ,才能实现外网访问,如背景中所述,目前大部分的家庭宽带用户只有动态的公网ip,而我们不可能每次都手动修改解析,因此需要DDNS 这一动态解析工具

从插件中心下载安装 ALIDDNS 插件

app key 和secret 从阿里云账户详情里面获取,检查时间可以设置地大一些,毕竟ip 更换得不是那么勤

设置完毕后你就可以通过这个域名访问该ip 下的服务了,如果你在路由器的 系统管理 中打开了从互联网 设置路由器的话,那么现在你就可以通过访问域名+端口号 进入路由器设置面板了

SSL 证书验证

华硕路由器自带的ai cloud 功能默认使用https 服务,并支持上传 证书,可以简便地帮助我们验证证书的有效性

当然最后的端口号是可以更改的。点击网址进入后,选择左下角的设定 - 证书 -汇入证书,依次上传下载的 3 个文件。之后保存退出,刷新网页,不出意外的话,你的地址左侧将会出现 绿钥匙图标。这说明你的证书是安全有效的。我们可以放心地将其用在 HA 中了。

端口转发

既然要做到外网访问,就必须把内网的服务映射到外网,在这里就是所谓的进行端口转发,我们的ha 使用的是默认端口 8123 ,我们前往 外部网络,端口转发,中添加如下规则

你可以将 通信端口范围,更改成其他外网访问的端口,443 是https 的默认访问端口

至此,所有的铺垫工作都完成了,我们正式将ha 映射到外网中

ha https

打开 configuration.yaml 文件,配置 http 项:

http:
api_password: !secret http_password //访问密码
trusted_networks: //免密登陆白名单,建议添加内网地址
- 127.0.0.1
- ::1
- 192.168.50.0/24
base_url: www.cxlwill.pub //访问地址,填入 DDNS 中设置的网址
ssl_certificate: /home/homeassistant/.homeassistant/cert.pem //公钥文件地址,注意放在有读取权限的文件夹
ssl_key: /home/homeassistant/.homeassistant/cert.key //私钥文件地址,注意放在有读取权限的文件夹
之后重启 HA,你会发现之前的 http://IP:8213 无法登陆了。请将访问地址更改为 https://域名:端口号,如果设置为 443 端口,则无需端口号。

现在你的ha 已经可以完美进行外网的登陆了,并且在浏览的地址栏左侧 你可以看到令人安心的绿钥匙图标

HB HADashboard 等相关服务

HA 进行全站https 后,千万记得更改相关服务的访问地址

HB 中的 config.json :

“platforms”: [
{
“platform”: “HomeAssistant”,
“name”: “HomeAssistant”,
“host”: “https://“, //修改为最新的域名,注意使用 https
•••
“verify_ssl”: false //建议使用 false
}
],
之后重启 HB,无响应的状况应该就消失了。

HADashboard 中的 Appdaemon.yaml:

HASS:
ha_url: https://xxx.com //这里也要更改为最新的地址
ha_key:

其他使用ha api 服务,例如ifttt 中的调用地址也需要进行即使更新,具体就不展开了

同样,iod app 中的访问地址也需要一并进行更改

后续注意事项

HA 全站 Https 之后,所有接入的服务都必须为 https,否则将会出现不安全的警示。请特别留意一些自定义组件的 API 和图标源,官方的组件一般情况下不会出现此类情况,RTSP 等协议不受影响

  • Copyrights © 2015-2024 TeX_baitu
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~